This commit is contained in:
iqudoo
2026-06-14 10:25:15 +08:00
parent ccb5b119de
commit 846061ab48
6 changed files with 56 additions and 11 deletions

View File

@@ -229,6 +229,13 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
[template.variableDefaults] [template.variableDefaults]
); );
const showReferencePreview = useMemo(
() =>
!!template.previewReferenceBackground &&
template.enablePreviewReferenceBackground !== false,
[template.previewReferenceBackground, template.enablePreviewReferenceBackground]
);
const localElementsRef = useRef<TemplateElement[] | null>(null); const localElementsRef = useRef<TemplateElement[] | null>(null);
/** 交互开始时的元素快照:拖动底图分层、缩放节流重绘 */ /** 交互开始时的元素快照:拖动底图分层、缩放节流重绘 */
const [interactionSnapshot, setInteractionSnapshot] = useState<TemplateElement[] | null>( const [interactionSnapshot, setInteractionSnapshot] = useState<TemplateElement[] | null>(
@@ -1654,10 +1661,10 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
<div <div
ref={canvasRef} ref={canvasRef}
className={`absolute inset-0 shadow-[0_2px_20px_rgba(0,0,0,0.5)] select-none overflow-hidden ${ className={`absolute inset-0 shadow-[0_2px_20px_rgba(0,0,0,0.5)] select-none overflow-hidden ${
template.previewReferenceBackground ? '' : 'bg-white' showReferencePreview ? '' : 'bg-white'
}`} }`}
> >
{template.previewReferenceBackground && ( {showReferencePreview && (
<img <img
src={template.previewReferenceBackground} src={template.previewReferenceBackground}
alt="" alt=""
@@ -1681,7 +1688,7 @@ export const LabelDesigner: React.FC<LabelDesignerProps> = ({
rowData={null} rowData={null}
rowIndex={0} rowIndex={0}
showBorder={false} showBorder={false}
transparentBackground={!!template.previewReferenceBackground} transparentBackground={showReferencePreview}
variableDefaults={previewDefaults} variableDefaults={previewDefaults}
renderScale={canvasRenderScale} renderScale={canvasRenderScale}
/> />

View File

@@ -858,7 +858,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
</h5> </h5>
<p className="text-[9px] text-[#777] leading-relaxed"> <p className="text-[9px] text-[#777] leading-relaxed">
便 /
</p> </p>
<label className="ps-btn text-[10px] cursor-pointer inline-flex"> <label className="ps-btn text-[10px] cursor-pointer inline-flex">
<Upload className="w-3.5 h-3.5" /> <Upload className="w-3.5 h-3.5" />
@@ -879,6 +879,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
template.previewReferenceBackgroundOpacity ?? 100, template.previewReferenceBackgroundOpacity ?? 100,
previewReferenceBackgroundFit: previewReferenceBackgroundFit:
template.previewReferenceBackgroundFit ?? 'cover', template.previewReferenceBackgroundFit ?? 'cover',
enablePreviewReferenceBackground: true,
}); });
reader.readAsDataURL(file); reader.readAsDataURL(file);
e.target.value = ''; e.target.value = '';
@@ -930,6 +931,25 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
className="w-full accent-[#31a8ff]" className="w-full accent-[#31a8ff]"
/> />
</div> </div>
<label className="flex items-start gap-2">
<input
type="checkbox"
checked={template.enablePreviewReferenceBackground !== false}
onChange={(e) =>
onChangeTemplate({
...template,
enablePreviewReferenceBackground: e.target.checked ? true : false,
})
}
className="ps-checkbox mt-0.5"
/>
<span className="text-xs text-[#ccc] leading-normal">
<span className="block text-[9px] text-[#777] mt-0.5">
</span>
</span>
</label>
<label className="flex items-start gap-2"> <label className="flex items-start gap-2">
<input <input
type="checkbox" type="checkbox"
@@ -957,6 +977,7 @@ export const PropSidebar: React.FC<PropSidebarProps> = ({
previewReferenceBackground: undefined, previewReferenceBackground: undefined,
previewReferenceBackgroundOpacity: undefined, previewReferenceBackgroundOpacity: undefined,
previewReferenceBackgroundFit: undefined, previewReferenceBackgroundFit: undefined,
enablePreviewReferenceBackground: undefined,
includeReferenceBackgroundInOutput: undefined, includeReferenceBackgroundInOutput: undefined,
}) })
} }

View File

