fix(intake): 样包测量/产品限价/首批质检列宽整列联动(受控列宽)

This commit is contained in:
WuYongJie 2026-09-29 11:25:55 +08:00
parent 749c28452c
commit eb6fa9d672
11 changed files with 388 additions and 72 deletions

View File

@ -258,6 +258,8 @@ export function buildNonIntegratedCoreWorkspaceRenderers({
isProductFactorySkuConfirmed: workflowRows.isSkuItemFactoryConfirmed,
isSampleMeasurementSkuLocked:
workflowCompletion.isSampleMeasurementSkuLocked,
columnWidths: columnResize.sampleMeasurementColumnWidths,
onColumnResize: columnResize.handleSampleMeasurementColumnResize,
onUpdateRow: productWorkflowActions.updateSampleMeasurementRow,
},
finishedSampleShipment: {
@ -300,6 +302,8 @@ export function buildNonIntegratedCoreWorkspaceRenderers({
displayedRows: workflowRows.displayedProductLimitRows,
isReadOnly: editability.isReadOnly,
isNodeLocked: workflowConfirmation.isProductLimitNodeLocked,
columnWidths: columnResize.productLimitColumnWidths,
onColumnResize: columnResize.handleProductLimitColumnResize,
onUpdateRow: productWorkflowActions.updateProductLimitRow,
},
productPricing: {

View File

@ -94,6 +94,7 @@ export function buildNonIntegratedDetailRenderers({
const secondary = buildNonIntegratedSecondaryWorkspaceRenderers({
aiWhiteBackground: skuActions.aiWhiteBackground,
artifactState,
columnResize,
currentProductDisplayName: fileActions.currentProductDisplayName,
detailToast,
documentConfirmActions: documentActions.documentConfirmActions,

View File

@ -50,6 +50,10 @@ describe("buildNonIntegratedSecondaryWorkspaceRenderers", () => {
const result = buildNonIntegratedSecondaryWorkspaceRenderers({
aiWhiteBackground: {},
artifactState: {},
columnResize: {
firstQualityColumnWidths: {},
handleFirstQualityColumnResize: jest.fn(),
},
currentProductDisplayName: "测试产品",
detailToast: {},
documentConfirmActions: {},

View File

@ -19,6 +19,7 @@ import type { useNonIntegratedSkuReviewActionControllers } from "./useNonIntegra
import type { useNonIntegratedSkuState } from "./useNonIntegratedSkuState";
import type { useNonIntegratedWorkflowDerivedController } from "./useNonIntegratedWorkflowDerivedController";
import type { useNonIntegratedWorkflowState } from "./useNonIntegratedWorkflowState";
import type { useSkuColumnResizeController } from "./workspaces/basic-info/useSkuColumnResizeController";
import type { useToast } from "@/components/ui/Toast";
import type { buildNonIntegratedCoreWorkspaceRenderers } from "./buildNonIntegratedCoreWorkspaceRenderers";
@ -52,6 +53,7 @@ export type SecondaryWorkspaceRendererProps = Pick<
> & {
aiWhiteBackground: SkuReviewActionState["aiWhiteBackground"];
artifactState: ReturnType<typeof useNonIntegratedArtifactState>;
columnResize: ReturnType<typeof useSkuColumnResizeController>;
currentProductDisplayName: FileActionState["currentProductDisplayName"];
detailToast: ReturnType<typeof useToast>;
documentConfirmActions: DocumentActionState["documentConfirmActions"];
@ -92,6 +94,7 @@ export type SecondaryWorkspaceRendererProps = Pick<
export function buildNonIntegratedSecondaryWorkspaceRenderers({
aiWhiteBackground,
artifactState,
columnResize,
currentProductDisplayName,
detailToast,
documentConfirmActions,
@ -134,10 +137,10 @@ export function buildNonIntegratedSecondaryWorkspaceRenderers({
workspaceUploadActions,
}: SecondaryWorkspaceRendererProps) {
const documentWorkspaceRenderers =
buildNonIntegratedDocumentWorkspaceRendererState({
aiWhiteBackground,
artifactState,
detailToast,
buildNonIntegratedDocumentWorkspaceRendererState({
aiWhiteBackground,
artifactState,
detailToast,
documentDerived,
documentDownloads,
documentPresentation,
@ -167,6 +170,8 @@ export function buildNonIntegratedSecondaryWorkspaceRenderers({
inheritedSkuBatchTabs,
isReadOnly: editability.isReadOnly,
canDownloadWorkspaceFiles: permissionState.canDownloadWorkspaceFiles,
columnWidths: columnResize.firstQualityColumnWidths,
onColumnResize: columnResize.handleFirstQualityColumnResize,
onUpdateRow: productWorkflowActions.updateFirstQualityRow,
onUploadFiles: workspaceUploadActions.handleUploadFirstQualityFiles,
onDownloadFiles: documentDownloads.handleDownloadWorkspaceFiles,

View File

@ -8,8 +8,15 @@ import type {
import type { ProductFirstQualityDisplayRow } from "../firstQualityHelpers";
import { HoverImagePreview } from "../components/HoverImagePreview";
import { InlineSelect } from "../components/InlineControls";
import { SkuRowField } from "../components/SkuTableFields";
import {
SkuColumnResizableFrame,
SkuRowField,
} from "../components/SkuTableFields";
import { getStyleKeyFromModel } from "../styleFileHelpers";
import {
FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS,
type FirstQualityColumnWidthKey,
} from "./firstQualityColumnWidthConfig";
type FirstQualityFieldKey = Exclude<
keyof NonIntegratedFirstQualityRow,
@ -23,6 +30,11 @@ type FirstQualityWorkspaceProps = {
inheritedSkuBatchTabs: ReactNode;
isReadOnly: boolean;
canDownloadWorkspaceFiles: boolean;
columnWidths: Record<FirstQualityColumnWidthKey, number>;
onColumnResize: (
column: FirstQualityColumnWidthKey,
width: number,
) => void;
onUpdateRow: (
skuId: string,
key: FirstQualityFieldKey,
@ -38,18 +50,25 @@ type FirstQualityWorkspaceProps = {
function ReadOnlyCell({
value,
minWidth = "96px",
columnWidth,
minWidth,
onColumnResize,
}: {
value: string;
minWidth?: string;
columnWidth: number;
minWidth: number;
onColumnResize: (width: number) => void;
}) {
return (
<div
className="w-max whitespace-nowrap rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs text-apple-label-primary"
style={{ minWidth }}
<SkuColumnResizableFrame
columnWidth={columnWidth}
minWidth={minWidth}
onColumnResize={onColumnResize}
>
{value || "-"}
</div>
<div className="h-8 w-full overflow-hidden text-ellipsis whitespace-nowrap rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs text-apple-label-primary">
{value || "-"}
</div>
</SkuColumnResizableFrame>
);
}
@ -60,6 +79,8 @@ export function FirstQualityWorkspace({
inheritedSkuBatchTabs,
isReadOnly,
canDownloadWorkspaceFiles,
columnWidths,
onColumnResize,
onUpdateRow,
onUploadFiles,
onDownloadFiles,
@ -76,6 +97,39 @@ export function FirstQualityWorkspace({
});
};
const renderReadOnlyCell = (
column: FirstQualityColumnWidthKey,
value: string,
) => (
<ReadOnlyCell
value={value}
columnWidth={columnWidths[column]}
minWidth={FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS[column]}
onColumnResize={(width) => onColumnResize(column, width)}
/>
);
const renderDetailInput = (row: ProductFirstQualityDisplayRow) => (
<SkuColumnResizableFrame
columnWidth={columnWidths.detail}
minWidth={FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS.detail}
onColumnResize={(width) => onColumnResize("detail", width)}
>
<input
type="text"
value={row.detail}
readOnly={isReadOnly}
onChange={(event) => onUpdateRow(row.skuId, "detail", event.target.value)}
placeholder="填写首批质检详细说明"
className={`h-8 w-full min-w-0 rounded border border-apple-separator px-2 text-xs leading-8 outline-none ${
isReadOnly
? "bg-apple-bg-primary text-apple-label-secondary"
: "bg-[#eef1f4] text-apple-label-primary"
}`}
/>
</SkuColumnResizableFrame>
);
return (
<div
data-testid="factory-quality-workspace"
@ -179,34 +233,31 @@ export function FirstQualityWorkspace({
)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.model} />
{renderReadOnlyCell("model", row.model)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.skuCode} />
{renderReadOnlyCell("skuCode", row.skuCode)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.barcode} minWidth="132px" />
{renderReadOnlyCell("barcode", row.barcode)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.setCount} minWidth="64px" />
{renderReadOnlyCell("setCount", row.setCount)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.specName} minWidth="128px" />
{renderReadOnlyCell("specName", row.specName)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.size} minWidth="120px" />
{renderReadOnlyCell("size", row.size)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.color} minWidth="80px" />
{renderReadOnlyCell("color", row.color)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell value={row.material} minWidth="112px" />
{renderReadOnlyCell("material", row.material)}
</td>
<td className="px-3 py-2 align-middle">
<ReadOnlyCell
value={row.supplierName}
minWidth="104px"
/>
{renderReadOnlyCell("supplierName", row.supplierName)}
</td>
<td className="px-3 py-2 align-middle">
<SkuRowField
@ -215,6 +266,10 @@ export function FirstQualityWorkspace({
readOnly={isReadOnly}
mode="singleLineResizable"
tone="manual"
columnWidth={columnWidths.qualityBatch}
onColumnResize={(width) =>
onColumnResize("qualityBatch", width)
}
onChange={(value) =>
onUpdateRow(row.skuId, "qualityBatch", value)
}
@ -234,20 +289,7 @@ export function FirstQualityWorkspace({
/>
</td>
<td className="px-3 py-2 align-middle">
<input
type="text"
value={row.detail}
readOnly={isReadOnly}
onChange={(event) =>
onUpdateRow(row.skuId, "detail", event.target.value)
}
placeholder="填写首批质检详细说明"
className={`h-8 w-[220px] rounded border border-apple-separator px-2 text-xs leading-8 outline-none ${
isReadOnly
? "bg-apple-bg-primary text-apple-label-secondary"
: "bg-[#eef1f4] text-apple-label-primary"
}`}
/>
{renderDetailInput(row)}
</td>
<td className="px-3 py-2 align-middle">
<div className="flex min-w-[196px] items-center justify-center gap-1.5 whitespace-nowrap">

View File

@ -4,7 +4,14 @@ import type { ReactNode } from "react";
import type { NonIntegratedProductLimitRow } from "../nonIntegratedStorage";
import type { ProductLimitDisplayRow } from "../productWorkflowRowHelpers";
import { HoverImagePreview } from "../components/HoverImagePreview";
import { SkuRowField } from "../components/SkuTableFields";
import {
SkuColumnResizableFrame,
SkuRowField,
} from "../components/SkuTableFields";
import {
PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS,
type ProductLimitColumnWidthKey,
} from "./productLimitColumnWidthConfig";
type ProductLimitFieldKey = Exclude<
keyof NonIntegratedProductLimitRow,
@ -17,6 +24,11 @@ type ProductLimitWorkspaceProps = {
inheritedSkuBatchTabs: ReactNode;
isReadOnly: boolean;
isNodeLocked: boolean;
columnWidths: Record<ProductLimitColumnWidthKey, number>;
onColumnResize: (
column: ProductLimitColumnWidthKey,
width: number,
) => void;
onUpdateRow: (
skuId: string,
key: ProductLimitFieldKey,
@ -27,18 +39,25 @@ type ProductLimitWorkspaceProps = {
function ReadOnlyCell({
value,
minWidth = "112px",
columnWidth,
minWidth,
onColumnResize,
}: {
value: string;
minWidth?: string;
columnWidth: number;
minWidth: number;
onColumnResize: (width: number) => void;
}) {
return (
<div
className="rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs text-apple-label-primary"
style={{ minWidth }}
<SkuColumnResizableFrame
columnWidth={columnWidth}
minWidth={minWidth}
onColumnResize={onColumnResize}
>
{value || "-"}
</div>
<div className="h-8 w-full overflow-hidden text-ellipsis whitespace-nowrap rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs text-apple-label-primary">
{value || "-"}
</div>
</SkuColumnResizableFrame>
);
}
@ -48,6 +67,8 @@ export function ProductLimitWorkspace({
inheritedSkuBatchTabs,
isReadOnly,
isNodeLocked,
columnWidths,
onColumnResize,
onUpdateRow,
onPreviewImage,
}: ProductLimitWorkspaceProps) {
@ -79,6 +100,17 @@ export function ProductLimitWorkspace({
</HoverImagePreview>
);
};
const renderReadOnlyCell = (
column: ProductLimitColumnWidthKey,
value: string,
) => (
<ReadOnlyCell
value={value}
columnWidth={columnWidths[column]}
minWidth={PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS[column]}
onColumnResize={(width) => onColumnResize(column, width)}
/>
);
const renderLimitInput = (
row: ProductLimitDisplayRow,
key: ProductLimitFieldKey,
@ -91,6 +123,8 @@ export function ProductLimitWorkspace({
mode="singleLineResizable"
tone="manual"
testId={`product-limit-${key}-${row.skuId}`}
columnWidth={columnWidths[key]}
onColumnResize={(width) => onColumnResize(key, width)}
onChange={(value) => onUpdateRow(row.skuId, key, value)}
/>
);
@ -152,22 +186,22 @@ export function ProductLimitWorkspace({
>
<td className="px-3 py-2">{renderImageCell(row, index)}</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.spu} />
{renderReadOnlyCell("spu", row.spu)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.skuCode} />
{renderReadOnlyCell("skuCode", row.skuCode)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.barcode} minWidth="160px" />
{renderReadOnlyCell("barcode", row.barcode)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.setCount} minWidth="80px" />
{renderReadOnlyCell("setCount", row.setCount)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.specName} minWidth="160px" />
{renderReadOnlyCell("specName", row.specName)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.costPrice} minWidth="100px" />
{renderReadOnlyCell("costPrice", row.costPrice)}
</td>
<td className="px-3 py-2">
{renderLimitInput(

View File

@ -5,7 +5,14 @@ import type {
ProductSampleMeasurementDisplayRow,
SampleMeasurementEditableKey,
} from "../sampleWorkflowHelpers";
import { SkuRowField } from "../components/SkuTableFields";
import {
SkuColumnResizableFrame,
SkuRowField,
} from "../components/SkuTableFields";
import {
SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS,
type SampleMeasurementColumnWidthKey,
} from "./sampleMeasurementColumnWidthConfig";
type SampleMeasurementWorkspaceProps = {
allRows: ProductSampleMeasurementDisplayRow[];
@ -14,6 +21,11 @@ type SampleMeasurementWorkspaceProps = {
isReadOnly: boolean;
isProductFactorySkuConfirmed: (skuId: string) => boolean;
isSampleMeasurementSkuLocked: (skuId: string) => boolean;
columnWidths: Record<SampleMeasurementColumnWidthKey, number>;
onColumnResize: (
column: SampleMeasurementColumnWidthKey,
width: number,
) => void;
onUpdateRow: (
skuId: string,
key: SampleMeasurementEditableKey,
@ -23,22 +35,31 @@ type SampleMeasurementWorkspaceProps = {
function ReadOnlyCell({
value,
minWidth = "112px",
columnWidth,
minWidth,
onColumnResize,
testId,
}: {
value: string;
minWidth?: string;
columnWidth: number;
minWidth: number;
onColumnResize: (width: number) => void;
testId?: string;
}) {
return (
<div
data-testid={testId}
title={value || "-"}
style={{ minWidth, width: minWidth }}
className="h-8 max-w-none resize-none overflow-hidden text-ellipsis whitespace-nowrap rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs leading-5 text-apple-label-primary md:resize-x"
<SkuColumnResizableFrame
columnWidth={columnWidth}
minWidth={minWidth}
onColumnResize={onColumnResize}
>
{value || "-"}
</div>
<div
data-testid={testId}
title={value || "-"}
className="h-8 w-full overflow-hidden text-ellipsis whitespace-nowrap rounded border border-apple-separator bg-apple-bg-secondary px-2 py-1.5 text-xs leading-5 text-apple-label-primary"
>
{value || "-"}
</div>
</SkuColumnResizableFrame>
);
}
@ -49,8 +70,24 @@ export function SampleMeasurementWorkspace({
isReadOnly,
isProductFactorySkuConfirmed,
isSampleMeasurementSkuLocked,
columnWidths,
onColumnResize,
onUpdateRow,
}: SampleMeasurementWorkspaceProps) {
const renderReadOnlyCell = (
column: SampleMeasurementColumnWidthKey,
value: string,
testId?: string,
) => (
<ReadOnlyCell
value={value}
columnWidth={columnWidths[column]}
minWidth={SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS[column]}
onColumnResize={(width) => onColumnResize(column, width)}
testId={testId}
/>
);
const renderMeasurementInput = (
row: ProductSampleMeasurementDisplayRow,
key: SampleMeasurementEditableKey,
@ -67,6 +104,8 @@ export function SampleMeasurementWorkspace({
mode="singleLineResizable"
tone="manual"
testId={`sample-measurement-${key}-${row.skuId}`}
columnWidth={columnWidths[key]}
onColumnResize={(width) => onColumnResize(key, width)}
onChange={(value) => onUpdateRow(row.skuId, key, value)}
/>
);
@ -124,26 +163,26 @@ export function SampleMeasurementWorkspace({
className="border-b border-apple-separator last:border-b-0"
>
<td className="px-3 py-2">
<ReadOnlyCell value={row.model} />
{renderReadOnlyCell("model", row.model)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.skuCode} />
{renderReadOnlyCell("skuCode", row.skuCode)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.setCount} />
{renderReadOnlyCell("setCount", row.setCount)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.supplierName} />
{renderReadOnlyCell("supplierName", row.supplierName)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell value={row.barcode} minWidth="160px" />
{renderReadOnlyCell("barcode", row.barcode)}
</td>
<td className="px-3 py-2">
<ReadOnlyCell
value={row.specName}
minWidth="180px"
testId={`sample-measurement-readonly-specName-${row.skuId}`}
/>
{renderReadOnlyCell(
"specName",
row.specName,
`sample-measurement-readonly-specName-${row.skuId}`,
)}
</td>
<td className="px-3 py-2">
{renderMeasurementInput(row, "lengthCm", "请输入长")}

View File

@ -1,5 +1,20 @@
import { useState } from "react";
import {
type FirstQualityColumnWidthKey,
FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS,
normalizeFirstQualityColumnWidth,
} from "../firstQualityColumnWidthConfig";
import {
type ProductLimitColumnWidthKey,
PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS,
normalizeProductLimitColumnWidth,
} from "../productLimitColumnWidthConfig";
import {
type SampleMeasurementColumnWidthKey,
SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS,
normalizeSampleMeasurementColumnWidth,
} from "../sampleMeasurementColumnWidthConfig";
import {
FINISHED_SAMPLE_SHIPMENT_COLUMN_DEFAULT_WIDTHS,
SKU_COLUMN_DEFAULT_WIDTHS,
@ -19,6 +34,16 @@ export function useSkuColumnResizeController() {
] = useState<Record<FinishedSampleShipmentColumnWidthKey, number>>(() => ({
...FINISHED_SAMPLE_SHIPMENT_COLUMN_DEFAULT_WIDTHS,
}));
const [sampleMeasurementColumnWidths, setSampleMeasurementColumnWidths] =
useState<Record<SampleMeasurementColumnWidthKey, number>>(() => ({
...SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS,
}));
const [productLimitColumnWidths, setProductLimitColumnWidths] = useState<
Record<ProductLimitColumnWidthKey, number>
>(() => ({ ...PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS }));
const [firstQualityColumnWidths, setFirstQualityColumnWidths] = useState<
Record<FirstQualityColumnWidthKey, number>
>(() => ({ ...FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS }));
function handleSkuColumnResize(
column: SkuColumnWidthKey,
@ -40,10 +65,46 @@ export function useSkuColumnResizeController() {
}));
}
function handleSampleMeasurementColumnResize(
column: SampleMeasurementColumnWidthKey,
width: number,
) {
setSampleMeasurementColumnWidths((current) => ({
...current,
[column]: normalizeSampleMeasurementColumnWidth(column, width),
}));
}
function handleProductLimitColumnResize(
column: ProductLimitColumnWidthKey,
width: number,
) {
setProductLimitColumnWidths((current) => ({
...current,
[column]: normalizeProductLimitColumnWidth(column, width),
}));
}
function handleFirstQualityColumnResize(
column: FirstQualityColumnWidthKey,
width: number,
) {
setFirstQualityColumnWidths((current) => ({
...current,
[column]: normalizeFirstQualityColumnWidth(column, width),
}));
}
return {
finishedSampleShipmentColumnWidths,
firstQualityColumnWidths,
handleFinishedSampleShipmentColumnResize,
handleFirstQualityColumnResize,
handleProductLimitColumnResize,
handleSampleMeasurementColumnResize,
handleSkuColumnResize,
productLimitColumnWidths,
sampleMeasurementColumnWidths,
skuColumnWidths,
};
}

View File

@ -0,0 +1,44 @@
import { SKU_COLUMN_MAX_WIDTH } from "./basic-info/skuFieldConfig";
export type FirstQualityColumnWidthKey =
| "model"
| "skuCode"
| "barcode"
| "setCount"
| "specName"
| "size"
| "color"
| "material"
| "supplierName"
| "qualityBatch"
| "detail";
// 默认宽度取自 3001 实测的当前渲染列宽(单元格宽 + 左右 12px 内边距),
// 保证接入受控列宽后默认外观与原先自动布局一致。
export const FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS: Record<
FirstQualityColumnWidthKey,
number
> = {
model: 102,
skuCode: 102,
barcode: 140,
setCount: 68,
specName: 136,
size: 127,
color: 85,
material: 119,
supplierName: 110,
qualityBatch: 148,
detail: 232,
};
export function normalizeFirstQualityColumnWidth(
column: FirstQualityColumnWidthKey,
width: number,
) {
const minWidth = FIRST_QUALITY_COLUMN_DEFAULT_WIDTHS[column];
return Math.min(
SKU_COLUMN_MAX_WIDTH,
Math.max(minWidth, Math.round(width)),
);
}

View File

@ -0,0 +1,40 @@
import { SKU_COLUMN_MAX_WIDTH } from "./basic-info/skuFieldConfig";
export type ProductLimitColumnWidthKey =
| "spu"
| "skuCode"
| "barcode"
| "setCount"
| "specName"
| "costPrice"
| "expectedDailyLimitPrice"
| "expectedLimitGrossMarginRate"
| "nonSpuOwnerLimitPrice";
// 默认宽度取自 3001 实测的当前渲染列宽(单元格宽 + 左右 12px 内边距),
// 保证接入受控列宽后默认外观与原先自动布局一致。
export const PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS: Record<
ProductLimitColumnWidthKey,
number
> = {
spu: 128,
skuCode: 128,
barcode: 182,
setCount: 92,
specName: 182,
costPrice: 115,
expectedDailyLimitPrice: 159,
expectedLimitGrossMarginRate: 159,
nonSpuOwnerLimitPrice: 159,
};
export function normalizeProductLimitColumnWidth(
column: ProductLimitColumnWidthKey,
width: number,
) {
const minWidth = PRODUCT_LIMIT_COLUMN_DEFAULT_WIDTHS[column];
return Math.min(
SKU_COLUMN_MAX_WIDTH,
Math.max(minWidth, Math.round(width)),
);
}

View File

@ -0,0 +1,42 @@
import { SKU_COLUMN_MAX_WIDTH } from "./basic-info/skuFieldConfig";
export type SampleMeasurementColumnWidthKey =
| "model"
| "skuCode"
| "setCount"
| "supplierName"
| "barcode"
| "specName"
| "lengthCm"
| "widthCm"
| "heightCm"
| "weightKg";
// 默认宽度取自 3001 实测的当前渲染列宽(单元格宽 + 左右 12px 内边距),
// 保证接入受控列宽后默认外观与原先自动布局一致。
export const SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS: Record<
SampleMeasurementColumnWidthKey,
number
> = {
model: 158,
skuCode: 158,
setCount: 158,
supplierName: 158,
barcode: 222,
specName: 250,
lengthCm: 194,
widthCm: 194,
heightCm: 194,
weightKg: 194,
};
export function normalizeSampleMeasurementColumnWidth(
column: SampleMeasurementColumnWidthKey,
width: number,
) {
const minWidth = SAMPLE_MEASUREMENT_COLUMN_DEFAULT_WIDTHS[column];
return Math.min(
SKU_COLUMN_MAX_WIDTH,
Math.max(minWidth, Math.round(width)),
);
}