优化
This commit is contained in:
@@ -3,8 +3,6 @@ import {
|
||||
ChevronLeft,
|
||||
FileDown,
|
||||
Loader2,
|
||||
CheckCircle2,
|
||||
Circle,
|
||||
Database,
|
||||
Link2,
|
||||
Download,
|
||||
@@ -40,40 +38,13 @@ interface MobileExportViewProps {
|
||||
onChangeDraftExportRange: (range: ExportRangeConfig) => void;
|
||||
cutLine: CutLineConfig;
|
||||
onChangeCutLine: (cutLine: CutLineConfig) => void;
|
||||
dataStale: boolean;
|
||||
dataApplied: boolean;
|
||||
onApplyData: () => void;
|
||||
draftSelectedCount: number;
|
||||
appliedSelectedCount: number;
|
||||
appliedTotalPages: number;
|
||||
selectedCount: number;
|
||||
totalPages: number;
|
||||
pdfGenerating: boolean;
|
||||
onBack: () => void;
|
||||
onExportPdf: () => void;
|
||||
}
|
||||
|
||||
function StepBadge({
|
||||
done,
|
||||
active,
|
||||
number,
|
||||
}: {
|
||||
done: boolean;
|
||||
active: boolean;
|
||||
number: number;
|
||||
}) {
|
||||
if (done) {
|
||||
return (
|
||||
<span className="mobile-step-badge done">
|
||||
<CheckCircle2 className="w-3.5 h-3.5" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span className={`mobile-step-badge ${active ? 'active' : ''}`}>
|
||||
{active ? number : <Circle className="w-3 h-3 opacity-50" />}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
template,
|
||||
templateName,
|
||||
@@ -91,12 +62,8 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
onChangeDraftExportRange,
|
||||
cutLine,
|
||||
onChangeCutLine,
|
||||
dataStale,
|
||||
dataApplied,
|
||||
onApplyData,
|
||||
draftSelectedCount,
|
||||
appliedSelectedCount,
|
||||
appliedTotalPages,
|
||||
selectedCount,
|
||||
totalPages,
|
||||
pdfGenerating,
|
||||
onBack,
|
||||
onExportPdf,
|
||||
@@ -108,17 +75,13 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
const needsMapping = templateVariables.length > 0;
|
||||
const mappingComplete = !needsMapping || (hasData && mappedCount === templateVariables.length);
|
||||
|
||||
const currentStep = !hasData ? 1 : !mappingComplete ? 2 : 3;
|
||||
|
||||
const exportBlockedReason = !hasData
|
||||
? '请先上传 Excel 数据'
|
||||
: !mappingComplete
|
||||
? `还有 ${templateVariables.length - mappedCount} 个变量未关联`
|
||||
: dataStale || !dataApplied
|
||||
? '请先应用数据'
|
||||
: appliedSelectedCount === 0
|
||||
? '当前数据范围内无标签'
|
||||
: null;
|
||||
? `还有 ${templateVariables.length - mappedCount} 个变量未关联`
|
||||
: selectedCount === 0
|
||||
? '当前数据范围内无标签'
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="mobile-export-view">
|
||||
@@ -130,34 +93,16 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
<p className="mobile-export-title truncate">{templateName}</p>
|
||||
<p className="mobile-export-subtitle">
|
||||
{template.width}×{template.height} mm
|
||||
{hasData && dataApplied && !dataStale && (
|
||||
{hasData && selectedCount > 0 && (
|
||||
<span>
|
||||
{' '}
|
||||
· {appliedSelectedCount} 枚 · {appliedTotalPages} 页
|
||||
· {selectedCount} 枚 · {totalPages} 页
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="mobile-export-steps" aria-label="导出步骤">
|
||||
<div className={`mobile-export-step ${currentStep >= 1 ? 'active' : ''} ${hasData ? 'done' : ''}`}>
|
||||
<StepBadge done={hasData} active={currentStep === 1} number={1} />
|
||||
<span>数据</span>
|
||||
</div>
|
||||
<div className="mobile-export-step-line" />
|
||||
<div
|
||||
className={`mobile-export-step ${currentStep >= 2 ? 'active' : ''} ${mappingComplete && hasData ? 'done' : ''}`}
|
||||
>
|
||||
<StepBadge done={mappingComplete && hasData} active={currentStep === 2} number={2} />
|
||||
<span>关联</span>
|
||||
</div>
|
||||
<div className={`mobile-export-step ${currentStep >= 3 ? 'active' : ''}`}>
|
||||
<StepBadge done={dataApplied && !dataStale && mappingComplete} active={currentStep === 3} number={3} />
|
||||
<span>导出</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<main className="mobile-export-content">
|
||||
<section className="mobile-export-card">
|
||||
<div className="mobile-export-card-head">
|
||||
@@ -165,7 +110,7 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<div className="min-w-0">
|
||||
<h2>步骤 1 · 数据源</h2>
|
||||
<h2>数据源</h2>
|
||||
<p>{hasData ? '已上传,可设置数据范围' : '上传 Excel 或 CSV 文件'}</p>
|
||||
</div>
|
||||
<button
|
||||
@@ -189,36 +134,14 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
templateVariables={templateVariables}
|
||||
/>
|
||||
{hasData && (
|
||||
<>
|
||||
<DataRangeFields
|
||||
variant="mobile"
|
||||
exportRange={draftExportRange}
|
||||
onChangeExportRange={onChangeDraftExportRange}
|
||||
rows={rows}
|
||||
paper={paper}
|
||||
template={template}
|
||||
/>
|
||||
<div className="space-y-2 pt-1 border-t border-slate-100">
|
||||
{dataStale && (
|
||||
<p className="text-xs text-amber-600">数据或数据范围已变更,请先应用数据</p>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onApplyData}
|
||||
disabled={draftSelectedCount === 0}
|
||||
className={`w-full inline-flex items-center justify-center gap-2 min-h-[44px] px-4 rounded-xl text-sm font-semibold transition cursor-pointer ${
|
||||
draftSelectedCount > 0
|
||||
? dataStale || !dataApplied
|
||||
? 'bg-indigo-600 text-white active:bg-indigo-700'
|
||||
: 'bg-slate-100 text-slate-600 border border-slate-200'
|
||||
: 'bg-slate-100 text-slate-400 cursor-not-allowed'
|
||||
}`}
|
||||
>
|
||||
<Database className="w-4 h-4 shrink-0" />
|
||||
应用数据
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
<DataRangeFields
|
||||
variant="mobile"
|
||||
exportRange={draftExportRange}
|
||||
onChangeExportRange={onChangeDraftExportRange}
|
||||
rows={rows}
|
||||
paper={paper}
|
||||
template={template}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
@@ -228,7 +151,7 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
<div className="mobile-export-card-head">
|
||||
<Link2 className="w-4 h-4 text-indigo-500 shrink-0" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<h2>步骤 2 · 关联变量</h2>
|
||||
<h2>关联变量</h2>
|
||||
<p>
|
||||
{needsMapping
|
||||
? `已关联 ${mappedCount}/${templateVariables.length}`
|
||||
@@ -281,7 +204,7 @@ export const MobileExportView: React.FC<MobileExportViewProps> = ({
|
||||
<FileDown className="w-5 h-5 shrink-0" />
|
||||
{exportBlockedReason
|
||||
? '生成 PDF'
|
||||
: `生成 PDF(${appliedSelectedCount} 枚 · ${appliedTotalPages} 页)`}
|
||||
: `生成 PDF(${selectedCount} 枚 · ${totalPages} 页)`}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user