完美
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/src/assets/logo.svg" />
|
<link rel="icon" type="image/svg+xml" href="/src/assets/logo.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, maximum-scale=1.0, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, maximum-scale=1.0, user-scalable=no" />
|
||||||
<title>智能标签排版设计与打印生成器</title>
|
<title>标签设计生成器</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "批量标签排版设计与打印生成器",
|
|
||||||
"description": "支持可视化绘制条码、二维码及多行文本标签模版,支持Excel/CSV数据批量导入与动态变量映射排版,一键平衡居中生成A4多页精细网格裁切图层,实现工业级无卷曲实体打印。",
|
|
||||||
"requestFramePermissions": [],
|
|
||||||
"majorCapabilities": ["MAJOR_CAPABILITY_SERVER_SIDE_GEMINI_API"]
|
|
||||||
}
|
|
||||||
146
src/App.tsx
146
src/App.tsx
@@ -30,6 +30,7 @@ import {
|
|||||||
Plus,
|
Plus,
|
||||||
Download,
|
Download,
|
||||||
Upload,
|
Upload,
|
||||||
|
Printer,
|
||||||
Trash2,
|
Trash2,
|
||||||
X,
|
X,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
@@ -639,10 +640,10 @@ export default function App() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`min-h-screen flex flex-col font-sans ${workflowStep === 'template-design' || (workflowStep === 'print-view' && !isMobile)
|
className={`min-h-screen flex flex-col font-sans ${workflowStep === 'template-design' || (workflowStep === 'print-view' && !isMobile)
|
||||||
? 'bg-[#323232] text-[#e8e8e8] h-screen overflow-hidden'
|
? 'bg-[#323232] text-[#e8e8e8] h-screen overflow-hidden'
|
||||||
: workflowStep === 'print-view' && isMobile
|
: workflowStep === 'print-view' && isMobile
|
||||||
? 'bg-slate-100 text-slate-800 h-screen overflow-hidden'
|
? 'bg-slate-100 text-slate-800 h-screen overflow-hidden'
|
||||||
: 'bg-slate-50 text-slate-800'
|
: 'bg-slate-50 text-slate-800'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/*
|
{/*
|
||||||
@@ -652,36 +653,55 @@ export default function App() {
|
|||||||
*/}
|
*/}
|
||||||
{!(isMobile && workflowStep === 'print-view') && (
|
{!(isMobile && workflowStep === 'print-view') && (
|
||||||
<header
|
<header
|
||||||
className={`no-print bg-slate-950 border-b border-slate-900 shrink-0 shadow flex flex-wrap items-center justify-between gap-4 mobile-template-header ${workflowStep === 'template-design' || workflowStep === 'print-view' ? 'px-4 py-2' : 'px-4 py-3 md:px-6 md:py-4'
|
className={`no-print bg-slate-950 border-b border-slate-900 shrink-0 shadow flex flex-wrap items-center justify-between gap-4 mobile-template-header ${
|
||||||
}`}
|
isMobile && workflowStep === 'template-select' && hasTemplates
|
||||||
|
? 'mobile-template-header-row'
|
||||||
|
: ''
|
||||||
|
} ${workflowStep === 'template-design' || workflowStep === 'print-view' ? 'px-4 py-2' : 'px-4 py-3 md:px-6 md:py-4'}`}
|
||||||
>
|
>
|
||||||
{/* Title logo and slogan description */}
|
{/* Title logo and slogan description */}
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
<div
|
||||||
|
className={`flex items-center gap-3 min-w-0 ${
|
||||||
|
isMobile && workflowStep === 'template-select' && hasTemplates ? 'flex-1' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<img src={logoUrl} alt="" className="w-10 h-10" aria-hidden />
|
<img src={logoUrl} alt="" className="w-10 h-10" aria-hidden />
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<h1 className="text-sm font-bold tracking-wider flex items-center gap-2 text-slate-100 uppercase">
|
<h1 className="text-[18px] font-bold tracking-wider flex items-center gap-2 text-slate-100 uppercase">
|
||||||
<span className="truncate">批量标签排版印刷生成器</span>
|
<span className="truncate">标签设计生成器</span>
|
||||||
</h1>
|
</h1>
|
||||||
{workflowStep !== 'template-design' && workflowStep !== 'print-view' && (
|
{workflowStep !== 'template-design' && workflowStep !== 'print-view' && (
|
||||||
<p className="text-[11px] text-slate-400">
|
<p className="text-[11px] text-slate-400">
|
||||||
所见即所得,上传Excel批量排版生成标签
|
所见即所得
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workflowStep === 'template-select' && hasTemplates && !isMobile && (
|
{workflowStep === 'template-select' && hasTemplates && (
|
||||||
<div className="flex flex-wrap items-center gap-2 shrink-0">
|
<div
|
||||||
<button
|
className={`flex items-center gap-2 shrink-0 ${
|
||||||
type="button"
|
isMobile ? 'ml-auto' : 'flex-wrap'
|
||||||
onClick={() => setShowAddTmplForm(true)}
|
}`}
|
||||||
className="inline-flex items-center gap-1.5 px-4 py-2 bg-indigo-600 text-white rounded-xl text-xs font-semibold whitespace-nowrap transition hover:bg-indigo-700 shadow-sm cursor-pointer"
|
>
|
||||||
|
{!isMobile && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowAddTmplForm(true)}
|
||||||
|
className="inline-flex items-center gap-1.5 px-4 py-2 bg-indigo-600 text-white rounded-xl text-xs font-semibold whitespace-nowrap transition hover:bg-indigo-700 shadow-sm cursor-pointer"
|
||||||
|
>
|
||||||
|
<Plus className="w-4 h-4 shrink-0" />
|
||||||
|
新建模板
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<label
|
||||||
|
className={`inline-flex items-center gap-1.5 bg-white/10 hover:bg-white/15 active:bg-white/20 border border-slate-700 text-slate-100 rounded-xl font-semibold whitespace-nowrap transition shadow-sm cursor-pointer ${
|
||||||
|
isMobile
|
||||||
|
? 'min-h-[40px] px-3 py-2 text-[11px]'
|
||||||
|
: 'px-4 py-2 text-xs'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4 shrink-0" />
|
<Upload className={`${isMobile ? 'w-3.5 h-3.5' : 'w-4 h-4'} shrink-0`} />
|
||||||
新建模板
|
|
||||||
</button>
|
|
||||||
<label className="inline-flex items-center gap-1.5 px-4 py-2 bg-white/10 hover:bg-white/15 border border-slate-700 text-slate-100 rounded-xl text-xs font-semibold whitespace-nowrap transition shadow-sm cursor-pointer">
|
|
||||||
<Upload className="w-4 h-4 shrink-0" />
|
|
||||||
导入模板
|
导入模板
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
@@ -698,8 +718,8 @@ export default function App() {
|
|||||||
{/* Primary Workspace scroll container */}
|
{/* Primary Workspace scroll container */}
|
||||||
<main
|
<main
|
||||||
className={`no-print flex-1 flex flex-col w-full ${workflowStep === 'template-design' || workflowStep === 'print-view'
|
className={`no-print flex-1 flex flex-col w-full ${workflowStep === 'template-design' || workflowStep === 'print-view'
|
||||||
? 'overflow-hidden min-h-0'
|
? 'overflow-hidden min-h-0'
|
||||||
: 'overflow-auto p-4 md:p-6 max-w-[1720px] mx-auto gap-6'
|
: 'overflow-auto p-4 md:p-6 max-w-[1720px] mx-auto gap-6'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
|
||||||
@@ -713,7 +733,7 @@ export default function App() {
|
|||||||
<h2 className="text-base font-bold text-gray-900">标签模板库</h2>
|
<h2 className="text-base font-bold text-gray-900">标签模板库</h2>
|
||||||
<p className="text-xs text-gray-400 mt-1">
|
<p className="text-xs text-gray-400 mt-1">
|
||||||
{isMobile
|
{isMobile
|
||||||
? '选择模板 → 上传 Excel → 关联变量 → 生成 PDF'
|
? '选择模板 → 上传 Excel → 关联变量 → 排版生成标签'
|
||||||
: '选择模板规格后进行设计与排版导出,或使用右上角按钮新建、导入模板。'}
|
: '选择模板规格后进行设计与排版导出,或使用右上角按钮新建、导入模板。'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -767,18 +787,19 @@ export default function App() {
|
|||||||
key={tmpl.id}
|
key={tmpl.id}
|
||||||
onClick={() => handleSelectTemplate(tmpl.id!)}
|
onClick={() => handleSelectTemplate(tmpl.id!)}
|
||||||
className={`bg-white border rounded-2xl p-5 shadow-xs transition-all flex flex-col cursor-pointer relative overflow-hidden group select-none ${isActive
|
className={`bg-white border rounded-2xl p-5 shadow-xs transition-all flex flex-col cursor-pointer relative overflow-hidden group select-none ${isActive
|
||||||
? 'ring-2 ring-indigo-500 border-indigo-500 bg-indigo-50/5'
|
// ? 'ring-2 ring-indigo-500 border-indigo-500 bg-indigo-50/5'
|
||||||
: 'border-gray-200 hover:shadow-md hover:border-indigo-200'
|
? 'border-gray-200 hover:shadow-md hover:border-indigo-200'
|
||||||
|
: 'border-gray-200 hover:shadow-md hover:border-indigo-200'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{isActive && (
|
{/* {isActive && (
|
||||||
<div
|
<div
|
||||||
className="absolute top-0 right-0 py-1.5 px-3 text-[10px] font-bold rounded-bl-xl text-white"
|
className="absolute top-0 right-0 py-1.5 px-3 text-[10px] font-bold rounded-bl-xl text-white"
|
||||||
style={{ backgroundColor: '#6366f1' }}
|
style={{ backgroundColor: '#6366f1' }}
|
||||||
>
|
>
|
||||||
当前选中
|
当前选中
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
|
|
||||||
<div className="space-y-1 pr-12 mb-3">
|
<div className="space-y-1 pr-12 mb-3">
|
||||||
<span className="text-[10px] font-mono font-extrabold text-indigo-700 bg-indigo-50 px-2 py-0.5 rounded-lg border border-indigo-100">
|
<span className="text-[10px] font-mono font-extrabold text-indigo-700 bg-indigo-50 px-2 py-0.5 rounded-lg border border-indigo-100">
|
||||||
@@ -834,36 +855,45 @@ export default function App() {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
openPrintView(tmpl.id!);
|
openPrintView(tmpl.id!);
|
||||||
}}
|
}}
|
||||||
className={`shrink-0 whitespace-nowrap inline-flex items-center gap-1 px-3 py-1.5 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg text-[11px] font-bold transition shadow-xs cursor-pointer ${isMobile ? 'mobile-primary-btn flex-1' : ''
|
className={`inline-flex items-center gap-1.5 bg-indigo-600 hover:bg-indigo-700 active:bg-indigo-800 text-white transition shadow-xs cursor-pointer ${
|
||||||
}`}
|
isMobile
|
||||||
|
? 'mobile-primary-btn flex-1 min-w-0 justify-center min-h-[44px] px-4 py-2.5 rounded-xl text-[13px] font-semibold'
|
||||||
|
: 'shrink-0 whitespace-nowrap px-3 py-1.5 rounded-lg text-[11px] font-bold'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
<FileDown className="w-3.5 h-3.5 shrink-0" />
|
<Printer className={`${isMobile ? 'w-4 h-4' : 'w-3.5 h-3.5'} shrink-0`} />
|
||||||
{isMobile ? '上传数据并导出 PDF' : '排版导出'}
|
{isMobile ? '排版生成标签' : '排版导出'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleExportTemplate(tmpl);
|
||||||
|
}}
|
||||||
|
className={`shrink-0 bg-gray-50 text-gray-500 hover:bg-gray-100 active:bg-gray-200 border border-gray-100 hover:border-gray-300 inline-flex items-center justify-center transition cursor-pointer ${
|
||||||
|
isMobile
|
||||||
|
? 'mobile-icon-btn min-w-[44px] min-h-[44px] rounded-xl'
|
||||||
|
: 'p-1.5 rounded-lg'
|
||||||
|
}`}
|
||||||
|
title="导出"
|
||||||
|
aria-label="导出模板"
|
||||||
|
>
|
||||||
|
<Download className={`${isMobile ? 'w-5 h-5' : 'w-3.5 h-3.5'}`} />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleDeleteTemplate(tmpl.id!);
|
||||||
|
}}
|
||||||
|
className={`shrink-0 bg-gray-50 text-rose-500 hover:text-white hover:bg-rose-600 active:bg-rose-700 border border-gray-100 inline-flex items-center justify-center transition cursor-pointer ${
|
||||||
|
isMobile
|
||||||
|
? 'mobile-icon-btn min-w-[44px] min-h-[44px] rounded-xl'
|
||||||
|
: 'p-1.5 rounded-lg'
|
||||||
|
}`}
|
||||||
|
title="删除模板"
|
||||||
|
aria-label="删除模板"
|
||||||
|
>
|
||||||
|
<Trash2 className={`${isMobile ? 'w-5 h-5' : 'w-3.5 h-3.5'}`} />
|
||||||
</button>
|
</button>
|
||||||
{!isMobile && (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
handleExportTemplate(tmpl);
|
|
||||||
}}
|
|
||||||
className="shrink-0 p-1.5 bg-gray-50 text-gray-500 hover:bg-gray-100 border border-gray-100 hover:border-gray-300 rounded-lg inline-flex items-center justify-center transition cursor-pointer"
|
|
||||||
title="导出"
|
|
||||||
>
|
|
||||||
<Download className="w-3.5 h-3.5" />
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
handleDeleteTemplate(tmpl.id!);
|
|
||||||
}}
|
|
||||||
className="shrink-0 p-1.5 bg-gray-50 text-rose-500 hover:text-white hover:bg-rose-600 border border-gray-100 rounded-lg inline-flex items-center justify-center transition cursor-pointer"
|
|
||||||
title="删除模板"
|
|
||||||
>
|
|
||||||
<Trash2 className="w-3.5 h-3.5" />
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -1014,8 +1044,8 @@ export default function App() {
|
|||||||
!appliedExportData || appliedLayoutResult.selectedCount === 0 || pdfGenerating
|
!appliedExportData || appliedLayoutResult.selectedCount === 0 || pdfGenerating
|
||||||
}
|
}
|
||||||
className={`inline-flex items-center gap-1.5 px-3 py-1 text-[11px] font-semibold transition cursor-pointer ${appliedExportData && appliedLayoutResult.selectedCount > 0 && !pdfGenerating
|
className={`inline-flex items-center gap-1.5 px-3 py-1 text-[11px] font-semibold transition cursor-pointer ${appliedExportData && appliedLayoutResult.selectedCount > 0 && !pdfGenerating
|
||||||
? 'bg-[#31a8ff] hover:bg-[#2890d8] text-white'
|
? 'bg-[#31a8ff] hover:bg-[#2890d8] text-white'
|
||||||
: 'bg-[#444] text-[#666] cursor-not-allowed'
|
: 'bg-[#444] text-[#666] cursor-not-allowed'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{pdfGenerating ? (
|
{pdfGenerating ? (
|
||||||
|
|||||||
@@ -1142,6 +1142,14 @@ body,
|
|||||||
gap: 8px !important;
|
gap: 8px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-template-header.mobile-template-header-row {
|
||||||
|
flex-direction: row !important;
|
||||||
|
flex-wrap: nowrap !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: space-between !important;
|
||||||
|
gap: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mobile-template-header h1 span:first-child {
|
.mobile-template-header h1 span:first-child {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user