286 lines
14 KiB
Plaintext
286 lines
14 KiB
Plaintext
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TabletDesigner.aspx.cs" Inherits="admin_item_TabletDesigner" MasterPageFile="~/admin/Templates/TBS5ADM001/MasterPage.master" %>
|
|
|
|
<%@ Register Src="~/admin/_uc/alert.ascx" TagPrefix="uc1" TagName="alert" %>
|
|
|
|
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" runat="Server">
|
|
<%-- <style type="text/css">
|
|
@import "css/styles.css";
|
|
@import "css/tablet-design.css";
|
|
@import "css/floating.css";
|
|
</style>--%>
|
|
</asp:Content>
|
|
|
|
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
|
|
|
|
<div class="d-flex overflow-hidden">
|
|
<div class="p-2 bg-dark text-white floting-box" style="width: 250px; left: 20px; top: 80px;">
|
|
<h6 class="border-bottom pb-2">設計工具箱</h6>
|
|
<select class="form-select form-select-sm " onchange="Designer.changePaper()" id="paperSize">
|
|
<option value="">請選擇</option>
|
|
</select>
|
|
<div id="paperOrientation" onclick="Designer.changeOrientation()">
|
|
<span></span>
|
|
</div>
|
|
<span class="btn btn-sm btn-outline-light w-100 mb-2" onclick="Designer.displayItem('address')">地址欄</span>
|
|
<span class="btn btn-sm btn-outline-light w-100 mb-2" onclick="Designer.displayItem('title1')">牌位正名</span>
|
|
<span class="btn btn-sm btn-outline-light w-100 mb-2" onclick="Designer.displayItem('titletriangle')">品字名單</span>
|
|
<span class="btn btn-sm btn-outline-info w-100 mb-2" onclick="Designer.displayItem('combined')">正名合併置中</span>
|
|
<span class="btn btn-sm btn-outline-info w-100 mb-2" onclick="Designer.displayItem()">陽上報恩</span>
|
|
<hr>
|
|
|
|
</div>
|
|
<div class="canvas-area flex-grow-1 overflow-auto d-flex flex-column align-items-center position-relative" id="canvas">
|
|
<div class="tablet-paper" >
|
|
<%--<div class="tablet-element vertical-text">嘿嘿</div>--%>
|
|
</div>
|
|
</div>
|
|
<div id="attr-box" class="d-none p-2 bg-dark text-whit floting-box" style="top: 80px; right: 20px">
|
|
<div class="form-floating mb-3">
|
|
<textarea id="inp-text" class="form-control form-control-sm mb-2" rows="5"></textarea>
|
|
<label class="small" for="inp-text">內容文字</label>
|
|
</div>
|
|
<div class="form-floating mb-3">
|
|
<input type="number" id="inp-size" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="inp-size">字體大小 (pt)</label>
|
|
</div>
|
|
<div class="form-floating mb-3">
|
|
<input type="number" id="2offset" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="2offset">二行偏移量</label>
|
|
</div>
|
|
<div class="form-floating mb-3">
|
|
<input type="number" id="3offset" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="3offset">三行偏移量</label>
|
|
</div>
|
|
<div class="form-floating mb-3">
|
|
<input type="number" id="4offset" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="4offset">四行偏移量</label>
|
|
</div>
|
|
<div class="form-floating mb-3">
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<input type="number" id="xPosition" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="xPosition">X</label>
|
|
</div>
|
|
<div class="col-6">
|
|
<input type="number" id="yPosition" class="form-control form-control-sm mb-2">
|
|
<label class="small" for="yPosition">Y</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</asp:Content>
|
|
<asp:Content ID="Content4" ContentPlaceHolderID="footer_script" runat="Server">
|
|
<%-- <script src="../../js/jquery-4.0.0.min.js"></script>
|
|
<script src="jquery-ui/jquery-ui.js"></script>--%>
|
|
<script>
|
|
const Designer = {
|
|
elements: [],
|
|
activeId: null,
|
|
paper: { width: 100, height: 272 },
|
|
rosterLimit: 8,
|
|
allSize: [
|
|
{ name: "A3", width: 297, height: 420, selected :""},
|
|
{ name: "A4", width: 210, height: 297, selected :""},
|
|
{ name: "B4", width: 257, height: 364, selected :""},
|
|
{ name: "red", width: 100, height: 272,selected:"selected" },
|
|
],
|
|
orientation: "portrait",
|
|
init() {
|
|
//$(".tablet-element").draggable({});
|
|
this.bindEvents();
|
|
this.loadConfig();
|
|
this.allSize.forEach(x => {
|
|
$("#paperSize").append("<option value='" + x.name + "' " + x.selected + ">" + x.width + "*" + x.height + "</option>")
|
|
})
|
|
$("#paperOrientation").html("<span>直向</span>")
|
|
},
|
|
changeOrientation() {
|
|
this.orientation = this.orientation == "portrait" ? "land" : "portrait";
|
|
$("#paperOrientation").empty();
|
|
$("#paperOrientation").html("<span>" + this.orientation == "portrait" ? "直向" : "橫向" + "</span>");
|
|
let paperSize = $("#paperSize").val()
|
|
|
|
let size = this.allSize.find(x => x.name == paperSize)
|
|
this.paper.width = size.width;
|
|
this.paper.height = size.height;
|
|
$(".tablet-paper").css({
|
|
"background-color": "red",
|
|
width: this.orientation == "portrait" ? size.width : size.height + "mm",
|
|
height: this.orientation == "portrait" ? size.height : size.width + "mm",
|
|
});
|
|
},
|
|
changePaper() {
|
|
let paperSize = $("#paperSize").val()
|
|
let size = this.allSize.find(x => x.name == paperSize)
|
|
$(".tablet-paper").css({
|
|
"background-color": "red",
|
|
width: size.width + "mm",
|
|
height: size.height + "mm",
|
|
});
|
|
},
|
|
bindEvents() {
|
|
// 文字變更連動渲染
|
|
$('#inp-text').on('input', (e) => this.updateActive('text', $(e.target).val()));
|
|
$('#inp-size').on('input', (e) => this.updateActive('fontSize', $(e.target).val()));
|
|
$(document).on('mousedown', '.tablet-element', (e) => {
|
|
e.stopPropagation();
|
|
this.select($(e.currentTarget).attr('id'));
|
|
});
|
|
},
|
|
|
|
loadConfig() {
|
|
$.ajax({
|
|
type: "POST", url: "TabletDesigner.aspx/GetConfig", contentType: "application/json",
|
|
success: (res) => {
|
|
const data = JSON.parse(res.d);
|
|
this.elements = data.elements;
|
|
this.render();
|
|
}
|
|
});
|
|
},
|
|
|
|
// 處理分頁渲染邏輯
|
|
render() {
|
|
//const $canvas = $('#canvas').empty();
|
|
const roster = this.elements.find(e => e.type === 'roster');
|
|
const names = roster ? roster.text.split('\n').filter(s => s.trim()) : [];
|
|
const pages = Math.max(1, Math.ceil(names.length / this.rosterLimit));
|
|
|
|
//for (let p = 0; p < pages; p++) {
|
|
// const $paper = $('<div class="tablet-paper"></div>')
|
|
// .css({ "background-color": "red", width: this.paper.width + 'mm', height: this.paper.height + 'mm' });
|
|
let $paper = $(".tablet-paper").css({ "background-color": "red", width: this.paper.width + 'mm', height: this.paper.height + 'mm' });
|
|
//const slice = names.slice(p * this.rosterLimit, (p + 1) * this.rosterLimit);
|
|
const slice = names.slice(0 * this.rosterLimit, (0 + 1) * this.rosterLimit);
|
|
this.elements.forEach(el => {
|
|
$paper.append(this.createEl(el, slice));
|
|
});
|
|
//$canvas.append($paper);
|
|
//}
|
|
this.makeDraggable();
|
|
},
|
|
|
|
createEl(el, slice) {
|
|
let html = '';
|
|
// 1. 智慧名單渲染
|
|
if (el.type === 'roster') {
|
|
html = this.renderRoster(slice, el);
|
|
}
|
|
// 2. 正名合併置中
|
|
else if (el.type === 'combined-center') {
|
|
const parts = el.text.split('\n');
|
|
html = `<div class="ancestor-wrapper" >
|
|
<span class="main-name" >${parts[0] || ''}</span>
|
|
<span class="sub-text">${parts[1] || ''}</span>
|
|
</div>`;
|
|
}
|
|
// 3. 地址數字轉橫排
|
|
else if (el.id === 'address') {
|
|
html = el.text.replace(/(\d+)/g, '<span class="tate-chu-yoko">$1</span>');
|
|
}
|
|
else {
|
|
html = el.text;
|
|
}
|
|
|
|
return $(`<div class="tablet-element vertical-text ${this.activeId === el.id ? 'selected' : ''}" id="${el.id}"></div>`)
|
|
.css({
|
|
left: el.x, top: el.y, fontSize: el.style.fontSize + 'pt', fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility
|
|
})
|
|
.html(html);
|
|
},
|
|
|
|
// 品字佈局邏輯:一上二下
|
|
renderRoster(names, el) {
|
|
if (!names.length) return '';
|
|
const mid = names.length === 1 ? 1 : Math.floor(names.length / 2);
|
|
const top = names.slice(0, mid);
|
|
const bot = names.slice(mid);
|
|
const size = this.autoScale(names, el.style.fontSize);
|
|
|
|
let h = `<div class="roster-container" style="gap:${el.style.itemSpacing || 20}px">`;
|
|
h += `<div class="name-group">${top.map(n => `<div class="roster-name" style="font-size:${size}pt">${n}</div>`).join('')}</div>`;
|
|
if (bot.length) h += `<div class="name-group">${bot.map(n => `<div class="roster-name" style="font-size:${size}pt">${n}</div>`).join('')}</div>`;
|
|
return h + `</div>`;
|
|
},
|
|
|
|
autoScale(names, base) {
|
|
const max = Math.max(...names.map(n => n.length), 0);
|
|
return max > 5 ? Math.max(base * (5 / max), base * 0.6) : base;
|
|
},
|
|
|
|
// 拖動後同步所有頁面的位置
|
|
makeDraggable() {
|
|
const self = this;
|
|
$(".tablet-element").draggable({
|
|
start(e, ui) {
|
|
console.log("gogogogo");
|
|
},
|
|
stop(e, ui) {
|
|
const id = $(this).attr('id');
|
|
const el = self.elements.find(x => x.id === id);
|
|
el.x = ui.position.left;
|
|
el.y = ui.position.top;
|
|
$(`.tablet-element[id="${id}"]`).css({ left: el.x, top: el.y });
|
|
}
|
|
});
|
|
},
|
|
|
|
select(id) {
|
|
this.activeId = id;
|
|
const el = this.elements.find(x => x.id === id);
|
|
$('#attr-box').removeClass('d-none');
|
|
$('#inp-text').val(el.text);
|
|
$('#inp-size').val(el.style.fontSize);
|
|
$('#xPosition').val(el.x);
|
|
$("#yPosition").val(el.y);
|
|
//this.render();
|
|
},
|
|
|
|
updateActive(key, val) {
|
|
const el = this.elements.find(x => x.id === this.activeId);
|
|
if (key === 'fontSize') el.style.fontSize = parseFloat(val);
|
|
else el[key] = val;
|
|
//this.render();
|
|
},
|
|
displayItem(id) {
|
|
console.log(id);
|
|
let el = this.elements.find(x => x.id === id);
|
|
console.log("before:",el);
|
|
el.style.visibility = el.style.visibility == "hidden" ? "" : "hidden";
|
|
console.log("after:", el);
|
|
$("#" + id).css({
|
|
left: el.x, top: el.y, fontSize: el.style.fontSize + 'pt', fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility
|
|
})
|
|
},
|
|
|
|
addMulti(prefix, count) {
|
|
for (let i = 1; i <= count; i++) {
|
|
const id = `${prefix}-${Date.now()}-${i}`;
|
|
this.elements.push({
|
|
id, type: 'title', text: `正名${i}`, x: 100 - (i * 30), y: 80,
|
|
style: { fontSize: 24, fontFamily: 'Kaiti', isVertical: true }
|
|
});
|
|
}
|
|
//this.render();
|
|
},
|
|
|
|
addCombined() {
|
|
this.stopPropagation();
|
|
|
|
this.elements.push({
|
|
id: 'combined-' + Date.now(), type: 'combined-center', text: '林張\n氏歷代祖先', x: 130, y: 80,
|
|
style: { fontSize: 24, fontFamily: 'Kaiti', isVertical: true }
|
|
});
|
|
//this.render();
|
|
},
|
|
addElement() {
|
|
console.log("QQQ");
|
|
}
|
|
};
|
|
|
|
$(() => Designer.init());
|
|
</script>
|
|
</asp:Content>
|