@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { X } from 'lucide-react'; import { X } from 'lucide-react';
import { VisibilityRule } from '../types'; import { VisibilityRule } from '../types';
import { visibilityOperatorNeedsValue } from '../utils'; import { visibilityOperatorNeedsValue } from '../utils';
@@ -65,7 +66,7 @@ export const VisibilityRuleDialog: React.FC<VisibilityRuleDialogProps> = ({
return () => window.removeEventListener('keydown', onKeyDown); return () => window.removeEventListener('keydown', onKeyDown);
}, [open, onClose]); }, [open, onClose]);
if (!open) return null; if (!open || typeof document === 'undefined') return null;
const target = draft.target ?? 'variable'; const target = draft.target ?? 'variable';
const canConfirm = target === 'content' || draft.variable.trim().length > 0; const canConfirm = target === 'content' || draft.variable.trim().length > 0;
@@ -86,7 +87,7 @@ export const VisibilityRuleDialog: React.FC<VisibilityRuleDialogProps> = ({
onClose(); onClose();
}; };
return ( return createPortal(
<div className="ps-modal-overlay" onClick={onClose} role="presentation"> <div className="ps-modal-overlay" onClick={onClose} role="presentation">
<div <div
className="ps-modal" className="ps-modal"
@@ -131,6 +132,7 @@ export const VisibilityRuleDialog: React.FC<VisibilityRuleDialogProps> = ({
</div> </div>
</form> </form>
</div> </div>
</div> </div>,
document.body
); );
}; };

View File

@@ -590,7 +590,7 @@ html.app-dark-shell body {
.ps-modal-overlay { .ps-modal-overlay {
position: fixed; position: fixed;
inset: 0; inset: 0;
z-index: 9000; z-index: 10000;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;

View File

@@ -588,7 +588,10 @@ export type ReferenceBackgroundRenderOptions = Pick<
type ReferenceBackgroundTemplate = Pick< type ReferenceBackgroundTemplate = Pick<
LabelTemplate, LabelTemplate,
'previewReferenceBackground' | 'previewReferenceBackgroundOpacity' | 'previewReferenceBackgroundFit' | 'previewReferenceBackground'
| 'previewReferenceBackgroundOpacity'
| 'previewReferenceBackgroundFit'
| 'enablePreviewReferenceBackground'
>; >;
function buildReferenceBackgroundRenderOptions( function buildReferenceBackgroundRenderOptions(
@@ -597,6 +600,9 @@ function buildReferenceBackgroundRenderOptions(
if (!template.previewReferenceBackground) { if (!template.previewReferenceBackground) {
return {}; return {};
} }
if (template.enablePreviewReferenceBackground === false) {
return {};
}
return { return {
referenceBackground: template.previewReferenceBackground, referenceBackground: template.previewReferenceBackground,
referenceBackgroundOpacity: template.previewReferenceBackgroundOpacity ?? 100, referenceBackgroundOpacity: template.previewReferenceBackgroundOpacity ?? 100,
@@ -604,7 +610,7 @@ function buildReferenceBackgroundRenderOptions(
}; };
} }
/** 模板列表 / 设计预览等:参考图绘制 */ /** 模板列表 / 设计预览等:参考图且启用预览时绘制 */
export function resolveReferenceBackgroundForPreview( export function resolveReferenceBackgroundForPreview(
template: ReferenceBackgroundTemplate template: ReferenceBackgroundTemplate
): ReferenceBackgroundRenderOptions { ): ReferenceBackgroundRenderOptions {
@@ -619,7 +625,14 @@ export function resolveReferenceBackgroundForOutput(
if (!template.includeReferenceBackgroundInOutput) { if (!template.includeReferenceBackgroundInOutput) {
return {}; return {};
} }
return buildReferenceBackgroundRenderOptions(template); if (!template.previewReferenceBackground) {
return {};
}
return {
referenceBackground: template.previewReferenceBackground,
referenceBackgroundOpacity: template.previewReferenceBackgroundOpacity ?? 100,
referenceBackgroundFit: template.previewReferenceBackgroundFit ?? 'cover',
};
} }
/** 离屏渲染标签为 PNG data URL */ /** 离屏渲染标签为 PNG data URL */

View File

@@ -252,6 +252,8 @@ export interface LabelTemplate {
previewReferenceBackgroundOpacity?: number; previewReferenceBackgroundOpacity?: number;
/** 预览参考背景适应方式,默认 cover */ /** 预览参考背景适应方式,默认 cover */
previewReferenceBackgroundFit?: 'contain' | 'cover' | 'fill'; previewReferenceBackgroundFit?: 'contain' | 'cover' | 'fill';
/** 设计预览(画布、模板列表缩略图)是否显示参考背景,默认 true */
enablePreviewReferenceBackground?: boolean;
/** 生成 PDF / 打印 / 排版预览输出时是否绘制参考背景,默认 false */ /** 生成 PDF / 打印 / 排版预览输出时是否绘制参考背景,默认 false */
includeReferenceBackgroundInOutput?: boolean; includeReferenceBackgroundInOutput?: boolean;
/** 批量导出图片时的文件名模板,支持 {#SEQ}、{#INDEX}、{变量名};留空则按序号补零命名 */ /** 批量导出图片时的文件名模板,支持 {#SEQ}、{#INDEX}、{变量名};留空则按序号补零命名 */