后台 3D 定价两栏底价输入改为描述表驱动
- apps/admin-web/src/pages/AdminEditorGenerationModel3dPricingSection.tsx:抽出 VERSION_PRICE_FIELDS 描述表,无贴图 / 带贴图两栏共用一段 JSX,字段键与展示名只有一处来源,避免两栏后续改动走偏
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import type { EditorGenerationModel3dPricingPayload } from '../api/adminApiTypes';
|
||||
import type {
|
||||
EditorGenerationModel3dPricingPayload,
|
||||
EditorGenerationModel3dVersionPricePayload,
|
||||
} from '../api/adminApiTypes';
|
||||
import {
|
||||
EDITOR_MODEL3D_ENDPOINT_SECTIONS,
|
||||
editorModel3dAddOnLabel,
|
||||
@@ -6,6 +9,18 @@ import {
|
||||
updateEditorModel3dEndpointPricing,
|
||||
} from './adminEditorGenerationPricing';
|
||||
|
||||
/**
|
||||
* 一个模型版本的两个底价字段。两栏只有字段键与展示名不同,用描述表驱动渲染,
|
||||
* 避免两段近乎相同的 JSX 各自演化。
|
||||
*/
|
||||
const VERSION_PRICE_FIELDS = [
|
||||
{ key: 'noTexture', label: '无贴图' },
|
||||
{ key: 'texture', label: '带贴图' },
|
||||
] as const satisfies ReadonlyArray<{
|
||||
key: keyof EditorGenerationModel3dVersionPricePayload;
|
||||
label: string;
|
||||
}>;
|
||||
|
||||
interface AdminEditorGenerationModel3dPricingSectionProps {
|
||||
model3d: EditorGenerationModel3dPricingPayload;
|
||||
onChange: (next: EditorGenerationModel3dPricingPayload) => void;
|
||||
@@ -51,54 +66,34 @@ export function AdminEditorGenerationModel3dPricingSection({
|
||||
<span className="admin-pricing-model3d-row-label">
|
||||
{version}
|
||||
</span>
|
||||
<label className="admin-field">
|
||||
<span>无贴图</span>
|
||||
<input
|
||||
aria-label={`${label} ${version} 无贴图`}
|
||||
min={1}
|
||||
step={1}
|
||||
type="number"
|
||||
value={price.noTexture}
|
||||
onChange={(event) =>
|
||||
updateEndpoint(key, (current) => ({
|
||||
...current,
|
||||
versionPrices: {
|
||||
...current.versionPrices,
|
||||
[version]: {
|
||||
...price,
|
||||
noTexture: parsePositiveInteger(
|
||||
event.target.value,
|
||||
),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
<label className="admin-field">
|
||||
<span>带贴图</span>
|
||||
<input
|
||||
aria-label={`${label} ${version} 带贴图`}
|
||||
min={1}
|
||||
step={1}
|
||||
type="number"
|
||||
value={price.texture}
|
||||
onChange={(event) =>
|
||||
updateEndpoint(key, (current) => ({
|
||||
...current,
|
||||
versionPrices: {
|
||||
...current.versionPrices,
|
||||
[version]: {
|
||||
...price,
|
||||
texture: parsePositiveInteger(
|
||||
event.target.value,
|
||||
),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
{VERSION_PRICE_FIELDS.map(
|
||||
({ key: field, label: fieldLabel }) => (
|
||||
<label className="admin-field" key={field}>
|
||||
<span>{fieldLabel}</span>
|
||||
<input
|
||||
aria-label={`${label} ${version} ${fieldLabel}`}
|
||||
min={1}
|
||||
step={1}
|
||||
type="number"
|
||||
value={price[field]}
|
||||
onChange={(event) =>
|
||||
updateEndpoint(key, (current) => ({
|
||||
...current,
|
||||
versionPrices: {
|
||||
...current.versionPrices,
|
||||
[version]: {
|
||||
...price,
|
||||
[field]: parsePositiveInteger(
|
||||
event.target.value,
|
||||
),
|
||||
},
|
||||
},
|
||||
}))
|
||||
}
|
||||
/>
|
||||
</label>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user