This commit is contained in:
2026-05-17 22:44:11 +08:00
parent 0380c01a27
commit 18fc9849a3
5 changed files with 203 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
/**
* my-editor.js — VvvebJS 儲存橋接腳本
* 覆蓋 vvvebjs 的 saveAjax 行為,附加 project slug 後送至 Flask /api/save
* my-editor.js — VvvebJS 儲存與新增頁面橋接腳本
* 覆蓋 Vvveb.Builder.saveAjax 行為,使儲存與新增頁面功能無縫串接至 Flask 後端
*/
(function () {
"use strict";
@@ -49,7 +49,7 @@
}, 3000);
}
// ── 覆蓋 saveAjax ───────────────────────────────────────────────
// ── 覆蓋 Vvveb.Builder.saveAjax ──────────────────────────────────
function patchSaveAjax() {
if (typeof Vvveb === "undefined" || !Vvveb.Builder) {
// 等待 Vvveb 載入
@@ -57,82 +57,94 @@
return;
}
const originalSaveAjax = Vvveb.Builder.saveAjax
? Vvveb.Builder.saveAjax.bind(Vvveb.Builder)
: null;
Vvveb.Builder.saveAjax = function (saveUrl) {
/**
* VvvebJS 原始簽名: saveAjax(data, saveUrl, callback, error)
*/
Vvveb.Builder.saveAjax = function (data, saveUrl, callback, error) {
if (!SLUG) {
showToast("錯誤:找不到專案識別碼 (slug)", "error");
if (error) error(new Error("Missing slug"));
return;
}
// 取得目前編輯的頁面檔名
const currentPage = Vvveb.FileManager
? Vvveb.FileManager.getCurrentPage
? Vvveb.FileManager.getCurrentPage()
: null
: null;
// 確保 data 為物件並填入專案識別碼
if (typeof data !== "object" || data === null) {
data = {};
}
data.slug = SLUG;
let filename = "index.html";
if (currentPage && currentPage.filename) {
filename = currentPage.filename;
} else if (currentPage && currentPage.file) {
// 只取檔名部分
filename = currentPage.file.split("/").pop();
// 扁平化處理新檔案檔名(確保所有頁面皆存於專案根目錄下)
if (data.file) {
const parts = data.file.split("/");
data.file = parts[parts.length - 1];
}
// 取得 HTML 內容
let html = "";
try {
html = Vvveb.Builder.getHtml ? Vvveb.Builder.getHtml() : "";
} catch (e) {
console.error("[my-editor] getHtml failed:", e);
// 如果不是新增頁面(即一般的儲存頁面),且未帶有 HTML 內容,則動態獲取目前 HTML
const isNewPage = !!data.startTemplateUrl;
if (!isNewPage && !data.html) {
try {
data.html = Vvveb.Builder.getHtml ? Vvveb.Builder.getHtml() : "";
} catch (e) {
console.error("[my-editor] getHtml failed:", e);
}
}
if (!html) {
showToast("無法取得頁面內容", "error");
return;
}
// 顯示儲存中狀態
// 顯示儲存中狀態(一般儲存時觸發)
const saveBtn = document.querySelector(".save-btn");
if (saveBtn) {
if (saveBtn && !isNewPage) {
saveBtn.querySelector(".loading")?.classList.remove("d-none");
saveBtn.querySelector(".button-text")?.classList.add("d-none");
}
const body = new URLSearchParams({
slug: SLUG,
file: filename,
html: html,
});
// 發送 POST 請求至 Flask API
fetch("/api/save", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: body.toString(),
body: new URLSearchParams(data).toString(),
})
.then((res) => res.json())
.then((data) => {
if (data.ok) {
showToast("✓ 已儲存:" + (data.saved || filename));
.then((res) => {
if (!res.ok) {
return res.json().then((errData) => {
throw new Error(errData.error || "伺服器儲存錯誤");
});
}
return res.json();
})
.then((resData) => {
if (isNewPage) {
// 新增頁面成功:秀出通知並執行 Vvveb 原生 callback 以載入新頁面
showToast("✓ 成功建立新頁面:" + resData.file);
if (callback) {
callback({
name: resData.name,
title: resData.title,
file: resData.file,
url: resData.url
});
}
} else {
showToast("儲存失敗:" + (data.error || "未知錯誤"), "error");
// 一般儲存成功
showToast("✓ 已儲存:" + (resData.saved || data.file));
if (callback) callback(resData);
// 停用儲存按鈕(直至下一次變更)
document.querySelectorAll("#top-panel .save-btn").forEach((e) =>
e.setAttribute("disabled", "true")
);
}
})
.catch((err) => {
showToast("網路錯誤" + err.message, "error");
showToast("儲存失敗" + err.message, "error");
if (error) error(err);
})
.finally(() => {
if (saveBtn) {
if (saveBtn && !isNewPage) {
saveBtn.querySelector(".loading")?.classList.add("d-none");
saveBtn.querySelector(".button-text")?.classList.remove("d-none");
}
});
};
console.log("[my-editor] saveAjax patched for slug:", SLUG);
console.log("[my-editor] Robust Vvveb.Builder.saveAjax patched for slug:", SLUG);
}
// ── 啟用 Save 按鈕vvvebjs 預設 disabled──────────────────────
@@ -150,7 +162,13 @@
if ((e.ctrlKey || e.metaKey) && e.key === "s") {
e.preventDefault();
if (typeof Vvveb !== "undefined" && Vvveb.Builder && Vvveb.Builder.saveAjax) {
Vvveb.Builder.saveAjax("/api/save");
// 觸發原生儲存按鈕的 click
const btn = document.querySelector(".save-btn");
if (btn) {
btn.click();
} else {
Vvveb.Builder.saveAjax({});
}
}
}
});