修复编辑pagetype字段后无法保存的问题
This commit is contained in:
parent
e529a35280
commit
50f99f64d9
@ -14,45 +14,53 @@ import TextControl from "./components/controls/TextControl.vue";
|
||||
import TextEditorControl from "./components/controls/TextEditorControl.vue";
|
||||
|
||||
export function registerGlobalComponents(app) {
|
||||
app.component("AttachControl", AttachControl)
|
||||
.component("AttachImageControl", AttachControl)
|
||||
.component("AutocompleteControl", DataControl)
|
||||
.component("BarcodeControl", DataControl)
|
||||
.component("ButtonControl", ButtonControl)
|
||||
.component("CheckControl", CheckControl)
|
||||
.component("CodeControl", CodeControl)
|
||||
.component("ColorControl", DataControl)
|
||||
.component("CurrencyControl", DataControl)
|
||||
.component("DataControl", DataControl)
|
||||
.component("DateControl", DataControl)
|
||||
.component("DatetimeControl", DataControl)
|
||||
.component("DurationControl", DataControl)
|
||||
.component("DynamicLinkControl", DataControl)
|
||||
.component("FloatControl", DataControl)
|
||||
.component("GeolocationControl", GeolocationControl)
|
||||
.component("HeadingControl", ButtonControl)
|
||||
.component("HTMLControl", DataControl)
|
||||
.component("HTMLEditorControl", CodeControl)
|
||||
.component("IconControl", DataControl)
|
||||
.component("ImageControl", ImageControl)
|
||||
.component("IntControl", DataControl)
|
||||
.component("JSONControl", CodeControl)
|
||||
.component("LinkControl", LinkControl)
|
||||
.component("LongTextControl", TextControl)
|
||||
.component("MarkdownEditorControl", CodeControl)
|
||||
.component("PasswordControl", DataControl)
|
||||
.component("PercentControl", DataControl)
|
||||
.component("PhoneControl", DataControl)
|
||||
.component("ReadOnlyControl", DataControl)
|
||||
.component("RatingControl", RatingControl)
|
||||
.component("SelectControl", SelectControl)
|
||||
.component("SignatureControl", SignatureControl)
|
||||
.component("SmallTextControl", TextControl)
|
||||
.component("TableControl", TableControl)
|
||||
.component("TableMultiSelectControl", DataControl)
|
||||
.component("TextControl", TextControl)
|
||||
.component("TextEditorControl", TextEditorControl)
|
||||
.component("TimeControl", DataControl);
|
||||
// Helper function to safely register component
|
||||
const safeRegister = (name, component) => {
|
||||
if (!app.component(name)) {
|
||||
app.component(name, component);
|
||||
}
|
||||
return app;
|
||||
};
|
||||
|
||||
safeRegister("AttachControl", AttachControl);
|
||||
safeRegister("AttachImageControl", AttachControl);
|
||||
safeRegister("AutocompleteControl", DataControl);
|
||||
safeRegister("BarcodeControl", DataControl);
|
||||
safeRegister("ButtonControl", ButtonControl);
|
||||
safeRegister("CheckControl", CheckControl);
|
||||
safeRegister("CodeControl", CodeControl);
|
||||
safeRegister("ColorControl", DataControl);
|
||||
safeRegister("CurrencyControl", DataControl);
|
||||
safeRegister("DataControl", DataControl);
|
||||
safeRegister("DateControl", DataControl);
|
||||
safeRegister("DatetimeControl", DataControl);
|
||||
safeRegister("DurationControl", DataControl);
|
||||
safeRegister("DynamicLinkControl", DataControl);
|
||||
safeRegister("FloatControl", DataControl);
|
||||
safeRegister("GeolocationControl", GeolocationControl);
|
||||
safeRegister("HeadingControl", ButtonControl);
|
||||
safeRegister("HTMLControl", DataControl);
|
||||
safeRegister("HTMLEditorControl", CodeControl);
|
||||
safeRegister("IconControl", DataControl);
|
||||
safeRegister("ImageControl", ImageControl);
|
||||
safeRegister("IntControl", DataControl);
|
||||
safeRegister("JSONControl", CodeControl);
|
||||
safeRegister("LinkControl", LinkControl);
|
||||
safeRegister("LongTextControl", TextControl);
|
||||
safeRegister("MarkdownEditorControl", CodeControl);
|
||||
safeRegister("PasswordControl", DataControl);
|
||||
safeRegister("PercentControl", DataControl);
|
||||
safeRegister("PhoneControl", DataControl);
|
||||
safeRegister("ReadOnlyControl", 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 = {
|
||||
|
||||
@ -986,6 +986,12 @@ async function loadDetail() {
|
||||
|
||||
// 保存
|
||||
async function handleSave() {
|
||||
// 触发自定义事件,通知所有 FormBuilder 同步 fields
|
||||
window.dispatchEvent(new CustomEvent('sync-form-builder-fields'))
|
||||
|
||||
// 等待一帧,确保 fields 已同步
|
||||
await new Promise(resolve => requestAnimationFrame(resolve))
|
||||
|
||||
// 脏检查:无改动则不保存
|
||||
try {
|
||||
if (JSON.stringify(record.value) === JSON.stringify(originalRecord.value)) {
|
||||
@ -1026,7 +1032,17 @@ async function handleSave() {
|
||||
}, 1500)
|
||||
}
|
||||
} 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) {
|
||||
message.success(t('Saved successfully'))
|
||||
// 保存成功更新快照
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
<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 { useMessage } from 'naive-ui'
|
||||
|
||||
const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>()
|
||||
const message = useMessage()
|
||||
|
||||
// FormBuilder ref
|
||||
const formBuilderRef = ref<InstanceType<typeof FormBuilderComponent> | null>(null)
|
||||
|
||||
// Label布局:上下结构(vertical) 或 左右结构(horizontal)
|
||||
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
|
||||
function handleFieldsUpdate(newFields: any[]) {
|
||||
if (props.canEdit && isFormBuilder.value) {
|
||||
@ -55,14 +94,21 @@ function handleSave(newFields: any[]) {
|
||||
|
||||
// Handle dirty state change
|
||||
function handleDirtyChange(isDirty: boolean) {
|
||||
// Form builder dirty state changed
|
||||
// 不在这里同步 fields,避免触发组件重新渲染导致输入失焦
|
||||
// fields 只在保存时同步
|
||||
}
|
||||
|
||||
// Expose methods to parent
|
||||
defineExpose({
|
||||
getLatestFields
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 如果是form_builder字段,渲染Form Builder组件 -->
|
||||
<div v-if="isFormBuilder" class="form-builder-field">
|
||||
<FormBuilderComponent
|
||||
ref="formBuilderRef"
|
||||
:fields="fields"
|
||||
:pagetype="pagetypeName"
|
||||
:pagetype-record="record"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user