修正快速報名

This commit is contained in:
2026-09-09 16:51:48 +08:00
parent 52a10420ae
commit fa0ab417e1
6 changed files with 723 additions and 244 deletions
+545 -179
View File
@@ -1593,6 +1593,7 @@ html, body, * {
//})
//return $namelist;
},*/
renderNameList(names, el) {
let h = Number(el.height);
let w = Number(el.width);
@@ -1614,16 +1615,23 @@ html, body, * {
names = names[0].split("暨");
names[0] = names[0] + "暨";
}
const init_fontSize = Number(d.fontSize) > 40 ? 40 : Number(d.fontSize);
const init_fontSize = Number(el.style.fontSize) > 40 ? 40 : Number(el.style.fontSize);
// 1. 初始判定與特例條件計算
let items = names.map(name => {
let l = name.length;
let isShort = (l * init_fontSize) <= (th + (v_gap / 2));
// 應該用初始最大值而不是40
let isShort = (l * 40) <= (th + (v_gap / 2));
return { name: name, l: l, isShort: isShort, isMulti: false, size: 0 };
});
let maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1);
let allShort = items.every(x => x.isShort);
console.log("全短名:", items, allShort);
// 🚀 動態防呆:不寫死字數!用「實際字體大小」計算是否放得進半高。
// 這樣 13 個字會自動出局,而 3 個字的小牌位絕對能穩穩過關。
let fitsInHalf = items.every(x => (x.l * short_s * 1.333) <= (h / 2));
let isSpecial1 = allShort && fitsInHalf && items.length === 1;
@@ -1650,12 +1658,16 @@ html, body, * {
if (item.isShort) {
let item_h = Math.max(th, maxShortLen * size_px);
// 壓縮高度釋放空間 (支援反向放大字體)
if (isSpecial) {
if (isSpecial1 || isSpecial2) item_h = h / 2;
if (isSpecial4) item_h = (h / 2) - (v_gap / 2);
} else {
let natural_h = maxShortLen * size_px;
if (item_h > natural_h * 1.5) item_h = natural_h * 1.5;
if (item_h > natural_h * 1.5) {
item_h = natural_h * 1.5;
}
}
if (current_col_h === 0) {
@@ -1675,10 +1687,13 @@ html, body, * {
current_col_h = 0;
current_col_w = 0;
}
let item_w = size_px;
if ((item.l * size_px) > (h - 10)) {
item.isMulti = true;
any_wrapped = true;
let chars_per_col = Math.floor((h - 10) / size_px);
if (chars_per_col < 1) chars_per_col = 1;
let item_cols = Math.ceil(item.l / chars_per_col);
@@ -1686,26 +1701,20 @@ html, body, * {
} else {
item.isMulti = false;
}
cols_width.push(item_w);
}
}
if (current_col_h > 0) cols_width.push(current_col_w);
totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) {
sizes = items.map(x => {
let final_s = x.size;
if (x.isShort) {
//let max_s_for_th = Math.floor(th / (maxShortLen * 1.333));
//if (final_s > max_s_for_th) final_s = max_s_for_th;
let available_h = th;
if (isSpecial) {
if (isSpecial1 || isSpecial2) available_h = h / 2;
if (isSpecial4) available_h = (h / 2) - v_gap - 2;
}
let max_s_for_th = Math.floor(available_h / (maxShortLen * 1.333));
let max_s_for_th = Math.floor(th / (maxShortLen * 1.333));
if (final_s > max_s_for_th) {
final_s = max_s_for_th;
}
@@ -1717,6 +1726,7 @@ html, body, * {
let hasLong = items.some(x => !x.isShort);
let hasShort = items.some(x => x.isShort);
if (hasLong && hasShort) {
if (shrink_turn === 'long') {
if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
@@ -1737,13 +1747,18 @@ html, body, * {
}
if (sizes.length === 0) {
sizes = names.map(name => ({ name: name, size: shrinkLimit, isMulti: false, isShort: true }));
sizes = names.map(name => {
return { name: name, size: shrinkLimit, isMulti: false, isShort: true };
});
}
// 3. 建立外層 Flexbox 容器
let flexDir = isSpecial2 ? "column" : "row";
let flexJustify = isSpecial ? "center" : "flex-start";
let flexAlign = "center";
//if (isSpecial4) v_gap = Number(h) / 4;
if (isSpecial4) {
v_gap = Number(h) / 4;
}
let $namelist = $(`<div class='nameList'></div>`).css({
"writing-mode": "vertical-rl",
@@ -1759,39 +1774,52 @@ html, body, * {
border: "0px solid transparent",
padding: "1px",
"column-gap": `${v_gap}px`,
"font-family": el.style.fontFamily
"font-family": el.style.fontFamily || el.fontFamily
});
// 4. 渲染單一名稱
sizes.forEach(item => {
let size_px = item.size * 1.333;
// 🚀 關鍵修正:統一使用 maxShortLen 算出標準高度,保證所有短名字的「格子」一模一樣大!
let natural_max_h = maxShortLen * size_px;
let boxH_num = item.isShort ? Math.max(th, natural_max_h) : h;
if (isSpecial) {
if (isSpecial1 || isSpecial2) boxH_num = h / 2;
if (isSpecial4) boxH_num = (h / 2) - v_gap - 2;
if (isSpecial4) boxH_num = (h / 2) - (v_gap) - 2;
} else if (item.isShort) {
if (boxH_num > natural_max_h * 1.5) boxH_num = natural_max_h * 1.5;
// 壓縮高度釋放空間時,同樣以統一的標準高度來判定
if (boxH_num > natural_max_h * 1.5) {
boxH_num = natural_max_h * 1.5;
}
}
let minH = `${boxH_num}px`;
let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
let spanDisplay = "block";
let spanJustifyContent = "flex-start";
let spanMarginTop = "0px";
if (isSpecial1 || isSpecial2) spanMarginTop = `-${h / 4}px`;
// 🚀 新增:只針對單一短名賦予 1/4 的 margin-top
let spanMarginTop = "0px";
if (isSpecial1 || isSpecial2) {
spanMarginTop = `-${h / 4}px`;
}
if (isSpecial1 || isSpecial2 || isSpecial4) {
alignStyle = "justify";
spanJustifyContent = "space-between";
}
// 這裡依然保留各自的真實字數,只用來計算「字距」,不影響格子大小
let nameLen = item.name.length;
let contentH = nameLen * size_px;
let emptySpace = boxH_num - contentH;
let gapsCount = nameLen > 1 ? (nameLen - 1) : 1;
let avgGap = emptySpace / gapsCount;
// 防過度拉扯 (排除特例,保護單名/雙名的正常分散)
if (!isSpecial && alignStyle === "justify" && avgGap > (size_px * 1.5)) {
alignStyle = "justify";
spanDisplay = "block";
@@ -1813,63 +1841,124 @@ html, body, * {
"text-justify": "inter-character",
"word-break": "break-all"
});
$namelist.append($span);
});
return $namelist;
},
renderLiveList(names, el) {
let h = parseFloat(el.height);
let w = parseFloat(el.width);
let th = parseFloat(el.textHeight) || h;
let v_gap = parseFloat(el.textSpan) || 0;
let h_gap = 5;
let shrinkLimit = 4;
if (Number(el.height) < 300) shrinkLimit = 8;
else if (Number(el.height) < 500) shrinkLimit = 6;
let s = parseFloat(el.style.fontSize);
if (names.length == 2) h = th + v_gap;
let maxLen = Math.max(...names.map(x => x.length), 1);
while (s >= shrinkLimit) {
let size_px = s * 1.333;
let current_col_h = 0;
let current_col_w = 0;
let cols_width = [];
let any_wrapped = false;
for (let i = 0; i < names.length; i++) {
let l = names[i].length;
let natural_max_h = maxLen * size_px;
let item_h = Math.max(th, natural_max_h);
if (item_h > natural_max_h * 1.5) item_h = natural_max_h * 1.5;
if (item_h > (h - 5)) {
any_wrapped = true;
if (current_col_h > 0) {
cols_width.push(current_col_w);
current_col_h = 0;
current_col_w = 0;
}
let chars_per_col = Math.floor((h - 5) / size_px);
if (chars_per_col < 1) chars_per_col = 1;
let item_cols = Math.ceil(l / chars_per_col);
cols_width.push(item_cols * (size_px * 1.1));
} else {
if (current_col_h === 0) {
current_col_h = item_h;
current_col_w = size_px;
} else if (current_col_h + v_gap + item_h <= h) {
current_col_h += v_gap + item_h;
if (size_px > current_col_w) current_col_w = size_px;
} else {
cols_width.push(current_col_w);
current_col_h = item_h;
current_col_w = size_px;
}
}
}
if (current_col_h > 0) cols_width.push(current_col_w);
let totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
if (totalWidth <= w && (!any_wrapped || s === shrinkLimit)) break;
s -= 1;
}
if (s < shrinkLimit) s = shrinkLimit;
let $namelist = $(`<div class='liveList'></div>`).css({
"writing-mode": "vertical-rl",
"display": "flex",
"flex-flow": "wrap",
"align-content": "center",
"align-items": "center",
"margin": "auto",
"width": `${w}px`,
"height": `${h}px`,
"border": "0px solid transparent",
"padding": "0px",
"font-family": el.style.fontFamily,
"column-gap": `${v_gap}px`
});
let self = this;
names.forEach(name => {
$namelist.append(self.renderLiveSpan(name, el, s, maxLen));
});
return $namelist;
},
renderNameSpan(item, el, colWidth) {
let th = Number(el.textHeight) || Number(el.height)
//let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
let minH = item.isShort ? `${th}px` : `${el.height}px`
;
let alignStyle = item.isMulti ? "start" : "justify";
renderLiveSpan(name, el, fontSize, maxLen = 1) {
let h = parseFloat(el.height);
let th = parseFloat(el.textHeight) || h;
let size_px = fontSize * 1.333;
return $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
display: "block",
"min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
"max-height": `${el.height}px`,
width: "auto",
"line-height": "1.1",
"text-align": alignStyle,
"text-align-last": alignStyle,
"margin-left": "5px",
let natural_max_h = maxLen * size_px;
let boxH_num = Math.max(th, natural_max_h);
if (boxH_num > natural_max_h * 1.5) {
boxH_num = natural_max_h * 1.5;
}
let minH = `${boxH_num}px`;
return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
"display": "block",
"min-height": minH,
"max-height": `${h}px`,
"width": "auto",
"text-align": "justify",
"text-align-last": "justify",
"margin-left": "0px",
"margin-top": "0px",
"text-justify": "inter-character",
"word-break": "break-all"
"word-break": "break-all",
"white-space": "pre-line"
});
//// 為「這個名字」獨立計算出專屬的最完美字體大小
//let indSize = this.calcIndividualFontSize(name, el, colWidth);
//// 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
//let s_px = indSize * 1.333;
//let isMultiLine = (name.length * s_px) > Number(el.textHeight);
//// 3. 根據是否折行動態決定對齊方式
//// 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start)
//let alignStyle = isMultiLine ? "start" : "justify";
//return $(`<span style="font-size: ${indSize}pt;">${name}</span>`).css({
// display: "block",
// "min-height": `${el.textHeight}px`,
// "max-height": `${el.height}px`,
// width: "auto",
// "line-height": "1.1",
// "text-align": alignStyle, // ★ 動態套用對齊方式
// "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
// "margin-left": "5px",
// "text-justify": "inter-character",
// "word-break": "break-all"
//});
//return $(`<span>${name}</span>`).css({
// display: "block",
// "min-height": `${el.textHeight}px`,
// "max-height": `${el.height}px`,
// width: `${rowWidth}px`,
// "text-align": "justify",
// "text-align-last": "justify",
// "margin-left": "5px",
// "text-justify": "inter-character",
//});// "margin-bottom": `${el.textSpan}px`,
},
/* renderLiveList(names, el) {
//console.log("renderLiveList:", names);
//$("#imp-text").updateActive("text",names)
@@ -1997,130 +2086,407 @@ html, body, * {
// "text-justify": "inter-character",
//});//"margin-bottom": `${el.textSpan}px`,
},*/
renderLiveList(names, el) {
let h = parseFloat(el.height);
let w = parseFloat(el.width);
let th = parseFloat(el.textHeight) || h;
let v_gap = parseFloat(el.textSpan) || 0;
let h_gap = 5;
let shrinkLimit = 4;
if (Number(el.height) < 300) shrinkLimit = 8;
else if (Number(el.height) < 500) shrinkLimit = 6;
//renderNameList(names, el) {
// let h = Number(el.height);
// let w = Number(el.width);
// let th = Number(el.textHeight) || h;
// let v_gap = Number(el.textSpan) || 0;
// let h_gap = 5;
// let shrinkLimit = 6;
let s = parseFloat(el.style.fontSize);
if (names.length == 2) h = th + v_gap;
// if (h < 500) {
// shrinkLimit = 8;
// } else if (h < 300) {
// shrinkLimit = 12;
// }
let maxLen = Math.max(...names.map(x => x.length), 1);
// let long_s = Number(el.style.fontSize);
// let short_s = Number(el.style.fontSize);
while (s >= shrinkLimit) {
let size_px = s * 1.333;
let current_col_h = 0;
let current_col_w = 0;
let cols_width = [];
let any_wrapped = false;
// if (h < 500 && names.length == 1 && names[0].includes("暨無始劫以來累世冤親債主")) {
// names = names[0].split("暨");
// names[0] = names[0] + "暨";
// }
// const init_fontSize = Number(el.fontSize) > 40 ? 40 : Number(el.fontSize);
// // 1. 初始判定與特例條件計算
// let items = names.map(name => {
// let l = name.length;
// let isShort = (l * init_fontSize) <= (th + (v_gap / 2));
// return { name: name, l: l, isShort: isShort, isMulti: false, size: 0 };
// });
for (let i = 0; i < names.length; i++) {
let l = names[i].length;
let natural_max_h = maxLen * size_px;
let item_h = Math.max(th, natural_max_h);
if (item_h > natural_max_h * 1.5) item_h = natural_max_h * 1.5;
// let maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1);
// let allShort = items.every(x => x.isShort);
// let fitsInHalf = items.every(x => (x.l * short_s * 1.333) <= (h / 2));
if (item_h > (h - 5)) {
any_wrapped = true;
if (current_col_h > 0) {
cols_width.push(current_col_w);
current_col_h = 0;
current_col_w = 0;
}
let chars_per_col = Math.floor((h - 5) / size_px);
if (chars_per_col < 1) chars_per_col = 1;
let item_cols = Math.ceil(l / chars_per_col);
cols_width.push(item_cols * (size_px * 1.1));
} else {
if (current_col_h === 0) {
current_col_h = item_h;
current_col_w = size_px;
} else if (current_col_h + v_gap + item_h <= h) {
current_col_h += v_gap + item_h;
if (size_px > current_col_w) current_col_w = size_px;
} else {
cols_width.push(current_col_w);
current_col_h = item_h;
current_col_w = size_px;
}
}
}
if (current_col_h > 0) cols_width.push(current_col_w);
let totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
if (totalWidth <= w && (!any_wrapped || s === shrinkLimit)) break;
s -= 1;
}
// let isSpecial1 = allShort && fitsInHalf && items.length === 1;
// let isSpecial2 = allShort && fitsInHalf && items.length === 2;
// let isSpecial4 = allShort && fitsInHalf && (items.length === 4 || items.length === 6 || items.length === 8);
// let isSpecial = isSpecial1 || isSpecial2 || isSpecial4;
if (s < shrinkLimit) s = shrinkLimit;
// let sizes = [];
// let shrink_turn = 'long';
let $namelist = $(`<div class='liveList'></div>`).css({
"writing-mode": "vertical-rl",
"display": "flex",
"flex-flow": "wrap",
"align-content": "center",
"align-items": "center",
"margin": "auto",
"width": `${w}px`,
"height": `${h}px`,
"border": "0px solid transparent",
"padding": "0px",
"font-family": el.style.fontFamily,
"column-gap": `${v_gap}px`
});
// // 2. 模擬排版與字體縮放運算
// while (true) {
// let totalWidth = 0;
// let current_col_h = 0;
// let current_col_w = 0;
// let cols_width = [];
// let any_wrapped = false;
let self = this;
names.forEach(name => {
$namelist.append(self.renderLiveSpan(name, el, s, maxLen));
});
return $namelist;
},
renderLiveSpan(name, el, fontSize, maxLen = 1) {
let h = parseFloat(el.height);
let th = parseFloat(el.textHeight) || h;
let size_px = fontSize * 1.333;
let l = name.length;
// for (let i = 0; i < items.length; i++) {
// let item = items[i];
// let s = item.isShort ? short_s : long_s;
// item.size = s;
// let size_px = s * 1.333;
let natural_max_h = maxLen * size_px;
let boxH_num = Math.max(th, natural_max_h);
if (boxH_num > natural_max_h * 1.5) boxH_num = natural_max_h * 1.5;
// if (item.isShort) {
// let item_h = Math.max(th, maxShortLen * size_px);
// if (isSpecial) {
// if (isSpecial1 || isSpecial2) item_h = h / 2;
// if (isSpecial4) item_h = (h / 2) - (v_gap / 2);
// } else {
// let natural_h = maxShortLen * size_px;
// if (item_h > natural_h * 1.5) item_h = natural_h * 1.5;
// }
let minH = `${boxH_num}px`;
let alignStyle = "justify";
let spanDisplay = "block";
let spanJustifyContent = "flex-start";
// if (current_col_h === 0) {
// current_col_h = item_h;
// current_col_w = size_px;
// } else if ((current_col_h + v_gap + item_h) <= h) {
// current_col_h += (v_gap + item_h);
// if (size_px > current_col_w) current_col_w = size_px;
// } else {
// cols_width.push(current_col_w);
// current_col_h = item_h;
// current_col_w = size_px;
// }
// } else {
// if (current_col_h > 0) {
// cols_width.push(current_col_w);
// current_col_h = 0;
// current_col_w = 0;
// }
// let item_w = size_px;
// if ((item.l * size_px) > (h - 10)) {
// item.isMulti = true;
// any_wrapped = true;
// let chars_per_col = Math.floor((h - 10) / size_px);
// if (chars_per_col < 1) chars_per_col = 1;
// let item_cols = Math.ceil(item.l / chars_per_col);
// item_w = item_cols * (size_px * 1.1);
// } else {
// item.isMulti = false;
// }
// cols_width.push(item_w);
// }
// }
let contentH = l * size_px;
let emptySpace = boxH_num - contentH;
let gapsCount = l > 1 ? (l - 1) : 1;
let avgGap = emptySpace / gapsCount;
// if (current_col_h > 0) cols_width.push(current_col_w);
// totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
alignStyle = "justify";
spanDisplay = "block";
spanJustifyContent = "space-between";
}
// if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) {
// sizes = items.map(x => {
// let final_s = x.size;
// if (x.isShort) {
// //let max_s_for_th = Math.floor(th / (maxShortLen * 1.333));
// //if (final_s > max_s_for_th) final_s = max_s_for_th;
// let available_h = th;
// if (isSpecial) {
// if (isSpecial1 || isSpecial2) available_h = h / 2;
// if (isSpecial4) available_h = (h / 2) - v_gap - 2;
// }
// let max_s_for_th = Math.floor(available_h / (maxShortLen * 1.333));
return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
"display": spanDisplay,
"justify-content": spanJustifyContent,
"align-items": "center",
"min-height": minH,
"max-height": `${h}px`,
"width": "auto",
"text-align": alignStyle,
"text-align-last": alignStyle,
"margin-left": "0px",
"margin-top": "0px",
"text-justify": "inter-character",
"word-break": "break-all",
"white-space": "pre-line"
});
},
// if (final_s > max_s_for_th) {
// final_s = max_s_for_th;
// }
// }
// return { name: x.name, size: final_s, isMulti: x.isMulti, isShort: x.isShort };
// });
// break;
// }
// let hasLong = items.some(x => !x.isShort);
// let hasShort = items.some(x => x.isShort);
// if (hasLong && hasShort) {
// if (shrink_turn === 'long') {
// if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
// else if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
// else break;
// } else {
// if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
// else if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
// else break;
// }
// } else if (hasLong) {
// if (long_s > shrinkLimit) long_s--;
// else break;
// } else {
// if (short_s > shrinkLimit) short_s--;
// else break;
// }
// }
// if (sizes.length === 0) {
// sizes = names.map(name => ({ name: name, size: shrinkLimit, isMulti: false, isShort: true }));
// }
// let flexDir = isSpecial2 ? "column" : "row";
// let flexJustify = isSpecial ? "center" : "flex-start";
// let flexAlign = "center";
// //if (isSpecial4) v_gap = Number(h) / 4;
// let $namelist = $(`<div class='nameList'></div>`).css({
// "writing-mode": "vertical-rl",
// display: "flex",
// "flex-direction": flexDir,
// "flex-wrap": "wrap",
// "align-content": "center",
// "align-items": flexAlign,
// "justify-content": flexJustify,
// margin: "auto",
// width: `${w}px`,
// height: `${h}px`,
// border: "0px solid transparent",
// padding: "1px",
// "column-gap": `${v_gap}px`,
// "font-family": el.style.fontFamily
// });
// sizes.forEach(item => {
// let size_px = item.size * 1.333;
// let natural_max_h = maxShortLen * size_px;
// let boxH_num = item.isShort ? Math.max(th, natural_max_h) : h;
// if (isSpecial) {
// if (isSpecial1 || isSpecial2) boxH_num = h / 2;
// if (isSpecial4) boxH_num = (h / 2) - v_gap - 2;
// } else if (item.isShort) {
// if (boxH_num > natural_max_h * 1.5) boxH_num = natural_max_h * 1.5;
// }
// let minH = `${boxH_num}px`;
// let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
// let spanDisplay = "block";
// let spanJustifyContent = "flex-start";
// let spanMarginTop = "0px";
// if (isSpecial1 || isSpecial2) spanMarginTop = `-${h / 4}px`;
// if (isSpecial1 || isSpecial2 || isSpecial4) {
// alignStyle = "justify";
// spanJustifyContent = "space-between";
// }
// let nameLen = item.name.length;
// let contentH = nameLen * size_px;
// let emptySpace = boxH_num - contentH;
// let gapsCount = nameLen > 1 ? (nameLen - 1) : 1;
// let avgGap = emptySpace / gapsCount;
// if (!isSpecial && alignStyle === "justify" && avgGap > (size_px * 1.5)) {
// alignStyle = "justify";
// spanDisplay = "block";
// spanJustifyContent = "start";
// }
// let $span = $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
// "display": spanDisplay,
// "justify-content": spanJustifyContent,
// "align-items": "center",
// "min-height": minH,
// "max-height": `${h}px`,
// "width": "auto",
// "line-height": "1.1",
// "text-align": alignStyle,
// "text-align-last": alignStyle,
// "margin-left": "5px",
// "margin-top": spanMarginTop,
// "text-justify": "inter-character",
// "word-break": "break-all"
// });
// $namelist.append($span);
// });
// return $namelist;
//},
//renderNameSpan(item, el, colWidth) {
// let th = Number(el.textHeight) || Number(el.height)
// //let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
// let minH = item.isShort ? `${th}px` : `${el.height}px`
// ;
// let alignStyle = item.isMulti ? "start" : "justify";
// return $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
// display: "block",
// "min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
// "max-height": `${el.height}px`,
// width: "auto",
// "line-height": "1.1",
// "text-align": alignStyle,
// "text-align-last": alignStyle,
// "margin-left": "5px",
// "text-justify": "inter-character",
// "word-break": "break-all"
// });
// //// 為「這個名字」獨立計算出專屬的最完美字體大小
// //let indSize = this.calcIndividualFontSize(name, el, colWidth);
// //// 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
// //let s_px = indSize * 1.333;
// //let isMultiLine = (name.length * s_px) > Number(el.textHeight);
// //// 3. 根據是否折行動態決定對齊方式
// //// 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start)
// //let alignStyle = isMultiLine ? "start" : "justify";
// //return $(`<span style="font-size: ${indSize}pt;">${name}</span>`).css({
// // display: "block",
// // "min-height": `${el.textHeight}px`,
// // "max-height": `${el.height}px`,
// // width: "auto",
// // "line-height": "1.1",
// // "text-align": alignStyle, // ★ 動態套用對齊方式
// // "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
// // "margin-left": "5px",
// // "text-justify": "inter-character",
// // "word-break": "break-all"
// //});
// //return $(`<span>${name}</span>`).css({
// // display: "block",
// // "min-height": `${el.textHeight}px`,
// // "max-height": `${el.height}px`,
// // width: `${rowWidth}px`,
// // "text-align": "justify",
// // "text-align-last": "justify",
// // "margin-left": "5px",
// // "text-justify": "inter-character",
// //});// "margin-bottom": `${el.textSpan}px`,
//},
//renderLiveList(names, el) {
// let h = parseFloat(el.height);
// let w = parseFloat(el.width);
// let th = parseFloat(el.textHeight) || h;
// let v_gap = parseFloat(el.textSpan) || 0;
// let h_gap = 5;
// let shrinkLimit = 4;
// if (Number(el.height) < 300) shrinkLimit = 8;
// else if (Number(el.height) < 500) shrinkLimit = 6;
// let s = parseFloat(el.style.fontSize);
// if (names.length == 2) h = th + v_gap;
// let maxLen = Math.max(...names.map(x => x.length), 1);
// while (s >= shrinkLimit) {
// let size_px = s * 1.333;
// let current_col_h = 0;
// let current_col_w = 0;
// let cols_width = [];
// let any_wrapped = false;
// for (let i = 0; i < names.length; i++) {
// let l = names[i].length;
// let natural_max_h = maxLen * size_px;
// let item_h = Math.max(th, natural_max_h);
// if (item_h > natural_max_h * 1.5) item_h = natural_max_h * 1.5;
// if (item_h > (h - 5)) {
// any_wrapped = true;
// if (current_col_h > 0) {
// cols_width.push(current_col_w);
// current_col_h = 0;
// current_col_w = 0;
// }
// let chars_per_col = Math.floor((h - 5) / size_px);
// if (chars_per_col < 1) chars_per_col = 1;
// let item_cols = Math.ceil(l / chars_per_col);
// cols_width.push(item_cols * (size_px * 1.1));
// } else {
// if (current_col_h === 0) {
// current_col_h = item_h;
// current_col_w = size_px;
// } else if (current_col_h + v_gap + item_h <= h) {
// current_col_h += v_gap + item_h;
// if (size_px > current_col_w) current_col_w = size_px;
// } else {
// cols_width.push(current_col_w);
// current_col_h = item_h;
// current_col_w = size_px;
// }
// }
// }
// if (current_col_h > 0) cols_width.push(current_col_w);
// let totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
// if (totalWidth <= w && (!any_wrapped || s === shrinkLimit)) break;
// s -= 1;
// }
// if (s < shrinkLimit) s = shrinkLimit;
// let $namelist = $(`<div class='liveList'></div>`).css({
// "writing-mode": "vertical-rl",
// "display": "flex",
// "flex-flow": "wrap",
// "align-content": "center",
// "align-items": "center",
// "margin": "auto",
// "width": `${w}px`,
// "height": `${h}px`,
// "border": "0px solid transparent",
// "padding": "0px",
// "font-family": el.style.fontFamily,
// "column-gap": `${v_gap}px`
// });
// let self = this;
// names.forEach(name => {
// $namelist.append(self.renderLiveSpan(name, el, s, maxLen));
// });
// return $namelist;
//},
//renderLiveSpan(name, el, fontSize, maxLen = 1) {
// let h = parseFloat(el.height);
// let th = parseFloat(el.textHeight) || h;
// let size_px = fontSize * 1.333;
// let l = name.length;
// let natural_max_h = maxLen * size_px;
// let boxH_num = Math.max(th, natural_max_h);
// if (boxH_num > natural_max_h * 1.5) boxH_num = natural_max_h * 1.5;
// let minH = `${boxH_num}px`;
// let alignStyle = "justify";
// let spanDisplay = "block";
// let spanJustifyContent = "flex-start";
// let contentH = l * size_px;
// let emptySpace = boxH_num - contentH;
// let gapsCount = l > 1 ? (l - 1) : 1;
// let avgGap = emptySpace / gapsCount;
// if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
// alignStyle = "justify";
// spanDisplay = "block";
// spanJustifyContent = "space-between";
// }
// return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
// "display": spanDisplay,
// "justify-content": spanJustifyContent,
// "align-items": "center",
// "min-height": minH,
// "max-height": `${h}px`,
// "width": "auto",
// "text-align": alignStyle,
// "text-align-last": alignStyle,
// "margin-left": "0px",
// "margin-top": "0px",
// "text-justify": "inter-character",
// "word-break": "break-all",
// "white-space": "pre-line"
// });
//},
// 品字佈局邏輯:一上二下
renderRoster(names, el, rowWidth) {
+97 -53
View File
@@ -55,6 +55,7 @@
</div>
<div class="col-2">
<button class="btn btn-primary" onclick="designer.save(event)">儲存牌位</button>
<button class="btn btn-primary" onclick="designer.saveTemplate(event)">存成範本</button>
</div>
<div class="col-4">
<div style="display: flex; align-items: center; padding: 8px; background-color: #f5f5f5; border-radius: 4px; margin-bottom: 12px; font-family: sans-serif;">
@@ -159,6 +160,33 @@
</div>
</div>
<div class="modal fade hide" id="templateModal" tabindex="-1" aria-labelledby="templateModalLabel" aria-hidden="true" style="z-index:10000 !important;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">範本名稱</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="form-floating mb-3">
<input class="form-control" type="text" id="templateName" placeholder="名稱" />
<label for="family_txt">名稱</label>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">關閉</button>
<button type="button" class="btn btn-primary" onclick="designer.saveTemplateReal()">存檔</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
const designer = {
zoomScale: 0.5,
@@ -192,6 +220,7 @@
follower_id: "",
toast: null,
modal: null,
templateModal:null,
bg: [
{ name: "超薦1", path: "../../../admin/print/html/tablet-1_new.svg" },
{ name: "超薦2", path: "../../../admin/print/html/tablet-1B_new.svg" },
@@ -203,6 +232,7 @@
async init() {
this.toast = new bootstrap.Toast($('#liveToast'));
this.modal = new bootstrap.Modal($('#familyModal'));
this.templateModal = new bootstrap.Modal($('#templateModal'));
$("#scaleSize").html((this.zoomScale * 100) + "%");
$("#scaleSlider").val(this.zoomScale).on("input change", function () {
designer.zoomScale = parseFloat($(this).val());
@@ -445,34 +475,34 @@
});
let pageStyle = `<style id="pageStyle">
* { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; }
.vertical-text { writing-mode: vertical-rl !important; -webkit-writing-mode: vertical-rl !important; text-orientation: mixed !important; }
body { overflow: visible !important; }
@media print {
:host { width:auto !important; height:auto !important; }
@page { size:${printSize.width}mm ${printSize.height}mm !important; margin:0; }
html, body, form, .full-home, .printArea, .canvas-area { height: auto !important; width: auto !important; overflow: visible !important; margin: 0 !important; padding: 0 !important; display: block !important; }
.no-print, #customMenu { display: none !important; }
.canvas-area { display:flex !important; flex-direction: row !important; justify-content:center !important; align-items:center !important; }
.tablet-paper { position: relative !important; display: block !important; break-inline:avoid; page-break-inline:avoid; break-after: page !important; page-break-after: always !important; margin: 0 !important; border: none !important; background-repeat: no-repeat; background-size: 100% 100%; }
.tablet-element { position: absolute !important; white-space: normal; color: black !important; }
}
.roster-container { width: 100%; height: 100%; writing-mode: vertical-rl; display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 20px; }
.roster-row { display: flex; flex-direction: row-reverse; justify-content: center; gap: 8px; margin-left: 10px; }
.name-group { display: flex; flex-direction: column; justify-content: center; align-items: center; }
.roster-name { text-orientation: upright; white-space: normal; line-height: 1.2; font-family: DFKai-sb; width: fit-content; }
.ancestor-wrapper { writing-mode: horizontal-tb; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; width: fit-content; }
.main-name { line-height: 1.2; }
.sub-text { font-size: ${ancestorFontSize}px; line-height: 1.2; margin-top: 4px; white-space: normal; writing-mode:vertical-rl; }
.canvas-area { width: ${pageSize.width}mm; height: ${pageSize.height}mm; break-after: page; page-break-after: always; display:flex !important; justify-content:center; }
.tablet-paper { background-color: white; display: inline-block; width: ${size.width}mm !important; height: ${size.height}mm !important; position: relative; margin-bottom: 0; background-image: url(${img.path}); background-size: 100% 100%; break-inline:avoid; page-break-inline:avoid; }
.tablet-element { cursor: move; padding: 4px; color: black !important; border: 1px solid transparent; transition: writing-mode 0.3s, transform 0.2s; }
.tablet-element:hover { border-color: rgba(13, 110, 253, 0.3); }
.tablet-paper:last-child { page-break-after: auto; }
.tablet-element span { z-index: 999; }
.selectedItem .canselectItem { font-size: 18px; }
.selectedItem, .rounded-pill .canselectItem, .rounded-pill { font-size: 12px; }
</style>`;
* { -webkit-print-color-adjust: exact !important; print-color-adjust: exact !important; color-adjust: exact !important; }
.vertical-text { writing-mode: vertical-rl !important; -webkit-writing-mode: vertical-rl !important; text-orientation: mixed !important; }
body { overflow: visible !important; }
@media print {
:host { width:auto !important; height:auto !important; }
@page { size:${printSize.width}mm ${printSize.height}mm !important; margin:0; }
html, body, form, .full-home, .printArea, .canvas-area { height: auto !important; width: auto !important; overflow: visible !important; margin: 0 !important; padding: 0 !important; display: block !important; }
.no-print, #customMenu { display: none !important; }
.canvas-area { display:flex !important; flex-direction: row !important; justify-content:center !important; align-items:center !important; }
.tablet-paper { position: relative !important; display: block !important; break-inline:avoid; page-break-inline:avoid; break-after: page !important; page-break-after: always !important; margin: 0 !important; border: none !important; background-repeat: no-repeat; background-size: 100% 100%; }
.tablet-element { position: absolute !important; white-space: normal; color: black !important; }
}
.roster-container { width: 100%; height: 100%; writing-mode: vertical-rl; display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 20px; }
.roster-row { display: flex; flex-direction: row-reverse; justify-content: center; gap: 8px; margin-left: 10px; }
.name-group { display: flex; flex-direction: column; justify-content: center; align-items: center; }
.roster-name { text-orientation: upright; white-space: normal; line-height: 1.2; font-family: DFKai-sb; width: fit-content; }
.ancestor-wrapper { writing-mode: horizontal-tb; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; width: fit-content; }
.main-name { line-height: 1.2; }
.sub-text { font-size: ${ancestorFontSize}px; line-height: 1.2; margin-top: 4px; white-space: normal; writing-mode:vertical-rl; }
.canvas-area { width: ${pageSize.width}mm; height: ${pageSize.height}mm; break-after: page; page-break-after: always; display:flex !important; justify-content:center; }
.tablet-paper { background-color: white; display: inline-block; width: ${size.width}mm !important; height: ${size.height}mm !important; position: relative; margin-bottom: 0; background-image: url(${img.path}); background-size: 100% 100%; break-inline:avoid; page-break-inline:avoid; }
.tablet-element { cursor: move; padding: 4px; color: black !important; border: 1px solid transparent; transition: writing-mode 0.3s, transform 0.2s; }
.tablet-element:hover { border-color: rgba(13, 110, 253, 0.3); }
.tablet-paper:last-child { page-break-after: auto; }
.tablet-element span { z-index: 999; }
.selectedItem .canselectItem { font-size: 18px; }
.selectedItem, .rounded-pill .canselectItem, .rounded-pill { font-size: 12px; }
</style>`;
$("#pageStyle").remove();
$("head").append(pageStyle);
@@ -494,11 +524,11 @@
this.alive.forEach(x => {
let f = this.familyMembers.find(z => z.fam_name == x);
$(".selectedItem").append(`<li><span style="opacity:0.5">卍</span>
<span class="selected">${x}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>
<span class="itemUp" style="float:right;margin-left:2rem;cursor:pointer;">&#8593;</span>
<span class="itemDown" style="float:right;margin-left:2rem;cursor:pointer;">&#8595;</span></li>`);
<span class="selected">${x}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>
<span class="itemUp" style="float:right;margin-left:2rem;cursor:pointer;">&#8593;</span>
<span class="itemDown" style="float:right;margin-left:2rem;cursor:pointer;">&#8595;</span></li>`);
});
let items = this.familyMembers.filter(x => x.deceased == false).map(x => x.fam_name);
@@ -507,19 +537,19 @@
finalItem.forEach(yy => {
let f = this.familyMembers.find(z => z.fam_name == yy);
$(".canselectItem").append(`<li><span style="opacity:0.5">卍</span> <span class="unselect">${yy}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
});
} else if (element.hasClass("address")) {
$(".selectedItem").append(`<li><span style="opacity:0.5">卍</span>
<span class="selected">${this.address == undefined ? "" : this.address}</span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
<span class="selected">${this.address == undefined ? "" : this.address}</span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
} else if (element.hasClass("lefttitle")) {
this.leftProperTitle.forEach(x => {
let f = this.familyMembers.find(z => z.fam_name == x);
$(".selectedItem").append(`<li><span style="opacity:0.5">卍</span><span class="selected">${x}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
});
let items = this.familyMembers.filter(x => (this.tabletType == "A" && x.deceased == false) || (this.tabletType == "B" && x.deceased == true)).map(x => x.fam_name);
@@ -528,15 +558,15 @@
finalItem.forEach(yy => {
let f = this.familyMembers.find(z => z.fam_name == yy);
$(".canselectItem").append(`<li><span style="opacity:0.5">卍</span> <span class="unselect">${yy}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
});
} else if (element.hasClass("righttitle")) {
this.rightProperTitle.forEach(x => {
let f = this.familyMembers.find(z => z.fam_name == x);
$(".selectedItem").append(`<li><span style="opacity:0.5">卍</span><span class="selected">${x}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>`);
});
let items = this.familyMembers.filter(x => (this.tabletType == "A" && x.deceased == false) || (this.tabletType == "B" && x.deceased == true)).map(x => x.fam_name);
@@ -545,8 +575,8 @@
finalItem.forEach(yy => {
let f = this.familyMembers.find(z => z.fam_name == yy);
$(".canselectItem").append(`<li><span style="opacity:0.5">卍</span> <span class="unselect">${yy}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
});
} else {
let hasControls = !element.hasClass("ancestor-wrapper");
@@ -554,8 +584,8 @@
let f = this.familyMembers.find(z => z.fam_name == y);
let controlHtml = hasControls ? `<span class="itemUp" style="float:right;margin-left:2rem;cursor:pointer;">&#8593;</span><span class="itemDown" style="float:right;margin-left:2rem;cursor:pointer;">&#8595;</span>` : '';
$(".selectedItem").append(`<li><span style="opacity:0.5">卍</span><span class="selected">${y}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>${controlHtml}</li>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class="itemRemove" style="float:right;margin-left:2rem;cursor:pointer;">&minus;</span>${controlHtml}</li>`);
});
if (hasControls) {
@@ -564,8 +594,8 @@
finalItem.forEach(yy => {
let f = this.familyMembers.find(z => z.fam_name == yy);
$(".canselectItem").append(`<li><span style="opacity:0.5">卍</span> <span class="unselect">${yy}</span>
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
<span><i class="rounded-pill rounded-3 ${(f && f.fam_title) ? 'p-1' : ''}" style="background-color:lightgray">${(f && f.fam_title) ? f.fam_title : ""}</i></span>
<span class='itemAppend' style="float:right;cursor:pointer;">&#43;</span></li>`);
});
}
}
@@ -1339,9 +1369,9 @@
renderCombined(mid, d) {
const parts = mid.join("\n").split('\n');
return `<div class="ancestor-wrapper" style="width:${d.width}px !important;height:${d.height}px !important;" >
<span class="main-name" >${parts[0] || ''}</span>
<span class="sub-text">${parts[1] || ''}</span>
</div>`;
<span class="main-name" >${parts[0] || ''}</span>
<span class="sub-text">${parts[1] || ''}</span>
</div>`;
},
renderNameGroups(items, el) {
@@ -1398,7 +1428,21 @@
}
});
},
async saveTemplate(event) {
//event.preventDefault();
this.templateModal.show();
},
async saveTemplateReal(event) {
//event.preventDefault();
let tablet = { mid_items: this.family_deceased_N_selected, left_items: this.family_deceased_Y_selected, style: this.selectStyle.style, mid_left: this.family_left_title, mid_right: this.family_right_title, addr_items: this.family_address };
let data = { num: "0", name: $("#templateName").val(), follower_num: this.follower_id, style_id: this.selectStyle.style, tablet: JSON.stringify(tablet), shuwen:"" }
await axios.post('/api/follower/SaveTabletTemplate', data).then(res => {
if (res.status == 200) {
this.templateModal.hide();
$("#toast_body").html("存檔成功");
}
});
},
async save(event) {
event.preventDefault();
let tablet = { mid_items: this.family_deceased_N_selected, left_items: this.family_deceased_Y_selected, style: this.selectStyle.style, mid_left: this.family_left_title, mid_right: this.family_right_title, addr_items: this.family_address };