diff --git a/apps/jingrow/frontend/src/core/features/form_builder/globals.js b/apps/jingrow/frontend/src/core/features/form_builder/globals.js
index df90736..61a70e7 100644
--- a/apps/jingrow/frontend/src/core/features/form_builder/globals.js
+++ b/apps/jingrow/frontend/src/core/features/form_builder/globals.js
@@ -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 = {
diff --git a/apps/jingrow/frontend/src/core/pagetype/default.vue b/apps/jingrow/frontend/src/core/pagetype/default.vue
index 75d66dd..f77d058 100644
--- a/apps/jingrow/frontend/src/core/pagetype/default.vue
+++ b/apps/jingrow/frontend/src/core/pagetype/default.vue
@@ -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'))
// 保存成功更新快照
diff --git a/apps/jingrow/frontend/src/core/pagetype/form/controls/HTML.vue b/apps/jingrow/frontend/src/core/pagetype/form/controls/HTML.vue
index cca946a..0f4478b 100644
--- a/apps/jingrow/frontend/src/core/pagetype/form/controls/HTML.vue
+++ b/apps/jingrow/frontend/src/core/pagetype/form/controls/HTML.vue
@@ -1,11 +1,14 @@