總疏文
This commit is contained in:
@@ -0,0 +1,47 @@
|
|||||||
|
using PagedList;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web;
|
||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// companyController 的摘要描述
|
||||||
|
/// </summary>
|
||||||
|
[ezAuthorize]
|
||||||
|
public class companyController : BaseApiController
|
||||||
|
{
|
||||||
|
public companyController()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TODO: 在這裡新增建構函式邏輯
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Route("api/hrs/basic/GetCompanys")]
|
||||||
|
public IHttpActionResult GetCompanys([FromBody] Model.hr_company comp, int page, int pageSize = 10,
|
||||||
|
string sortBy = "", bool sortDesc = false)
|
||||||
|
{
|
||||||
|
var qry = _db.hr_company.AsQueryable();
|
||||||
|
|
||||||
|
|
||||||
|
var count = qry.Count();
|
||||||
|
var qryList = (pageSize > 0) ? qry.ToPagedList(page, pageSize).ToList() : qry.ToList();
|
||||||
|
|
||||||
|
var ret = new
|
||||||
|
{
|
||||||
|
list = qryList.Select(x => new
|
||||||
|
{
|
||||||
|
x.company_id,
|
||||||
|
x.name,
|
||||||
|
x.parent_id,
|
||||||
|
x.super_visor,
|
||||||
|
x.contactor
|
||||||
|
}),
|
||||||
|
count = count
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -612,6 +612,9 @@
|
|||||||
<button class="nav-link" id="sec2-tab3" data-bs-toggle="tab" data-bs-target="#sec2-page3"
|
<button class="nav-link" id="sec2-tab3" data-bs-toggle="tab" data-bs-target="#sec2-page3"
|
||||||
type="button" role="tab" aria-controls="bom" aria-selected="false">
|
type="button" role="tab" aria-controls="bom" aria-selected="false">
|
||||||
功德項目</button>
|
功德項目</button>
|
||||||
|
<%--<button class="nav-link" id="sec2-tab4" data-bs-toggle="tab" data-bs-target="#sec2-page4"
|
||||||
|
type="button" role="tab" aria-controls="bom" aria-selected="false">
|
||||||
|
總疏文維護</button>--%>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -884,6 +887,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</asp:Panel>
|
</asp:Panel>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<%-- <div class="tab-pane fade giftItems label-sm-right" id="sec2-page4" role="tabpanel" aria-labelledby="sec2-tab4">
|
||||||
|
總疏文維護
|
||||||
|
</div>--%>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<%@ Register Src="~/admin/_uc/alert.ascx" TagPrefix="uc1" TagName="alert" %>
|
<%@ Register Src="~/admin/_uc/alert.ascx" TagPrefix="uc1" TagName="alert" %>
|
||||||
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" runat="Server">
|
<asp:Content ID="Content1" ContentPlaceHolderID="page_header" runat="Server">
|
||||||
|
<script src="/js/httpVueLoader.js"></script>
|
||||||
</asp:Content>
|
</asp:Content>
|
||||||
<asp:Content ID="Content4" ContentPlaceHolderID="footer_script" runat="Server">
|
<asp:Content ID="Content4" ContentPlaceHolderID="footer_script" runat="Server">
|
||||||
<script>
|
<script>
|
||||||
@@ -286,7 +287,8 @@
|
|||||||
items: [
|
items: [
|
||||||
{ order_no: "D", member_name: "S", order_date: "2025-12-07" }
|
{ order_no: "D", member_name: "S", order_date: "2025-12-07" }
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
currentView: 'shuwen-component',
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -317,6 +319,9 @@
|
|||||||
deep: true,
|
deep: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
'shuwen-component': httpVueLoader('./shuwen02.vue'),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
search_show(curr) {
|
search_show(curr) {
|
||||||
//console.log("btn_click:", curr, curr.api_url);
|
//console.log("btn_click:", curr, curr.api_url);
|
||||||
@@ -1061,6 +1066,10 @@
|
|||||||
type="button" role="tab" aria-controls="profile" aria-selected="false" @click="loadUnfilledList">
|
type="button" role="tab" aria-controls="profile" aria-selected="false" @click="loadUnfilledList">
|
||||||
未填寫名單
|
未填寫名單
|
||||||
</button>
|
</button>
|
||||||
|
<button v-if="this_id!=''" class="nav-link" id="sec2-tab5" data-bs-toggle="tab" data-bs-target="#sec2-page5"
|
||||||
|
type="button" role="tab" aria-controls="profile" aria-selected="false">
|
||||||
|
總疏文維護
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -1349,7 +1358,16 @@
|
|||||||
</v-data-table>
|
</v-data-table>
|
||||||
</v-card>
|
</v-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="tab-pane fade" id="sec2-page5" role="tabpanel" aria-labelledby="sec2-tab5" v-if="this_id!=''">
|
||||||
|
<%-- <v-card class="mx-auto" outlined >
|
||||||
|
<keep-alive>
|
||||||
|
<component :is="currentView">
|
||||||
|
</component>
|
||||||
|
</keep-alive>
|
||||||
|
</v-card>--%>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</asp:Panel>
|
</asp:Panel>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,558 @@
|
|||||||
|
<template>
|
||||||
|
<div id="control-panel">
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>紙張大小</label><select id="paper-size" onchange="updateLayout()">
|
||||||
|
<option value="A4" data-w="210" data-h="297" selected>A4</option>
|
||||||
|
<option value="A3" data-w="297" data-h="420">A3</option>
|
||||||
|
<option value="B5" data-w="176" data-h="250">B5</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>紙張方向</label><select id="paper-orientation" onchange="updateLayout()">
|
||||||
|
<option value="portrait" selected>直向</option>
|
||||||
|
<option value="landscape">橫向</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>一次修改全部行距: <span id="global-margin-lbl">10</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="adjustAllMargins(-1)">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="global-margin-slide"
|
||||||
|
min="0"
|
||||||
|
max="80"
|
||||||
|
value="10"
|
||||||
|
oninput="changeAllMargins(this.value)" /><button onclick="adjustAllMargins(1)">+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<p style="
|
||||||
|
font-size: 11px;
|
||||||
|
color: #c0392b;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #fde8e7;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0;
|
||||||
|
">
|
||||||
|
💡 提示:在右側文字上【按滑鼠右鍵】觸發設定,面板固定顯示在左下角!
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<button class="action-btn"
|
||||||
|
style="background: #28a745"
|
||||||
|
onclick="saveData()">
|
||||||
|
1. 儲存至資料庫
|
||||||
|
</button>
|
||||||
|
<button class="action-btn" onclick="window.print()">
|
||||||
|
2. 產生 PDF / 列印
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="preview-container" onclick="hideFloatingMenu(event)">
|
||||||
|
<div id="paper-preview">
|
||||||
|
<div id="editor"
|
||||||
|
contenteditable="true"
|
||||||
|
oncontextmenu="rightClickLineTrack(event)">
|
||||||
|
<div style="
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 25px;
|
||||||
|
">
|
||||||
|
中元普渡祈福文疏
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div style="font-size: 16px; letter-spacing: 4px; margin-left: 12px">
|
||||||
|
今逢佳節齋供養,花果盡是素佳餚。
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 16px; margin-left: 12px">
|
||||||
|
誠心祈求風調雨順、國泰民安。
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div style="font-size: 14px; align-items: flex-end; margin-left: 30px">
|
||||||
|
歲次天運民國一一五[YEAR]年七[MONTH]月十五[DAY]日。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="line-floating-menu" onclick="event.stopPropagation()">
|
||||||
|
<h4 id="menu-header">✥ 拖拉此處移動面板</h4>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>字型大小: <span id="f-size-lbl">16</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'fontSize',
|
||||||
|
'f-size-slide',
|
||||||
|
'f-size-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-size-slide"
|
||||||
|
min="12"
|
||||||
|
max="60"
|
||||||
|
value="16"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'fontSize',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-size-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'fontSize',
|
||||||
|
'f-size-slide',
|
||||||
|
'f-size-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>字距: <span id="f-space-lbl">2</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'letterSpacing',
|
||||||
|
'f-space-slide',
|
||||||
|
'f-space-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-space-slide"
|
||||||
|
min="0"
|
||||||
|
max="25"
|
||||||
|
value="2"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'letterSpacing',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-space-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'letterSpacing',
|
||||||
|
'f-space-slide',
|
||||||
|
'f-space-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>行距(與左側): <span id="f-margin-lbl">10</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'marginLeft',
|
||||||
|
'f-margin-slide',
|
||||||
|
'f-margin-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-margin-slide"
|
||||||
|
min="0"
|
||||||
|
max="80"
|
||||||
|
value="10"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'marginLeft',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-margin-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'marginLeft',
|
||||||
|
'f-margin-slide',
|
||||||
|
'f-margin-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>垂直位置對齊</label>
|
||||||
|
<div class="menu-btn-group">
|
||||||
|
<button id="f-align-top"
|
||||||
|
onclick="adjustLineAlign('flex-start', this)">
|
||||||
|
上
|
||||||
|
</button><button id="f-align-center"
|
||||||
|
onclick="adjustLineAlign('center', this)">
|
||||||
|
中
|
||||||
|
</button><button id="f-align-bottom"
|
||||||
|
onclick="adjustLineAlign('flex-end', this)">
|
||||||
|
下
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
let currentTargetLine = null;
|
||||||
|
function updateLayout() {
|
||||||
|
const e = document.getElementById("paper-size"),
|
||||||
|
t = document.getElementById("paper-orientation"),
|
||||||
|
n = document.getElementById("paper-preview"),
|
||||||
|
a = document.getElementById("print-style"),
|
||||||
|
o = e.options[e.selectedIndex],
|
||||||
|
i = parseFloat(o.getAttribute("data-w")),
|
||||||
|
r = parseFloat(o.getAttribute("data-h")),
|
||||||
|
d = e.value,
|
||||||
|
l = t.value;
|
||||||
|
let s = "portrait" === l ? i : r,
|
||||||
|
c = "portrait" === l ? r : i;
|
||||||
|
((n.style.width = s + "mm"),
|
||||||
|
(n.style.height = c + "mm"),
|
||||||
|
(a.innerHTML = `@media print { @page { size: ${d} ${l}; margin: 0mm; } }`),
|
||||||
|
hideFloatingMenu());
|
||||||
|
}
|
||||||
|
function rightClickLineTrack(e) {
|
||||||
|
s
|
||||||
|
let t = e.target;
|
||||||
|
const n = document.getElementById("editor");
|
||||||
|
while (t && t.parentNode !== n && t !== n) {
|
||||||
|
t = t.parentNode;
|
||||||
|
}
|
||||||
|
if (!t || t === n || "DIV" !== t.tagName) return;
|
||||||
|
(e.preventDefault(),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
(currentTargetLine = t),
|
||||||
|
currentTargetLine.classList.add("selected-line"));
|
||||||
|
const a = window.getComputedStyle(currentTargetLine),
|
||||||
|
o = parseInt(a.fontSize) || 16;
|
||||||
|
((document.getElementById("f-size-slide").value = o),
|
||||||
|
(document.getElementById("f-size-lbl").innerText = o));
|
||||||
|
const i = "normal" === a.letterSpacing ? 0 : parseInt(a.letterSpacing);
|
||||||
|
((document.getElementById("f-space-slide").value = i),
|
||||||
|
(document.getElementById("f-space-lbl").innerText = i));
|
||||||
|
const r = parseInt(a.marginLeft) || 10;
|
||||||
|
((document.getElementById("f-margin-slide").value = r),
|
||||||
|
(document.getElementById("f-margin-lbl").innerText = r),
|
||||||
|
document
|
||||||
|
.querySelectorAll(".menu-btn-group button")
|
||||||
|
.forEach((e) => e.classList.remove("active")),
|
||||||
|
"flex-start" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-top").classList.add("active"),
|
||||||
|
"center" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-center").classList.add("active"),
|
||||||
|
"flex-end" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-bottom").classList.add("active"),
|
||||||
|
(document.getElementById("line-floating-menu").style.display =
|
||||||
|
"flex"));
|
||||||
|
}
|
||||||
|
function hideFloatingMenu(e) {
|
||||||
|
if (
|
||||||
|
e &&
|
||||||
|
("preview-container" === e.target.id ||
|
||||||
|
"paper-preview" === e.target.id)
|
||||||
|
) {
|
||||||
|
((document.getElementById("line-floating-menu").style.display =
|
||||||
|
"none"),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
(currentTargetLine = null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function adjustLineStyle(e, t, n, a) {
|
||||||
|
currentTargetLine &&
|
||||||
|
((currentTargetLine.style[e] = t),
|
||||||
|
(document.getElementById(n).innerText = a));
|
||||||
|
}
|
||||||
|
function stepSingleLine(e, t, n, a, o) {
|
||||||
|
if (currentTargetLine) {
|
||||||
|
const i = document.getElementById(t);
|
||||||
|
let r = parseInt(i.value) + a;
|
||||||
|
(r < parseInt(i.min) && (r = parseInt(i.min)),
|
||||||
|
r > parseInt(i.max) && (r = parseInt(i.max)),
|
||||||
|
(i.value = r),
|
||||||
|
adjustLineStyle(e, r + o, n, r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function changeAllMargins(e) {
|
||||||
|
((document.getElementById("global-margin-lbl").innerText = e),
|
||||||
|
document.querySelectorAll("#editor > div").forEach((t) => {
|
||||||
|
t.style.marginLeft = e + "px";
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function adjustAllMargins(e) {
|
||||||
|
const t = document.getElementById("global-margin-slide");
|
||||||
|
let n = parseInt(t.value) + e;
|
||||||
|
(n < parseInt(t.min) && (n = parseInt(t.min)),
|
||||||
|
n > parseInt(t.max) && (n = parseInt(t.max)),
|
||||||
|
(t.value = n),
|
||||||
|
changeAllMargins(n));
|
||||||
|
}
|
||||||
|
function adjustLineAlign(e, t) {
|
||||||
|
currentTargetLine &&
|
||||||
|
((currentTargetLine.style.alignItems = e),
|
||||||
|
document
|
||||||
|
.querySelectorAll(".menu-btn-group button")
|
||||||
|
.forEach((e) => e.classList.remove("active")),
|
||||||
|
t.classList.add("active"));
|
||||||
|
}
|
||||||
|
function saveData() {
|
||||||
|
((document.getElementById("line-floating-menu").style.display = "none"),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
console.log(document.getElementById("editor").innerHTML),
|
||||||
|
alert("已成功擷取 HTML 結構至 Console!"));
|
||||||
|
}
|
||||||
|
window.onload = function () {
|
||||||
|
updateLayout();
|
||||||
|
};
|
||||||
|
(function () {
|
||||||
|
const e = document.getElementById("line-floating-menu"),
|
||||||
|
t = document.getElementById("menu-header");
|
||||||
|
let n = !1,
|
||||||
|
a,
|
||||||
|
o;
|
||||||
|
(t.addEventListener("mousedown", (r) => {
|
||||||
|
const i = e.getBoundingClientRect();
|
||||||
|
((a = r.clientX - i.left),
|
||||||
|
(o = r.clientY - i.top),
|
||||||
|
r.target === t && ((n = !0), (e.style.position = "fixed")));
|
||||||
|
}),
|
||||||
|
document.addEventListener("mousemove", (t) => {
|
||||||
|
if (n) {
|
||||||
|
t.preventDefault();
|
||||||
|
let i = t.clientX - a,
|
||||||
|
r = t.clientY - o;
|
||||||
|
((e.style.left = i + "px"),
|
||||||
|
(e.style.top = r + "px"),
|
||||||
|
(e.style.bottom = "auto"));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
document.addEventListener("mouseup", () => (n = !1)));
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media print {
|
||||||
|
@page {
|
||||||
|
size: A4 portrait;
|
||||||
|
margin: 0mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Microsoft JhengHei", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#control-panel {
|
||||||
|
width: 240px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
input[type="range"] {
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.action-btn {
|
||||||
|
padding: 12px;
|
||||||
|
background: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview-container {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
background: #ddd;
|
||||||
|
padding: 20px;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paper-preview {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20mm;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
outline: none;
|
||||||
|
writing-mode: vertical-rl;
|
||||||
|
text-orient: upright;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div {
|
||||||
|
min-height: 1em;
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div:hover {
|
||||||
|
background: rgba(0, 123, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div.selected-line {
|
||||||
|
background: rgba(0, 123, 255, 0.1) !important;
|
||||||
|
box-shadow: 0 0 0 1px #ff7675;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line-floating-menu {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 280px;
|
||||||
|
background: #fff0f1;
|
||||||
|
border: 2px solid #ff7675;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 99999;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
width: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line-floating-menu h4 {
|
||||||
|
margin: 0;
|
||||||
|
color: #d63031;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: move;
|
||||||
|
background: #ffe4e6;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group button.active {
|
||||||
|
background: #28a745;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row button {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row button:hover {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row input[type="range"] {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
#control-panel,
|
||||||
|
#line-floating-menu {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
#preview-container {
|
||||||
|
background: #fff;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paper-preview {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
box-shadow: none;
|
||||||
|
/* 1. 移除原本的 flex 與置中設定,改為一般的區塊顯示 */
|
||||||
|
display: block !important;
|
||||||
|
/* 2. 透過 padding 設定您需要的上邊界與右邊界 (數值可自由調整) */
|
||||||
|
padding-top: 30mm !important; /* 控制上方留白 */
|
||||||
|
padding-right: 30mm !important; /* 控制右側留白 */
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
/* padding: 0;
|
||||||
|
display: flex !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
align-items: center !important; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
height: auto !important;
|
||||||
|
/* width: auto !important; 加入這行,讓寬度貼合內容 */
|
||||||
|
max-height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,558 @@
|
|||||||
|
<template>
|
||||||
|
<div id="control-panel">
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label>紙張大小</label><select id="paper-size" onchange="updateLayout()">
|
||||||
|
<option value="A4" data-w="210" data-h="297" selected>A4</option>
|
||||||
|
<option value="A3" data-w="297" data-h="420">A3</option>
|
||||||
|
<option value="B5" data-w="176" data-h="250">B5</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>紙張方向</label><select id="paper-orientation" onchange="updateLayout()">
|
||||||
|
<option value="portrait" selected>直向</option>
|
||||||
|
<option value="landscape">橫向</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>一次修改全部行距: <span id="global-margin-lbl">10</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="adjustAllMargins(-1)">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="global-margin-slide"
|
||||||
|
min="0"
|
||||||
|
max="80"
|
||||||
|
value="10"
|
||||||
|
oninput="changeAllMargins(this.value)" /><button onclick="adjustAllMargins(1)">+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<p style="
|
||||||
|
font-size: 11px;
|
||||||
|
color: #c0392b;
|
||||||
|
font-weight: 700;
|
||||||
|
background: #fde8e7;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0;
|
||||||
|
">
|
||||||
|
💡 提示:在右側文字上【按滑鼠右鍵】觸發設定,面板固定顯示在左下角!
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<button class="action-btn"
|
||||||
|
style="background: #28a745"
|
||||||
|
onclick="saveData()">
|
||||||
|
1. 儲存至資料庫
|
||||||
|
</button>
|
||||||
|
<button class="action-btn" onclick="window.print()">
|
||||||
|
2. 產生 PDF / 列印
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="preview-container" onclick="hideFloatingMenu(event)">
|
||||||
|
<div id="paper-preview">
|
||||||
|
<div id="editor"
|
||||||
|
contenteditable="true"
|
||||||
|
oncontextmenu="rightClickLineTrack(event)">
|
||||||
|
<div style="
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 25px;
|
||||||
|
">
|
||||||
|
中元普渡祈福文疏
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div style="font-size: 16px; letter-spacing: 4px; margin-left: 12px">
|
||||||
|
今逢佳節齋供養,花果盡是素佳餚。
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 16px; margin-left: 12px">
|
||||||
|
誠心祈求風調雨順、國泰民安。
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
<div style="font-size: 14px; align-items: flex-end; margin-left: 30px">
|
||||||
|
歲次天運民國一一五[YEAR]年七[MONTH]月十五[DAY]日。
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="line-floating-menu" onclick="event.stopPropagation()">
|
||||||
|
<h4 id="menu-header">✥ 拖拉此處移動面板</h4>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>字型大小: <span id="f-size-lbl">16</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'fontSize',
|
||||||
|
'f-size-slide',
|
||||||
|
'f-size-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-size-slide"
|
||||||
|
min="12"
|
||||||
|
max="60"
|
||||||
|
value="16"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'fontSize',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-size-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'fontSize',
|
||||||
|
'f-size-slide',
|
||||||
|
'f-size-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>字距: <span id="f-space-lbl">2</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'letterSpacing',
|
||||||
|
'f-space-slide',
|
||||||
|
'f-space-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-space-slide"
|
||||||
|
min="0"
|
||||||
|
max="25"
|
||||||
|
value="2"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'letterSpacing',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-space-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'letterSpacing',
|
||||||
|
'f-space-slide',
|
||||||
|
'f-space-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>行距(與左側): <span id="f-margin-lbl">10</span>px</label>
|
||||||
|
<div class="adjust-row">
|
||||||
|
<button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'marginLeft',
|
||||||
|
'f-margin-slide',
|
||||||
|
'f-margin-lbl',
|
||||||
|
-1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
-
|
||||||
|
</button><input type="range"
|
||||||
|
id="f-margin-slide"
|
||||||
|
min="0"
|
||||||
|
max="80"
|
||||||
|
value="10"
|
||||||
|
oninput="
|
||||||
|
adjustLineStyle(
|
||||||
|
'marginLeft',
|
||||||
|
this.value + 'px',
|
||||||
|
'f-margin-lbl',
|
||||||
|
this.value,
|
||||||
|
)
|
||||||
|
" /><button onclick="
|
||||||
|
stepSingleLine(
|
||||||
|
'marginLeft',
|
||||||
|
'f-margin-slide',
|
||||||
|
'f-margin-lbl',
|
||||||
|
1,
|
||||||
|
'px',
|
||||||
|
)
|
||||||
|
">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label>垂直位置對齊</label>
|
||||||
|
<div class="menu-btn-group">
|
||||||
|
<button id="f-align-top"
|
||||||
|
onclick="adjustLineAlign('flex-start', this)">
|
||||||
|
上
|
||||||
|
</button><button id="f-align-center"
|
||||||
|
onclick="adjustLineAlign('center', this)">
|
||||||
|
中
|
||||||
|
</button><button id="f-align-bottom"
|
||||||
|
onclick="adjustLineAlign('flex-end', this)">
|
||||||
|
下
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
let currentTargetLine = null;
|
||||||
|
function updateLayout() {
|
||||||
|
const e = document.getElementById("paper-size"),
|
||||||
|
t = document.getElementById("paper-orientation"),
|
||||||
|
n = document.getElementById("paper-preview"),
|
||||||
|
a = document.getElementById("print-style"),
|
||||||
|
o = e.options[e.selectedIndex],
|
||||||
|
i = parseFloat(o.getAttribute("data-w")),
|
||||||
|
r = parseFloat(o.getAttribute("data-h")),
|
||||||
|
d = e.value,
|
||||||
|
l = t.value;
|
||||||
|
let s = "portrait" === l ? i : r,
|
||||||
|
c = "portrait" === l ? r : i;
|
||||||
|
((n.style.width = s + "mm"),
|
||||||
|
(n.style.height = c + "mm"),
|
||||||
|
(a.innerHTML = `@media print { @page { size: ${d} ${l}; margin: 0mm; } }`),
|
||||||
|
hideFloatingMenu());
|
||||||
|
}
|
||||||
|
function rightClickLineTrack(e) {
|
||||||
|
s
|
||||||
|
let t = e.target;
|
||||||
|
const n = document.getElementById("editor");
|
||||||
|
while (t && t.parentNode !== n && t !== n) {
|
||||||
|
t = t.parentNode;
|
||||||
|
}
|
||||||
|
if (!t || t === n || "DIV" !== t.tagName) return;
|
||||||
|
(e.preventDefault(),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
(currentTargetLine = t),
|
||||||
|
currentTargetLine.classList.add("selected-line"));
|
||||||
|
const a = window.getComputedStyle(currentTargetLine),
|
||||||
|
o = parseInt(a.fontSize) || 16;
|
||||||
|
((document.getElementById("f-size-slide").value = o),
|
||||||
|
(document.getElementById("f-size-lbl").innerText = o));
|
||||||
|
const i = "normal" === a.letterSpacing ? 0 : parseInt(a.letterSpacing);
|
||||||
|
((document.getElementById("f-space-slide").value = i),
|
||||||
|
(document.getElementById("f-space-lbl").innerText = i));
|
||||||
|
const r = parseInt(a.marginLeft) || 10;
|
||||||
|
((document.getElementById("f-margin-slide").value = r),
|
||||||
|
(document.getElementById("f-margin-lbl").innerText = r),
|
||||||
|
document
|
||||||
|
.querySelectorAll(".menu-btn-group button")
|
||||||
|
.forEach((e) => e.classList.remove("active")),
|
||||||
|
"flex-start" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-top").classList.add("active"),
|
||||||
|
"center" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-center").classList.add("active"),
|
||||||
|
"flex-end" === a.alignItems &&
|
||||||
|
document.getElementById("f-align-bottom").classList.add("active"),
|
||||||
|
(document.getElementById("line-floating-menu").style.display =
|
||||||
|
"flex"));
|
||||||
|
}
|
||||||
|
function hideFloatingMenu(e) {
|
||||||
|
if (
|
||||||
|
e &&
|
||||||
|
("preview-container" === e.target.id ||
|
||||||
|
"paper-preview" === e.target.id)
|
||||||
|
) {
|
||||||
|
((document.getElementById("line-floating-menu").style.display =
|
||||||
|
"none"),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
(currentTargetLine = null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function adjustLineStyle(e, t, n, a) {
|
||||||
|
currentTargetLine &&
|
||||||
|
((currentTargetLine.style[e] = t),
|
||||||
|
(document.getElementById(n).innerText = a));
|
||||||
|
}
|
||||||
|
function stepSingleLine(e, t, n, a, o) {
|
||||||
|
if (currentTargetLine) {
|
||||||
|
const i = document.getElementById(t);
|
||||||
|
let r = parseInt(i.value) + a;
|
||||||
|
(r < parseInt(i.min) && (r = parseInt(i.min)),
|
||||||
|
r > parseInt(i.max) && (r = parseInt(i.max)),
|
||||||
|
(i.value = r),
|
||||||
|
adjustLineStyle(e, r + o, n, r));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function changeAllMargins(e) {
|
||||||
|
((document.getElementById("global-margin-lbl").innerText = e),
|
||||||
|
document.querySelectorAll("#editor > div").forEach((t) => {
|
||||||
|
t.style.marginLeft = e + "px";
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function adjustAllMargins(e) {
|
||||||
|
const t = document.getElementById("global-margin-slide");
|
||||||
|
let n = parseInt(t.value) + e;
|
||||||
|
(n < parseInt(t.min) && (n = parseInt(t.min)),
|
||||||
|
n > parseInt(t.max) && (n = parseInt(t.max)),
|
||||||
|
(t.value = n),
|
||||||
|
changeAllMargins(n));
|
||||||
|
}
|
||||||
|
function adjustLineAlign(e, t) {
|
||||||
|
currentTargetLine &&
|
||||||
|
((currentTargetLine.style.alignItems = e),
|
||||||
|
document
|
||||||
|
.querySelectorAll(".menu-btn-group button")
|
||||||
|
.forEach((e) => e.classList.remove("active")),
|
||||||
|
t.classList.add("active"));
|
||||||
|
}
|
||||||
|
function saveData() {
|
||||||
|
((document.getElementById("line-floating-menu").style.display = "none"),
|
||||||
|
currentTargetLine &&
|
||||||
|
currentTargetLine.classList.remove("selected-line"),
|
||||||
|
console.log(document.getElementById("editor").innerHTML),
|
||||||
|
alert("已成功擷取 HTML 結構至 Console!"));
|
||||||
|
}
|
||||||
|
window.onload = function () {
|
||||||
|
updateLayout();
|
||||||
|
};
|
||||||
|
(function () {
|
||||||
|
const e = document.getElementById("line-floating-menu"),
|
||||||
|
t = document.getElementById("menu-header");
|
||||||
|
let n = !1,
|
||||||
|
a,
|
||||||
|
o;
|
||||||
|
(t.addEventListener("mousedown", (r) => {
|
||||||
|
const i = e.getBoundingClientRect();
|
||||||
|
((a = r.clientX - i.left),
|
||||||
|
(o = r.clientY - i.top),
|
||||||
|
r.target === t && ((n = !0), (e.style.position = "fixed")));
|
||||||
|
}),
|
||||||
|
document.addEventListener("mousemove", (t) => {
|
||||||
|
if (n) {
|
||||||
|
t.preventDefault();
|
||||||
|
let i = t.clientX - a,
|
||||||
|
r = t.clientY - o;
|
||||||
|
((e.style.left = i + "px"),
|
||||||
|
(e.style.top = r + "px"),
|
||||||
|
(e.style.bottom = "auto"));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
document.addEventListener("mouseup", () => (n = !1)));
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media print {
|
||||||
|
@page {
|
||||||
|
size: A4 portrait;
|
||||||
|
margin: 0mm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Microsoft JhengHei", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#control-panel {
|
||||||
|
width: 240px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
input[type="range"] {
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.action-btn {
|
||||||
|
padding: 12px;
|
||||||
|
background: #007bff;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
#preview-container {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
background: #ddd;
|
||||||
|
padding: 20px;
|
||||||
|
overflow: auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paper-preview {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20mm;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
outline: none;
|
||||||
|
writing-mode: vertical-rl;
|
||||||
|
text-orient: upright;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div {
|
||||||
|
min-height: 1em;
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-left: 10px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div:hover {
|
||||||
|
background: rgba(0, 123, 255, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor > div.selected-line {
|
||||||
|
background: rgba(0, 123, 255, 0.1) !important;
|
||||||
|
box-shadow: 0 0 0 1px #ff7675;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line-floating-menu {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 280px;
|
||||||
|
background: #fff0f1;
|
||||||
|
border: 2px solid #ff7675;
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 99999;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
width: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#line-floating-menu h4 {
|
||||||
|
margin: 0;
|
||||||
|
color: #d63031;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: move;
|
||||||
|
background: #ffe4e6;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn-group button.active {
|
||||||
|
background: #28a745;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #28a745;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row button {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row button:hover {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.adjust-row input[type="range"] {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
#control-panel,
|
||||||
|
#line-floating-menu {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
#preview-container {
|
||||||
|
background: #fff;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#paper-preview {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
box-shadow: none;
|
||||||
|
/* 1. 移除原本的 flex 與置中設定,改為一般的區塊顯示 */
|
||||||
|
display: block !important;
|
||||||
|
/* 2. 透過 padding 設定您需要的上邊界與右邊界 (數值可自由調整) */
|
||||||
|
padding-top: 30mm !important; /* 控制上方留白 */
|
||||||
|
padding-right: 30mm !important; /* 控制右側留白 */
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
padding-left: 0 !important;
|
||||||
|
/* padding: 0;
|
||||||
|
display: flex !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
align-items: center !important; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor {
|
||||||
|
height: auto !important;
|
||||||
|
/* width: auto !important; 加入這行,讓寬度貼合內容 */
|
||||||
|
max-height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user