2026-04-18-18-08-37 - 编辑器工具栏新增字号行距选择、修复字体选择、模板排版间距调整

This commit is contained in:
Administrator
2026-04-18 18:13:07 +08:00
parent 55ce78d898
commit db1c11f7eb
6 changed files with 339 additions and 12 deletions

View File

@@ -505,6 +505,19 @@ export default function ReportEditor() {
saveDraftToStorage();
};
const changeLineHeight = (height: string) => {
const sel = window.getSelection();
if (!sel || !sel.rangeCount) return;
let node = sel.getRangeAt(0).commonAncestorContainer;
if (node.nodeType === Node.TEXT_NODE) node = node.parentNode as Node;
const block = (node as HTMLElement).closest('p, div, td, h1, h2, h3, li');
if (block) {
(block as HTMLElement).style.lineHeight = height;
if (editorRef.current) contentRef.current = editorRef.current.innerHTML;
saveDraftToStorage();
}
};
const insertTable = () => {
editorRef.current?.focus();
setTableModal({ isOpen: true, rows: '2', cols: '3' });
@@ -1313,6 +1326,7 @@ export default function ReportEditor() {
</div>
<div className="flex gap-1 pr-3 mr-3 border-r border-border">
<select
onMouseDown={(e) => e.preventDefault()}
onChange={(e) => { execCmd('fontName', e.target.value); e.target.value = ''; }}
className="h-9 px-3 border border-border rounded-lg text-xs bg-white cursor-pointer focus:outline-hidden focus:border-accent"
>
@@ -1322,6 +1336,27 @@ export default function ReportEditor() {
<option value="SimHei"></option>
<option value="KaiTi"></option>
</select>
<select
onMouseDown={(e) => e.preventDefault()}
onChange={(e) => { if (e.target.value) { execCmd('fontSize', e.target.value); } e.target.value = ''; }}
className="h-9 px-3 border border-border rounded-lg text-xs bg-white cursor-pointer focus:outline-hidden focus:border-accent"
>
<option value=""></option>
<option value="3">12pt</option>
<option value="4">14pt</option>
<option value="5">18pt</option>
<option value="6">24pt</option>
</select>
<select
onMouseDown={(e) => e.preventDefault()}
onChange={(e) => { if (e.target.value) { changeLineHeight(e.target.value); } e.target.value = ''; }}
className="h-9 px-3 border border-border rounded-lg text-xs bg-white cursor-pointer focus:outline-hidden focus:border-accent"
>
<option value=""></option>
<option value="1">1.0</option>
<option value="1.5">1.5</option>
<option value="2">2.0</option>
</select>
</div>
<div className="flex gap-1 pr-3 mr-3 border-r border-border">
<button onClick={() => execCmd('bold')} className="w-9 h-9 flex items-center justify-center rounded-lg hover:bg-white text-text-muted hover:text-text-main transition-colors" title="粗体"><Bold size={16} /></button>

View File

@@ -359,6 +359,18 @@ export default function TemplateManage() {
editorRef.current?.focus();
};
const changeLineHeight = (height: string) => {
const sel = window.getSelection();
if (!sel || !sel.rangeCount) return;
let node = sel.getRangeAt(0).commonAncestorContainer;
if (node.nodeType === Node.TEXT_NODE) node = node.parentNode as Node;
const block = (node as HTMLElement).closest('p, div, td, h1, h2, h3, li');
if (block) {
(block as HTMLElement).style.lineHeight = height;
saveTemplateContent();
}
};
const saveTemplateContent = () => {
if (!currentTemplateId || !editorRef.current) return;
const allTemplates = storage.get<Template[]>('templates', []);
@@ -739,6 +751,27 @@ export default function TemplateManage() {
<option value="SimHei"></option>
<option value="KaiTi"></option>
</select>
<select
onMouseDown={(e) => e.preventDefault()}
onChange={(e) => { if (e.target.value) { execCmd('fontSize', e.target.value); } e.target.value = ''; }}
className="h-9 px-3 border border-border rounded-lg text-xs bg-white cursor-pointer focus:outline-hidden focus:border-accent"
>
<option value=""></option>
<option value="3">12pt</option>
<option value="4">14pt</option>
<option value="5">18pt</option>
<option value="6">24pt</option>
</select>
<select
onMouseDown={(e) => e.preventDefault()}
onChange={(e) => { if (e.target.value) { changeLineHeight(e.target.value); } e.target.value = ''; }}
className="h-9 px-3 border border-border rounded-lg text-xs bg-white cursor-pointer focus:outline-hidden focus:border-accent"
>
<option value=""></option>
<option value="1">1.0</option>
<option value="1.5">1.5</option>
<option value="2">2.0</option>
</select>
</div>
<div className="flex gap-1 pr-3 mr-3 border-r border-border">
<button onMouseDown={(e) => e.preventDefault()} onClick={() => execCmd('bold')} className="w-9 h-9 flex items-center justify-center rounded-lg hover:bg-white text-text-muted hover:text-text-main transition-colors" title="粗体"><Bold size={16} /></button>

View File

@@ -1,7 +1,7 @@
const smartField = (key: string) => `<span class="smart-field-wrapper" contenteditable="false" style="white-space:nowrap;position:relative;"><span class="field-value" data-bind="${key}" contenteditable="true" style="min-width:32px;padding:0 4px;margin:0 2px;border:1px solid #cbd5e1;border-radius:2px;display:inline-block;background:#f8fafc;color:#0f172a;line-height:1.2;font-size:inherit;vertical-align:text-bottom;box-sizing:border-box;min-height:1.2em;outline:none;"> </span><span class="delete-btn" contenteditable="false">×</span></span>&#8203;`;
export const defaultReportContent = `
<div style="display: flex; justify-content: center; align-items: center; gap: 12px; margin-bottom: 16px;">
<div style="display: flex; justify-content: center; align-items: center; gap: 12px; margin-bottom: 4px;">
<span class="image-placeholder" data-placeholder="true" contenteditable="false" data-mode="manual" style="position:relative;display:inline-flex;align-items:center;justify-content:center;width:65px;height:65px;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;cursor:pointer;">
<span class="delete-btn" contenteditable="false">×</span>
<span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">插入图片</span>
@@ -34,7 +34,7 @@ export const defaultReportContent = `
<strong>手术名称:</strong>${smartField('title')}
</p>
<table style="width: 100%; border: none; font-family: SimSun; font-size: 12pt; margin-bottom: 12pt;">
<table style="width: 100%; border: none; font-family: SimSun; font-size: 12pt; margin-top: 0; margin-bottom: 0;">
<tr>
<td style="border: none; padding: 0; width: 50%; line-height: 1.5;">手术开始时间:${smartField('startTime')}</td>
<td style="border: none; padding: 0; width: 50%; line-height: 1.5;">手术终止时间:${smartField('endTime')}</td>
@@ -53,23 +53,23 @@ export const defaultReportContent = `
<strong>手术步骤、术中出现的情况及处理:</strong>
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
1患者仰卧位麻醉成功后常规消毒术野、铺无菌巾于脐下穿刺建立CO2气腹气腹压力为12mmHg进镜探查无穿刺损伤分别于剑突下2.0cm、右锁中线肋缘下2.0cm各点穿刺置穿刺器,插入相应手术器械。
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
2腹腔镜探查腹腔内无腹水形成无明显粘连肝脏色红质软无明显结节硬化改变胆囊大小约 cm× cm× cm壁轻度水肿张力可胆囊三角解剖关系清楚胆囊管及胆总管无明显扩张。胃、十二指肠、小肠、结肠、脾脏及盆腔未见明显异常。术中诊断胆囊结石伴慢性胆囊炎。遂行腹腔镜胆囊切除术。
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
3.切除胆囊钳夹胆囊颈部并解剖胆囊三角游离出胆囊动脉及胆囊管明确胆囊与胆总管的关系距胆总管0.3cm处近端以一枚可吸收夹,远端夹一枚钛夹夹闭胆囊管,两夹间以剪刀剪断胆囊管,另用一枚可吸收夹夹闭胆囊动脉后离断。顺行游离胆囊浆膜,完整切除胆囊后装入标本袋取出。胆囊床严密止血并覆盖止血材料。
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
4.检查腹腔内无活动性出血及漏胆后,清点器械纱布无误,拔除腔镜器械,排出腹腔残余气体,缝合各刺孔,术毕。
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
5.手术顺利,麻醉满意。切除的标本经家属过目后送病理。术中出血约 ml术中输血成分输血量是否有输血不良反应。
</p>
@@ -124,23 +124,23 @@ export const defaultReportContent = `
</table>
<div class="template-info-section">
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
<strong>手术后情况</strong>${smartField('postOpCondition')}
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
<strong>切除标本描述</strong>${smartField('specimenDescription')}
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
<strong>是否送病理检查</strong>${smartField('pathologyCheck')}
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
<strong>冰冻病理结果</strong>${smartField('frozenPathology')}
</p>
<p style="font-family: SimSun; line-height: 1.5; margin: 0; padding: 0;">
<p style="font-family: SimSun; font-size: 12pt; line-height: 1.5; margin: 0; padding: 0;">
手术者签名:<span class="image-placeholder" data-placeholder="true" contenteditable="false" data-mode="manual" style="display:inline-flex;align-items:center;justify-content:center;width:200px;height:40px;border:1px dashed #cbd5e1;background:#f8fafc;vertical-align:middle;margin:0 4px;cursor:pointer;"><span class="delete-btn" contenteditable="false">×</span><span class="placeholder-text" style="color:#94a3b8;font-size:11px;pointer-events:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;">插入/点击放置图片</span></span>
</p>