更新
This commit is contained in:
@@ -669,114 +669,81 @@
|
|||||||
$("#canselectItem").empty();
|
$("#canselectItem").empty();
|
||||||
let currentData = [], editLabel = "未定義區塊";
|
let currentData = [], editLabel = "未定義區塊";
|
||||||
|
|
||||||
// 🌟 1. 判斷是否為超薦牌位 (利用 item_type === 'B' 或是依據底圖名稱防呆)
|
let isChaojian = (this.item_type === 'B' || (typeof VueApp !== 'undefined' && VueApp.item_type === 'B') || (this.tabletItem && this.tabletItem.item_type === 'B')) ||
|
||||||
let isChaojian = false;
|
(this.allStyle.find(y => y.styleID == this.selectStyle)?.name || "").includes("超薦");
|
||||||
if (this.item_type === 'B' || (typeof VueApp !== 'undefined' && VueApp.item_type === 'B') || (this.tabletItem && this.tabletItem.item_type === 'B')) {
|
|
||||||
isChaojian = true;
|
|
||||||
} else {
|
|
||||||
let style = this.allStyle.find(y => y.styleID == this.selectStyle);
|
|
||||||
if (style && style.name && style.name.includes("超薦")) {
|
|
||||||
isChaojian = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 預設生死條件:超薦要死者(true),消災要活者(false)
|
|
||||||
let requireDeceased = isChaojian;
|
let requireDeceased = isChaojian;
|
||||||
|
|
||||||
// 🌟 2. 判斷當前編輯區塊
|
if (element.hasClass("liveList")) { editLabel = "陽上"; currentData = this.alive; requireDeceased = false; }
|
||||||
if (element.hasClass("liveList")) {
|
else if (element.hasClass("nameList") || element.hasClass("rosterList") || element.hasClass("ancestor-wrapper")) { editLabel = "正名"; currentData = this.properTitle; }
|
||||||
editLabel = "陽上";
|
else if (element.hasClass("lefttitle")) { editLabel = "左正名"; currentData = this.leftProperTitle; }
|
||||||
currentData = this.alive;
|
else if (element.hasClass("righttitle")) { editLabel = "右正名"; currentData = this.rightProperTitle; }
|
||||||
requireDeceased = false; // 🚨 陽上永遠只能選活者
|
else if (element.hasClass("address")) { editLabel = "地址"; currentData = this.address ? [this.address] : []; }
|
||||||
}
|
|
||||||
else if (element.hasClass("nameList") || element.hasClass("rosterList") || element.hasClass("ancestor-wrapper")) {
|
|
||||||
editLabel = "正名";
|
|
||||||
currentData = this.properTitle;
|
|
||||||
}
|
|
||||||
else if (element.hasClass("lefttitle")) {
|
|
||||||
editLabel = "左正名";
|
|
||||||
currentData = this.leftProperTitle;
|
|
||||||
}
|
|
||||||
else if (element.hasClass("righttitle")) {
|
|
||||||
editLabel = "右正名";
|
|
||||||
currentData = this.rightProperTitle;
|
|
||||||
}
|
|
||||||
else if (element.hasClass("address")) {
|
|
||||||
editLabel = "地址";
|
|
||||||
currentData = this.address ? [this.address] : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#current-edit-label").text("目前編輯:" + editLabel);
|
$("#current-edit-label").text("目前編輯:" + editLabel);
|
||||||
|
|
||||||
// 渲染已選
|
// 🌟 從物件中取出 fam_name 顯示
|
||||||
currentData.forEach((x, index) => {
|
currentData.forEach((item, index) => {
|
||||||
|
let displayName = typeof item === 'string' ? item : item.fam_name;
|
||||||
$("#selectedItem").append(`
|
$("#selectedItem").append(`
|
||||||
<li><span class="selected">${x}</span><div class="list-actions">
|
<li><span class="selected">${displayName}</span><div class="list-actions">
|
||||||
<button class="itemUp" data-idx="${index}">↑</button><button class="itemDown" data-idx="${index}">↓</button><button class="itemRemove" data-idx="${index}">-</button>
|
<button class="itemUp" data-idx="${index}">↑</button><button class="itemDown" data-idx="${index}">↓</button><button class="itemRemove" data-idx="${index}">-</button>
|
||||||
</div></li>`);
|
</div></li>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 地址不需要出現親友選單
|
if (element.hasClass("address")) { this.bindListEvents(); return; }
|
||||||
if (element.hasClass("address")) {
|
|
||||||
this.bindListEvents();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 🌟 3. 渲染可選 (嚴格過濾生死狀態)
|
// 🌟 從已選陣列取出名稱來做比對
|
||||||
|
let currentNames = currentData.map(x => typeof x === 'string' ? x : x.fam_name);
|
||||||
let filterKeyword = $('#filter_txt').val().trim() || "";
|
let filterKeyword = $('#filter_txt').val().trim() || "";
|
||||||
this.familyMembers.forEach(f => {
|
|
||||||
// 判斷該親友的生死狀態 (相容 boolean 與字串)
|
|
||||||
let isDead = (f.deceased === true || f.deceased === "true" || f.deceased === "True");
|
|
||||||
|
|
||||||
// 條件成立:生死符合要求 + 尚未加入 + 關鍵字相符
|
this.familyMembers.forEach(f => {
|
||||||
if (isDead === requireDeceased && !currentData.includes(f.fam_name) && f.fam_name.includes(filterKeyword)) {
|
let isDead = (f.deceased === true || f.deceased === "true" || f.deceased === "True");
|
||||||
|
if (isDead === requireDeceased && !currentNames.includes(f.fam_name) && f.fam_name.includes(filterKeyword)) {
|
||||||
$("#canselectItem").append(`
|
$("#canselectItem").append(`
|
||||||
<li>
|
<li><span style="opacity:0.5">卍</span> <span class="unselect">${f.fam_name}</span>
|
||||||
<span style="opacity:0.5">卍</span>
|
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${f.fam_title ? f.fam_title : ""}</i></span>
|
||||||
<span class="unselect">${f.fam_name}</span>
|
<span class='itemAppend' style="float:right;cursor:pointer;">+</span></li>`);
|
||||||
<span>
|
|
||||||
<i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">
|
|
||||||
${f.fam_title ? f.fam_title : ""}
|
|
||||||
</i>
|
|
||||||
</span>
|
|
||||||
<span class='itemAppend' style="float:right;cursor:pointer;">+</span>
|
|
||||||
</li>
|
|
||||||
`);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bindListEvents();
|
this.bindListEvents();
|
||||||
},
|
},
|
||||||
|
|
||||||
bindListEvents() {
|
bindListEvents() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
||||||
// 🌟 修正1:加上 .off() 解除舊綁定,防止「幽靈疊加點擊」!
|
|
||||||
// 否則您每點一次,它會因為 renderItemMenu 重新綁定,導致一次加好幾個名字甚至當掉
|
|
||||||
$("#canselectItem").off("click", ".itemAppend").on("click", ".itemAppend", function (e) {
|
$("#canselectItem").off("click", ".itemAppend").on("click", ".itemAppend", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
self.modifyDataAndRerender("add", $(this).siblings(".unselect").text());
|
let name = $(this).siblings(".unselect").text();
|
||||||
|
let fam = self.familyMembers.find(f => f.fam_name === name);
|
||||||
|
// 🌟 從親友名單帶入時,組裝成完整物件
|
||||||
|
let obj = {
|
||||||
|
IsShuWen: false, deceased: fam ? (fam.deceased === true || fam.deceased === "True") : false,
|
||||||
|
fam_gender: "", fam_name: name, fam_file: "", nospace: true, num: fam ? fam.num : 0, option_break: false
|
||||||
|
};
|
||||||
|
self.modifyDataAndRerender("add", obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#selectedItem").off("click", ".itemRemove").on("click", ".itemRemove", function (e) {
|
$("#selectedItem").off("click", ".itemRemove").on("click", ".itemRemove", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault(); self.modifyDataAndRerender("remove", $(this).data("idx"));
|
||||||
self.modifyDataAndRerender("remove", $(this).closest("li").find(".selected").text());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#selectedItem").off("click", ".itemUp").on("click", ".itemUp", function (e) {
|
$("#selectedItem").off("click", ".itemUp").on("click", ".itemUp", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault(); self.modifyDataAndRerender("up", $(this).data("idx"));
|
||||||
self.modifyDataAndRerender("up", $(this).data("idx"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#selectedItem").off("click", ".itemDown").on("click", ".itemDown", function (e) {
|
$("#selectedItem").off("click", ".itemDown").on("click", ".itemDown", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault(); self.modifyDataAndRerender("down", $(this).data("idx"));
|
||||||
self.modifyDataAndRerender("down", $(this).data("idx"));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#btn_add_custom').off("click").on('click', function (e) {
|
$('#btn_add_custom').off("click").on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault(); let val = $('#custom_txt').val().trim();
|
||||||
let val = $('#custom_txt').val().trim();
|
if (val) {
|
||||||
if (val) { self.modifyDataAndRerender("add", val); $('#custom_txt').val(''); }
|
// 🌟 手動輸入時,產生帶有 num: 0 的物件
|
||||||
|
let obj = {
|
||||||
|
IsShuWen: false, deceased: false, fam_gender: "",
|
||||||
|
fam_name: val, fam_file: "", nospace: true, num: 0, option_break: false
|
||||||
|
};
|
||||||
|
self.modifyDataAndRerender("add", obj);
|
||||||
|
$('#custom_txt').val('');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#filter_txt').off("keyup").on('keyup', () => {
|
$('#filter_txt').off("keyup").on('keyup', () => {
|
||||||
@@ -809,17 +776,17 @@
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
$('#btn_save').off('click').on('click', async function (e) {
|
$('#btn_save').off('click').on('click', async function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
//let tablet = {
|
let tablet = {
|
||||||
// mid_items: designer.family_deceased_N_selected,
|
mid_items: self.properTitle,
|
||||||
// left_items: designer.family_deceased_Y_selected,
|
left_items: self.alive,
|
||||||
// style: designer.selectStyle.style,
|
mid_left: self.leftProperTitle,
|
||||||
// mid_left: designer.family_left_title,
|
mid_right: self.rightProperTitle,
|
||||||
// mid_right: designer.family_right_title,
|
addr_items: self.address,
|
||||||
// addr_items: designer.family_address
|
style: self.selectStyle,
|
||||||
//}
|
}
|
||||||
let data = {
|
let data = {
|
||||||
num: 0, name: $("#template_name_txt").val(), follower_num: VueApp.follower_id,
|
num: 0, name: $("#template_name_txt").val(), follower_num: VueApp.follower_id,
|
||||||
style_id: $(".styleSelector").val(),tablet:"",shuwen:""
|
style_id: $(".styleSelector").val(), tablet: JSON.stringify(tablet), shuwen: ""
|
||||||
}
|
}
|
||||||
console.log("btn_save:", data);
|
console.log("btn_save:", data);
|
||||||
});
|
});
|
||||||
@@ -830,25 +797,29 @@
|
|||||||
let target = this.selectedElement.children().first(), targetArr = null;
|
let target = this.selectedElement.children().first(), targetArr = null;
|
||||||
|
|
||||||
if (target.hasClass("liveList")) targetArr = this.alive;
|
if (target.hasClass("liveList")) targetArr = this.alive;
|
||||||
else if (target.hasClass("nameList")) targetArr = this.properTitle;
|
else if (target.hasClass("nameList") || target.hasClass("rosterList") || target.hasClass("ancestor-wrapper")) targetArr = this.properTitle;
|
||||||
else if (target.hasClass("lefttitle")) targetArr = this.leftProperTitle;
|
else if (target.hasClass("lefttitle")) targetArr = this.leftProperTitle;
|
||||||
else if (target.hasClass("righttitle")) targetArr = this.rightProperTitle;
|
else if (target.hasClass("righttitle")) targetArr = this.rightProperTitle;
|
||||||
else if (target.hasClass("address")) {
|
else if (target.hasClass("address")) {
|
||||||
if (action === "add") this.address = payload; else if (action === "remove") this.address = "";
|
if (action === "add") this.address = typeof payload === 'string' ? payload : payload.fam_name;
|
||||||
targetArr = this.address ? [this.address] : [];
|
else if (action === "remove") this.address = "";
|
||||||
|
targetArr = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetArr) {
|
if (targetArr) {
|
||||||
if (action === "add" && !targetArr.includes(payload)) targetArr.push(payload);
|
if (action === "add") {
|
||||||
else if (action === "add" && targetArr.includes(payload)) { alert("名稱已存在!"); return; }
|
// 🌟 檢查是否已經存在 (比對物件的 fam_name)
|
||||||
else if (action === "remove") { let idx = targetArr.indexOf(payload); if (idx > -1) targetArr.splice(idx, 1); }
|
if (targetArr.some(x => x.fam_name === payload.fam_name)) { alert("名稱已存在!"); return; }
|
||||||
|
targetArr.push(payload);
|
||||||
|
}
|
||||||
|
else if (action === "remove") { targetArr.splice(payload, 1); } // 🌟 刪除改用 index
|
||||||
else if (action === "up" && payload > 0) [targetArr[payload - 1], targetArr[payload]] = [targetArr[payload], targetArr[payload - 1]];
|
else if (action === "up" && payload > 0) [targetArr[payload - 1], targetArr[payload]] = [targetArr[payload], targetArr[payload - 1]];
|
||||||
else if (action === "down" && payload < targetArr.length - 1) [targetArr[payload], targetArr[payload + 1]] = [targetArr[payload + 1], targetArr[payload]];
|
else if (action === "down" && payload < targetArr.length - 1) [targetArr[payload], targetArr[payload + 1]] = [targetArr[payload + 1], targetArr[payload]];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.renderItemMenu(target);
|
this.renderItemMenu(target);
|
||||||
this.rerenderPart();
|
this.rerenderPart();
|
||||||
this.renderEditorRight();
|
if (this.renderEditorRight) this.renderEditorRight();
|
||||||
},
|
},
|
||||||
|
|
||||||
rerenderPart() {
|
rerenderPart() {
|
||||||
@@ -873,15 +844,20 @@
|
|||||||
if (!d) return;
|
if (!d) return;
|
||||||
|
|
||||||
this.selectedElement.empty();
|
this.selectedElement.empty();
|
||||||
|
|
||||||
let html = "";
|
let html = "";
|
||||||
// 🌟 重新導向對應的排版引擎
|
|
||||||
if (target.hasClass("nameList")) html = this.buildNameList(this.properTitle, d);
|
// 🌟 在傳入排版引擎前,統一 map 成字串陣列
|
||||||
else if (target.hasClass("rosterList")) html = this.buildRosterList(this.properTitle, d);
|
let pTitleNames = this.properTitle.map(x => typeof x === 'string' ? x : x.fam_name);
|
||||||
else if (target.hasClass("ancestor-wrapper")) html = this.buildCombinedList(this.properTitle, d);
|
let aliveNames = this.alive.map(x => typeof x === 'string' ? x : x.fam_name);
|
||||||
else if (target.hasClass("liveList")) html = this.buildLiveList(this.alive, d);
|
let leftNames = this.leftProperTitle.map(x => typeof x === 'string' ? x : x.fam_name);
|
||||||
else if (target.hasClass("lefttitle")) html = this.buildNormalWithSpace(this.leftProperTitle, d, 'lefttitle');
|
let rightNames = this.rightProperTitle.map(x => typeof x === 'string' ? x : x.fam_name);
|
||||||
else if (target.hasClass("righttitle")) html = this.buildNormalWithSpace(this.rightProperTitle, d, 'righttitle');
|
|
||||||
|
if (target.hasClass("nameList")) html = this.buildNameList(pTitleNames, d);
|
||||||
|
else if (target.hasClass("rosterList")) html = this.buildRosterList(pTitleNames, d);
|
||||||
|
else if (target.hasClass("ancestor-wrapper")) html = this.buildCombinedList(pTitleNames, d);
|
||||||
|
else if (target.hasClass("liveList")) html = this.buildLiveList(aliveNames, d);
|
||||||
|
else if (target.hasClass("lefttitle")) html = this.buildNormalWithSpace(leftNames, d, 'lefttitle');
|
||||||
|
else if (target.hasClass("righttitle")) html = this.buildNormalWithSpace(rightNames, d, 'righttitle');
|
||||||
else if (target.hasClass("address")) html = `<div class='address' style='width:${d.width}px; height:${d.height}px; font-size:${d.fontSize}px; font-family:${d.fontFamily};'>${this.address}</div>`;
|
else if (target.hasClass("address")) html = `<div class='address' style='width:${d.width}px; height:${d.height}px; font-size:${d.fontSize}px; font-family:${d.fontFamily};'>${this.address}</div>`;
|
||||||
|
|
||||||
this.selectedElement.append(html);
|
this.selectedElement.append(html);
|
||||||
@@ -981,33 +957,21 @@
|
|||||||
renderEditorRight() {
|
renderEditorRight() {
|
||||||
let $editorRight = $('#editor-right');
|
let $editorRight = $('#editor-right');
|
||||||
$editorRight.empty();
|
$editorRight.empty();
|
||||||
|
|
||||||
// 1. 設定為直書模式,拔除 flex,恢復自然的區塊(Block)換行特性
|
|
||||||
$editorRight.css({
|
$editorRight.css({
|
||||||
"writing-mode": "vertical-rl",
|
"writing-mode": "vertical-rl", "text-orientation": "mixed", "padding": "20px", "display": "block"
|
||||||
"text-orientation": "mixed",
|
|
||||||
"padding": "20px",
|
|
||||||
"display": "block" // 🌟 關鍵:改用 block,讓每個子元素絕對獨佔一整行
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. 收集所有要同步的名單
|
// 🌟 同樣從物件萃取 fam_name
|
||||||
let syncNames = [
|
let syncNames = [
|
||||||
...this.properTitle,
|
...this.properTitle.map(x => x.fam_name),
|
||||||
...this.leftProperTitle,
|
...this.leftProperTitle.map(x => x.fam_name),
|
||||||
...this.rightProperTitle
|
...this.rightProperTitle.map(x => x.fam_name)
|
||||||
];
|
];
|
||||||
|
|
||||||
// 3. 渲染名單
|
|
||||||
syncNames.forEach(name => {
|
syncNames.forEach(name => {
|
||||||
let $div = $('<div></div>').css({
|
let $div = $('<div></div>').css({
|
||||||
"font-size": "16pt",
|
"font-size": "16pt", "font-family": "DFKai-sb", "line-height": "1.2", "letter-spacing": "2px", "white-space": "pre-line", "margin-left": "25px"
|
||||||
"font-family": "DFKai-sb",
|
|
||||||
"line-height": "1.2",
|
|
||||||
"letter-spacing": "2px",
|
|
||||||
"white-space": "pre-line",
|
|
||||||
"margin-left": "25px" // 🌟 設定行距 (在直書模式中,左邊就是下一行的位置)
|
|
||||||
}).text(name);
|
}).text(name);
|
||||||
|
|
||||||
$editorRight.append($div);
|
$editorRight.append($div);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user