修正快速報名
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using DocumentFormat.OpenXml.Drawing.Charts;
|
using DocumentFormat.OpenXml.Drawing.Charts;
|
||||||
|
using DocumentFormat.OpenXml.Spreadsheet;
|
||||||
using Model;
|
using Model;
|
||||||
using MyWeb;
|
using MyWeb;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -227,6 +228,8 @@ public class orderController : ApiController
|
|||||||
var hasList = _db.pro_order.AsNoTracking().Where(x => x.activity_num == po.activity_num).AsNoTracking().ToList();
|
var hasList = _db.pro_order.AsNoTracking().Where(x => x.activity_num == po.activity_num).AsNoTracking().ToList();
|
||||||
var actItemList=_db.activity_relating.AsNoTracking().Where(x=>x.activity_num==po.activity_num).AsNoTracking().ToList();
|
var actItemList=_db.activity_relating.AsNoTracking().Where(x=>x.activity_num==po.activity_num).AsNoTracking().ToList();
|
||||||
List<int> rp=new List<int>();
|
List<int> rp=new List<int>();
|
||||||
|
string print_id=string.Empty;
|
||||||
|
var items = _db.actItems.AsQueryable();
|
||||||
//要檢查是否已經報名
|
//要檢查是否已經報名
|
||||||
foreach (var item in list)
|
foreach (var item in list)
|
||||||
{
|
{
|
||||||
@@ -254,8 +257,10 @@ public class orderController : ApiController
|
|||||||
item.up_time= DateTime.Now;
|
item.up_time= DateTime.Now;
|
||||||
item.order_no= createOrderNumber();
|
item.order_no= createOrderNumber();
|
||||||
item.activity_num= po.activity_num;
|
item.activity_num= po.activity_num;
|
||||||
|
item.activity = act;
|
||||||
|
print_id=string.Empty;
|
||||||
_db.pro_order.Add(item);
|
_db.pro_order.Add(item);
|
||||||
|
_db.SaveChanges();
|
||||||
orders.Add(item);
|
orders.Add(item);
|
||||||
foreach (var detail in item.pro_order_detail)
|
foreach (var detail in item.pro_order_detail)
|
||||||
{
|
{
|
||||||
@@ -286,9 +291,33 @@ public class orderController : ApiController
|
|||||||
detail.start_date= act.startDate_solar;
|
detail.start_date= act.startDate_solar;
|
||||||
detail.due_date= act.endDate_solar;
|
detail.due_date= act.endDate_solar;
|
||||||
detail.printed_files = "";
|
detail.printed_files = "";
|
||||||
|
detail.actItem_num = actItem.num;
|
||||||
|
//if (string.IsNullOrEmpty(print_id))
|
||||||
|
//{
|
||||||
|
// print_id = GenerateSequentialId(detail, item);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// string last_three = print_id.Substring(print_id.Length - 3);
|
||||||
|
// if (int.TryParse(last_three, out int result))
|
||||||
|
// {
|
||||||
|
// print_id = print_id.Substring(0, print_id.Length - 3) + string.Format("{0:D3}", result + 1);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// string last_two = print_id.Substring(print_id.Length - 2);
|
||||||
|
// if (int.TryParse(last_two, out int result1))
|
||||||
|
// {
|
||||||
|
// print_id = print_id.Substring(0, print_id.Length - 2) + string.Format("{0:D2}", result1 + 1);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
var defaultStyle=items.Where(i => i.num == detail.actItem_num).Select(i=>i.defaultStyle).FirstOrDefault();
|
||||||
|
detail.style = defaultStyle==null?"":defaultStyle;
|
||||||
detail.print_id = GenerateSequentialId(detail, item);
|
detail.print_id = GenerateSequentialId(detail, item);
|
||||||
|
|
||||||
_db.pro_order_detail.Add(detail);
|
_db.pro_order_detail.Add(detail);
|
||||||
|
_db.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -296,7 +325,7 @@ public class orderController : ApiController
|
|||||||
//_db.pro_order.AddRange(orders);
|
//_db.pro_order.AddRange(orders);
|
||||||
//_db.SaveChanges();
|
//_db.SaveChanges();
|
||||||
//_db.pro_order_detail.AddRange(order_details);
|
//_db.pro_order_detail.AddRange(order_details);
|
||||||
_db.SaveChanges();
|
|
||||||
return Ok(new {result="Y",message="完成",data=rp});
|
return Ok(new {result="Y",message="完成",data=rp});
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -979,7 +1008,7 @@ public class orderController : ApiController
|
|||||||
var last_order = _db.pro_order.Where(x => x.order_no == last_order_no).FirstOrDefault();
|
var last_order = _db.pro_order.Where(x => x.order_no == last_order_no).FirstOrDefault();
|
||||||
if (last_order != null)
|
if (last_order != null)
|
||||||
{
|
{
|
||||||
|
var activity = _db.activities.Where(z => z.num == item.activity_num).FirstOrDefault();
|
||||||
new_pro_order.up_time = DateTime.Now;
|
new_pro_order.up_time = DateTime.Now;
|
||||||
new_pro_order.reg_time = DateTime.Now;
|
new_pro_order.reg_time = DateTime.Now;
|
||||||
new_pro_order.phone = last_order.phone;
|
new_pro_order.phone = last_order.phone;
|
||||||
@@ -991,13 +1020,17 @@ public class orderController : ApiController
|
|||||||
new_pro_order.customize_data = last_order.customize_data;
|
new_pro_order.customize_data = last_order.customize_data;
|
||||||
new_pro_order.send_receipt = last_order.send_receipt;
|
new_pro_order.send_receipt = last_order.send_receipt;
|
||||||
new_pro_order.receipt_title = last_order.receipt_title;
|
new_pro_order.receipt_title = last_order.receipt_title;
|
||||||
|
new_pro_order.activity = activity;
|
||||||
_db.pro_order.Add(new_pro_order);
|
_db.pro_order.Add(new_pro_order);
|
||||||
|
var items = _db.actItems.AsQueryable();
|
||||||
|
string print_id = "";
|
||||||
|
//判斷如果details只有一個,要檢查是否為功德主,是的話撈出牌位,做成功德主底下的
|
||||||
foreach (var item1 in details)
|
foreach (var item1 in details)
|
||||||
{//如果item1 change_item_num 有值且不為0,表示要複製過來
|
{//如果item1 change_item_num 有值且不為0,表示要複製過來
|
||||||
|
|
||||||
var last_detail = _db.pro_order_detail.Where(x => x.num == item1.num).FirstOrDefault();
|
var last_detail = _db.pro_order_detail.Where(x => x.num == item1.num).FirstOrDefault();
|
||||||
var detail = new pro_order_detail();
|
var detail = new pro_order_detail();
|
||||||
|
|
||||||
detail.order_no = new_pro_order.order_no;
|
detail.order_no = new_pro_order.order_no;
|
||||||
detail.actItem_num = (item1.change_item_num!=null&&item1.change_item_num!=0)?item1.change_item_num: last_detail.actItem_num;
|
detail.actItem_num = (item1.change_item_num!=null&&item1.change_item_num!=0)?item1.change_item_num: last_detail.actItem_num;
|
||||||
detail.f_num_tablet = last_detail.f_num_tablet;
|
detail.f_num_tablet = last_detail.f_num_tablet;
|
||||||
@@ -1005,14 +1038,39 @@ public class orderController : ApiController
|
|||||||
detail.price = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.price : last_detail.price;
|
detail.price = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.price : last_detail.price;
|
||||||
detail.qty = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.qty : last_detail.qty;
|
detail.qty = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.qty : last_detail.qty;
|
||||||
detail.printed_files = "";//(item1.change_item_num != null && item1.change_item_num != 0) ? item1.printed_files : last_detail.printed_files;
|
detail.printed_files = "";//(item1.change_item_num != null && item1.change_item_num != 0) ? item1.printed_files : last_detail.printed_files;
|
||||||
detail.style = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.style : last_detail.style;
|
//要改抓回牌位的預設版型
|
||||||
|
var defaultStyle = items.Where(i => i.num == detail.actItem_num).Select(i => i.defaultStyle).FirstOrDefault();
|
||||||
|
detail.style = defaultStyle == null ? "" : defaultStyle;
|
||||||
|
//detail.style = (item1.change_item_num != null && item1.change_item_num != 0) ? item1.style : last_detail.style;
|
||||||
detail.UpdateTime = DateTime.Now;
|
detail.UpdateTime = DateTime.Now;
|
||||||
detail.start_date = DateTime.Now;//這兩個要用活動的
|
detail.start_date = DateTime.Now;//這兩個要用活動的
|
||||||
detail.due_date = DateTime.Now;//
|
detail.due_date = DateTime.Now;//
|
||||||
|
// //因為還沒進資料庫,所以會跑出一樣的號碼
|
||||||
|
//if (string.IsNullOrEmpty(print_id))
|
||||||
|
//{
|
||||||
|
// print_id = GenerateSequentialId(detail, new_pro_order);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// string last_three = print_id.Substring(print_id.Length - 3);
|
||||||
|
// if (int.TryParse(last_three, out int result))
|
||||||
|
// {
|
||||||
|
// print_id = print_id.Substring(0,print_id.Length - 3)+string.Format("{0:D3}",result+1);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// string last_two = print_id.Substring(print_id.Length - 2);
|
||||||
|
// if (int.TryParse(last_two, out int result1))
|
||||||
|
// {
|
||||||
|
// print_id = print_id.Substring(0, print_id.Length - 2) + string.Format("{0:D2}", result1 + 1);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
detail.print_id =GenerateSequentialId(detail, new_pro_order);
|
detail.print_id =GenerateSequentialId(detail, new_pro_order);
|
||||||
_db.pro_order_detail.Add(detail);
|
_db.pro_order_detail.Add(detail);
|
||||||
}
|
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(new
|
return Ok(new
|
||||||
{
|
{
|
||||||
result = "Y",
|
result = "Y",
|
||||||
|
|||||||
@@ -245,7 +245,7 @@
|
|||||||
'group-component': httpVueLoader('./group_reconcile.vue'),
|
'group-component': httpVueLoader('./group_reconcile.vue'),
|
||||||
'personal-component': httpVueLoader('./personal_reconcile.vue'),
|
'personal-component': httpVueLoader('./personal_reconcile.vue'),
|
||||||
'balance-component': httpVueLoader('./balance_reconcile.vue'),
|
'balance-component': httpVueLoader('./balance_reconcile.vue'),
|
||||||
'verify_query-component': httpVueLoader('./verify_order_record_query.vue'),
|
'verify_query-component': httpVueLoader('./audit.vue'),
|
||||||
'balance_query-component': httpVueLoader('./balance_reconcile_query.vue'),
|
'balance_query-component': httpVueLoader('./balance_reconcile_query.vue'),
|
||||||
'statistic_query-component': httpVueLoader('./statistic.vue'),
|
'statistic_query-component': httpVueLoader('./statistic.vue'),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,6 +28,12 @@
|
|||||||
:page.sync="data_table.page"
|
:page.sync="data_table.page"
|
||||||
:items-per-page.sync="data_table.pageSize"
|
:items-per-page.sync="data_table.pageSize"
|
||||||
class="elevation-1">
|
class="elevation-1">
|
||||||
|
|
||||||
|
<template #item.slot_btn="{ item }">
|
||||||
|
<%-- <a :href="'reg.aspx?num='+item.num" class="btn btn-outline-secondary btn-sm"><i class="mdi mdi-pencil-box-outline"></i>修改</a>
|
||||||
|
<a @click="deleteItem(item)" class="btn btn-outline-secondary btn-sm"><i class="mdi mdi-trash-can"></i>刪除</a> --%>
|
||||||
|
|
||||||
|
</template>
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row class="align-baseline" wrap>
|
<v-row class="align-baseline" wrap>
|
||||||
@@ -101,6 +107,11 @@
|
|||||||
itemsPerPageOptions: [5, 10, 20, 30],
|
itemsPerPageOptions: [5, 10, 20, 30],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
modify_dialog: {
|
||||||
|
show: false,
|
||||||
|
mode:'view'
|
||||||
|
},
|
||||||
|
currentView:'company-component',
|
||||||
search: {}
|
search: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -778,7 +778,7 @@
|
|||||||
{ text: '開始日期', value: '開始日期', width: 120 },
|
{ text: '開始日期', value: '開始日期', width: 120 },
|
||||||
{ text: '結束日期', value: '結束日期', width: 120 },
|
{ text: '結束日期', value: '結束日期', width: 120 },
|
||||||
{ text: '報名截止', value: '報名截止日', width: 120 },
|
{ text: '報名截止', value: '報名截止日', width: 120 },
|
||||||
{ text: '報名數', value: '功德數量', width: 100, align: 'center' },
|
{ text: '功德數量', value: '功德數量', width: 100, align: 'center' },
|
||||||
{ text: '總金額', value: '合計', width: 120, align: 'end' },
|
{ text: '總金額', value: '合計', width: 120, align: 'end' },
|
||||||
{ text: '操作', value: 'actions', width: 120, sortable: false, align: 'center' }
|
{ text: '操作', value: 'actions', width: 120, sortable: false, align: 'center' }
|
||||||
],
|
],
|
||||||
|
|||||||
+545
-179
@@ -1593,6 +1593,7 @@ html, body, * {
|
|||||||
//})
|
//})
|
||||||
//return $namelist;
|
//return $namelist;
|
||||||
},*/
|
},*/
|
||||||
|
|
||||||
renderNameList(names, el) {
|
renderNameList(names, el) {
|
||||||
let h = Number(el.height);
|
let h = Number(el.height);
|
||||||
let w = Number(el.width);
|
let w = Number(el.width);
|
||||||
@@ -1614,16 +1615,23 @@ html, body, * {
|
|||||||
names = names[0].split("暨");
|
names = names[0].split("暨");
|
||||||
names[0] = names[0] + "暨";
|
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. 初始判定與特例條件計算
|
// 1. 初始判定與特例條件計算
|
||||||
let items = names.map(name => {
|
let items = names.map(name => {
|
||||||
let l = name.length;
|
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 };
|
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 maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1);
|
||||||
|
|
||||||
let allShort = items.every(x => x.isShort);
|
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 fitsInHalf = items.every(x => (x.l * short_s * 1.333) <= (h / 2));
|
||||||
|
|
||||||
let isSpecial1 = allShort && fitsInHalf && items.length === 1;
|
let isSpecial1 = allShort && fitsInHalf && items.length === 1;
|
||||||
@@ -1650,12 +1658,16 @@ html, body, * {
|
|||||||
|
|
||||||
if (item.isShort) {
|
if (item.isShort) {
|
||||||
let item_h = Math.max(th, maxShortLen * size_px);
|
let item_h = Math.max(th, maxShortLen * size_px);
|
||||||
|
|
||||||
|
// 壓縮高度釋放空間 (支援反向放大字體)
|
||||||
if (isSpecial) {
|
if (isSpecial) {
|
||||||
if (isSpecial1 || isSpecial2) item_h = h / 2;
|
if (isSpecial1 || isSpecial2) item_h = h / 2;
|
||||||
if (isSpecial4) item_h = (h / 2) - (v_gap / 2);
|
if (isSpecial4) item_h = (h / 2) - (v_gap / 2);
|
||||||
} else {
|
} else {
|
||||||
let natural_h = maxShortLen * size_px;
|
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) {
|
if (current_col_h === 0) {
|
||||||
@@ -1675,10 +1687,13 @@ html, body, * {
|
|||||||
current_col_h = 0;
|
current_col_h = 0;
|
||||||
current_col_w = 0;
|
current_col_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let item_w = size_px;
|
let item_w = size_px;
|
||||||
|
|
||||||
if ((item.l * size_px) > (h - 10)) {
|
if ((item.l * size_px) > (h - 10)) {
|
||||||
item.isMulti = true;
|
item.isMulti = true;
|
||||||
any_wrapped = true;
|
any_wrapped = true;
|
||||||
|
|
||||||
let chars_per_col = Math.floor((h - 10) / size_px);
|
let chars_per_col = Math.floor((h - 10) / size_px);
|
||||||
if (chars_per_col < 1) chars_per_col = 1;
|
if (chars_per_col < 1) chars_per_col = 1;
|
||||||
let item_cols = Math.ceil(item.l / chars_per_col);
|
let item_cols = Math.ceil(item.l / chars_per_col);
|
||||||
@@ -1686,26 +1701,20 @@ html, body, * {
|
|||||||
} else {
|
} else {
|
||||||
item.isMulti = false;
|
item.isMulti = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cols_width.push(item_w);
|
cols_width.push(item_w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_col_h > 0) cols_width.push(current_col_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);
|
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)) {
|
if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) {
|
||||||
sizes = items.map(x => {
|
sizes = items.map(x => {
|
||||||
let final_s = x.size;
|
let final_s = x.size;
|
||||||
if (x.isShort) {
|
if (x.isShort) {
|
||||||
//let max_s_for_th = Math.floor(th / (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;
|
|
||||||
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));
|
|
||||||
|
|
||||||
if (final_s > max_s_for_th) {
|
if (final_s > max_s_for_th) {
|
||||||
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 hasLong = items.some(x => !x.isShort);
|
||||||
let hasShort = items.some(x => x.isShort);
|
let hasShort = items.some(x => x.isShort);
|
||||||
|
|
||||||
if (hasLong && hasShort) {
|
if (hasLong && hasShort) {
|
||||||
if (shrink_turn === 'long') {
|
if (shrink_turn === 'long') {
|
||||||
if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
||||||
@@ -1737,13 +1747,18 @@ html, body, * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sizes.length === 0) {
|
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 flexDir = isSpecial2 ? "column" : "row";
|
||||||
let flexJustify = isSpecial ? "center" : "flex-start";
|
let flexJustify = isSpecial ? "center" : "flex-start";
|
||||||
let flexAlign = "center";
|
let flexAlign = "center";
|
||||||
//if (isSpecial4) v_gap = Number(h) / 4;
|
if (isSpecial4) {
|
||||||
|
v_gap = Number(h) / 4;
|
||||||
|
}
|
||||||
|
|
||||||
let $namelist = $(`<div class='nameList'></div>`).css({
|
let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
"writing-mode": "vertical-rl",
|
"writing-mode": "vertical-rl",
|
||||||
@@ -1759,39 +1774,52 @@ html, body, * {
|
|||||||
border: "0px solid transparent",
|
border: "0px solid transparent",
|
||||||
padding: "1px",
|
padding: "1px",
|
||||||
"column-gap": `${v_gap}px`,
|
"column-gap": `${v_gap}px`,
|
||||||
"font-family": el.style.fontFamily
|
"font-family": el.style.fontFamily || el.fontFamily
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 4. 渲染單一名稱
|
||||||
sizes.forEach(item => {
|
sizes.forEach(item => {
|
||||||
let size_px = item.size * 1.333;
|
let size_px = item.size * 1.333;
|
||||||
|
|
||||||
|
// 🚀 關鍵修正:統一使用 maxShortLen 算出標準高度,保證所有短名字的「格子」一模一樣大!
|
||||||
let natural_max_h = maxShortLen * size_px;
|
let natural_max_h = maxShortLen * size_px;
|
||||||
let boxH_num = item.isShort ? Math.max(th, natural_max_h) : h;
|
let boxH_num = item.isShort ? Math.max(th, natural_max_h) : h;
|
||||||
|
|
||||||
if (isSpecial) {
|
if (isSpecial) {
|
||||||
if (isSpecial1 || isSpecial2) boxH_num = h / 2;
|
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) {
|
} 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 minH = `${boxH_num}px`;
|
||||||
let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
|
let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
|
||||||
|
|
||||||
let spanDisplay = "block";
|
let spanDisplay = "block";
|
||||||
let spanJustifyContent = "flex-start";
|
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) {
|
if (isSpecial1 || isSpecial2 || isSpecial4) {
|
||||||
alignStyle = "justify";
|
alignStyle = "justify";
|
||||||
spanJustifyContent = "space-between";
|
spanJustifyContent = "space-between";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 這裡依然保留各自的真實字數,只用來計算「字距」,不影響格子大小
|
||||||
let nameLen = item.name.length;
|
let nameLen = item.name.length;
|
||||||
let contentH = nameLen * size_px;
|
let contentH = nameLen * size_px;
|
||||||
let emptySpace = boxH_num - contentH;
|
let emptySpace = boxH_num - contentH;
|
||||||
let gapsCount = nameLen > 1 ? (nameLen - 1) : 1;
|
let gapsCount = nameLen > 1 ? (nameLen - 1) : 1;
|
||||||
let avgGap = emptySpace / gapsCount;
|
let avgGap = emptySpace / gapsCount;
|
||||||
|
|
||||||
|
// 防過度拉扯 (排除特例,保護單名/雙名的正常分散)
|
||||||
if (!isSpecial && alignStyle === "justify" && avgGap > (size_px * 1.5)) {
|
if (!isSpecial && alignStyle === "justify" && avgGap > (size_px * 1.5)) {
|
||||||
alignStyle = "justify";
|
alignStyle = "justify";
|
||||||
spanDisplay = "block";
|
spanDisplay = "block";
|
||||||
@@ -1813,63 +1841,124 @@ html, body, * {
|
|||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
"word-break": "break-all"
|
"word-break": "break-all"
|
||||||
});
|
});
|
||||||
|
|
||||||
$namelist.append($span);
|
$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;
|
return $namelist;
|
||||||
},
|
},
|
||||||
renderNameSpan(item, el, colWidth) {
|
renderLiveSpan(name, el, fontSize, maxLen = 1) {
|
||||||
let th = Number(el.textHeight) || Number(el.height)
|
let h = parseFloat(el.height);
|
||||||
//let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
|
let th = parseFloat(el.textHeight) || h;
|
||||||
let minH = item.isShort ? `${th}px` : `${el.height}px`
|
let size_px = fontSize * 1.333;
|
||||||
;
|
|
||||||
let alignStyle = item.isMulti ? "start" : "justify";
|
|
||||||
|
|
||||||
return $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
|
let natural_max_h = maxLen * size_px;
|
||||||
display: "block",
|
let boxH_num = Math.max(th, natural_max_h);
|
||||||
"min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
|
|
||||||
"max-height": `${el.height}px`,
|
if (boxH_num > natural_max_h * 1.5) {
|
||||||
width: "auto",
|
boxH_num = natural_max_h * 1.5;
|
||||||
"line-height": "1.1",
|
}
|
||||||
"text-align": alignStyle,
|
|
||||||
"text-align-last": alignStyle,
|
let minH = `${boxH_num}px`;
|
||||||
"margin-left": "5px",
|
|
||||||
|
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",
|
"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) {
|
/* renderLiveList(names, el) {
|
||||||
//console.log("renderLiveList:", names);
|
//console.log("renderLiveList:", names);
|
||||||
//$("#imp-text").updateActive("text",names)
|
//$("#imp-text").updateActive("text",names)
|
||||||
@@ -1997,130 +2086,407 @@ html, body, * {
|
|||||||
// "text-justify": "inter-character",
|
// "text-justify": "inter-character",
|
||||||
//});//"margin-bottom": `${el.textSpan}px`,
|
//});//"margin-bottom": `${el.textSpan}px`,
|
||||||
},*/
|
},*/
|
||||||
renderLiveList(names, el) {
|
//renderNameList(names, el) {
|
||||||
let h = parseFloat(el.height);
|
// let h = Number(el.height);
|
||||||
let w = parseFloat(el.width);
|
// let w = Number(el.width);
|
||||||
let th = parseFloat(el.textHeight) || h;
|
// let th = Number(el.textHeight) || h;
|
||||||
let v_gap = parseFloat(el.textSpan) || 0;
|
// let v_gap = Number(el.textSpan) || 0;
|
||||||
let h_gap = 5;
|
// let h_gap = 5;
|
||||||
let shrinkLimit = 4;
|
// let shrinkLimit = 6;
|
||||||
if (Number(el.height) < 300) shrinkLimit = 8;
|
|
||||||
else if (Number(el.height) < 500) shrinkLimit = 6;
|
|
||||||
|
|
||||||
let s = parseFloat(el.style.fontSize);
|
// if (h < 500) {
|
||||||
if (names.length == 2) h = th + v_gap;
|
// 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) {
|
// if (h < 500 && names.length == 1 && names[0].includes("暨無始劫以來累世冤親債主")) {
|
||||||
let size_px = s * 1.333;
|
// names = names[0].split("暨");
|
||||||
let current_col_h = 0;
|
// names[0] = names[0] + "暨";
|
||||||
let current_col_w = 0;
|
// }
|
||||||
let cols_width = [];
|
// const init_fontSize = Number(el.fontSize) > 40 ? 40 : Number(el.fontSize);
|
||||||
let any_wrapped = false;
|
// // 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 maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1);
|
||||||
let l = names[i].length;
|
// let allShort = items.every(x => x.isShort);
|
||||||
let natural_max_h = maxLen * size_px;
|
// let fitsInHalf = items.every(x => (x.l * short_s * 1.333) <= (h / 2));
|
||||||
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)) {
|
// let isSpecial1 = allShort && fitsInHalf && items.length === 1;
|
||||||
any_wrapped = true;
|
// let isSpecial2 = allShort && fitsInHalf && items.length === 2;
|
||||||
if (current_col_h > 0) {
|
// let isSpecial4 = allShort && fitsInHalf && (items.length === 4 || items.length === 6 || items.length === 8);
|
||||||
cols_width.push(current_col_w);
|
// let isSpecial = isSpecial1 || isSpecial2 || isSpecial4;
|
||||||
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 sizes = [];
|
||||||
|
// let shrink_turn = 'long';
|
||||||
|
|
||||||
let $namelist = $(`<div class='liveList'></div>`).css({
|
// // 2. 模擬排版與字體縮放運算
|
||||||
"writing-mode": "vertical-rl",
|
// while (true) {
|
||||||
"display": "flex",
|
// let totalWidth = 0;
|
||||||
"flex-flow": "wrap",
|
// let current_col_h = 0;
|
||||||
"align-content": "center",
|
// let current_col_w = 0;
|
||||||
"align-items": "center",
|
// let cols_width = [];
|
||||||
"margin": "auto",
|
// let any_wrapped = false;
|
||||||
"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;
|
// for (let i = 0; i < items.length; i++) {
|
||||||
names.forEach(name => {
|
// let item = items[i];
|
||||||
$namelist.append(self.renderLiveSpan(name, el, s, maxLen));
|
// let s = item.isShort ? short_s : long_s;
|
||||||
});
|
// item.size = s;
|
||||||
return $namelist;
|
// let size_px = s * 1.333;
|
||||||
},
|
|
||||||
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;
|
// if (item.isShort) {
|
||||||
let boxH_num = Math.max(th, natural_max_h);
|
// let item_h = Math.max(th, maxShortLen * size_px);
|
||||||
if (boxH_num > natural_max_h * 1.5) boxH_num = natural_max_h * 1.5;
|
// 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`;
|
// if (current_col_h === 0) {
|
||||||
let alignStyle = "justify";
|
// current_col_h = item_h;
|
||||||
let spanDisplay = "block";
|
// current_col_w = size_px;
|
||||||
let spanJustifyContent = "flex-start";
|
// } 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;
|
// if (current_col_h > 0) cols_width.push(current_col_w);
|
||||||
let emptySpace = boxH_num - contentH;
|
// totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
|
||||||
let gapsCount = l > 1 ? (l - 1) : 1;
|
|
||||||
let avgGap = emptySpace / gapsCount;
|
|
||||||
|
|
||||||
if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
|
// if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) {
|
||||||
alignStyle = "justify";
|
// sizes = items.map(x => {
|
||||||
spanDisplay = "block";
|
// let final_s = x.size;
|
||||||
spanJustifyContent = "space-between";
|
// 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({
|
// if (final_s > max_s_for_th) {
|
||||||
"display": spanDisplay,
|
// final_s = max_s_for_th;
|
||||||
"justify-content": spanJustifyContent,
|
// }
|
||||||
"align-items": "center",
|
// }
|
||||||
"min-height": minH,
|
// return { name: x.name, size: final_s, isMulti: x.isMulti, isShort: x.isShort };
|
||||||
"max-height": `${h}px`,
|
// });
|
||||||
"width": "auto",
|
// break;
|
||||||
"text-align": alignStyle,
|
// }
|
||||||
"text-align-last": alignStyle,
|
|
||||||
"margin-left": "0px",
|
// let hasLong = items.some(x => !x.isShort);
|
||||||
"margin-top": "0px",
|
// let hasShort = items.some(x => x.isShort);
|
||||||
"text-justify": "inter-character",
|
// if (hasLong && hasShort) {
|
||||||
"word-break": "break-all",
|
// if (shrink_turn === 'long') {
|
||||||
"white-space": "pre-line"
|
// 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) {
|
renderRoster(names, el, rowWidth) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<button class="btn btn-primary" onclick="designer.save(event)">儲存牌位</button>
|
<button class="btn btn-primary" onclick="designer.save(event)">儲存牌位</button>
|
||||||
|
<button class="btn btn-primary" onclick="designer.saveTemplate(event)">存成範本</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<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;">
|
<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>
|
</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">
|
<script type="text/javascript">
|
||||||
const designer = {
|
const designer = {
|
||||||
zoomScale: 0.5,
|
zoomScale: 0.5,
|
||||||
@@ -192,6 +220,7 @@
|
|||||||
follower_id: "",
|
follower_id: "",
|
||||||
toast: null,
|
toast: null,
|
||||||
modal: null,
|
modal: null,
|
||||||
|
templateModal:null,
|
||||||
bg: [
|
bg: [
|
||||||
{ name: "超薦1", path: "../../../admin/print/html/tablet-1_new.svg" },
|
{ name: "超薦1", path: "../../../admin/print/html/tablet-1_new.svg" },
|
||||||
{ name: "超薦2", path: "../../../admin/print/html/tablet-1B_new.svg" },
|
{ name: "超薦2", path: "../../../admin/print/html/tablet-1B_new.svg" },
|
||||||
@@ -203,6 +232,7 @@
|
|||||||
async init() {
|
async init() {
|
||||||
this.toast = new bootstrap.Toast($('#liveToast'));
|
this.toast = new bootstrap.Toast($('#liveToast'));
|
||||||
this.modal = new bootstrap.Modal($('#familyModal'));
|
this.modal = new bootstrap.Modal($('#familyModal'));
|
||||||
|
this.templateModal = new bootstrap.Modal($('#templateModal'));
|
||||||
$("#scaleSize").html((this.zoomScale * 100) + "%");
|
$("#scaleSize").html((this.zoomScale * 100) + "%");
|
||||||
$("#scaleSlider").val(this.zoomScale).on("input change", function () {
|
$("#scaleSlider").val(this.zoomScale).on("input change", function () {
|
||||||
designer.zoomScale = parseFloat($(this).val());
|
designer.zoomScale = parseFloat($(this).val());
|
||||||
@@ -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) {
|
async save(event) {
|
||||||
event.preventDefault();
|
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 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 };
|
||||||
|
|||||||
Reference in New Issue
Block a user