fix: keep cp gift relation type
This commit is contained in:
parent
4520e16470
commit
ae8ae7db55
@ -81,6 +81,7 @@ test("resource APIs use generated admin paths", async () => {
|
|||||||
await createGift({
|
await createGift({
|
||||||
chargeAssetType: "COIN",
|
chargeAssetType: "COIN",
|
||||||
coinPrice: 10,
|
coinPrice: 10,
|
||||||
|
cpRelationType: "",
|
||||||
effectiveAtMs: 1777766400000,
|
effectiveAtMs: 1777766400000,
|
||||||
effectiveFromMs: 0,
|
effectiveFromMs: 0,
|
||||||
effectiveToMs: 0,
|
effectiveToMs: 0,
|
||||||
@ -131,6 +132,7 @@ test("resource APIs use generated admin paths", async () => {
|
|||||||
await updateGift("rose", {
|
await updateGift("rose", {
|
||||||
chargeAssetType: "COIN",
|
chargeAssetType: "COIN",
|
||||||
coinPrice: 10,
|
coinPrice: 10,
|
||||||
|
cpRelationType: "",
|
||||||
effectiveAtMs: 1777766400000,
|
effectiveAtMs: 1777766400000,
|
||||||
effectiveFromMs: 0,
|
effectiveFromMs: 0,
|
||||||
effectiveToMs: 0,
|
effectiveToMs: 0,
|
||||||
|
|||||||
@ -126,6 +126,7 @@ export interface GiftDto {
|
|||||||
presentationJson?: string;
|
presentationJson?: string;
|
||||||
priceVersion?: string;
|
priceVersion?: string;
|
||||||
giftTypeCode?: string;
|
giftTypeCode?: string;
|
||||||
|
cpRelationType?: string;
|
||||||
chargeAssetType?: string;
|
chargeAssetType?: string;
|
||||||
coinPrice?: number;
|
coinPrice?: number;
|
||||||
effectiveFromMs?: number;
|
effectiveFromMs?: number;
|
||||||
@ -158,6 +159,7 @@ export interface GiftPayload {
|
|||||||
presentationJson: string;
|
presentationJson: string;
|
||||||
priceVersion: string;
|
priceVersion: string;
|
||||||
giftTypeCode: string;
|
giftTypeCode: string;
|
||||||
|
cpRelationType: string;
|
||||||
chargeAssetType: string;
|
chargeAssetType: string;
|
||||||
coinPrice: number;
|
coinPrice: number;
|
||||||
effectiveAtMs: number;
|
effectiveAtMs: number;
|
||||||
|
|||||||
@ -122,14 +122,11 @@ const emptyGroupWalletAssetItem = (walletAssetType) => ({
|
|||||||
const emptyGiftForm = (gift = {}) => {
|
const emptyGiftForm = (gift = {}) => {
|
||||||
const giftTypeCode = gift.giftTypeCode || "normal";
|
const giftTypeCode = gift.giftTypeCode || "normal";
|
||||||
const presentationJson = gift.presentationJson || "{}";
|
const presentationJson = gift.presentationJson || "{}";
|
||||||
const cpRelationType =
|
const cpRelationType = cpRelationTypeFromGift({ ...gift, giftTypeCode, presentationJson }) || defaultCPRelationType;
|
||||||
giftTypeCode === cpGiftTypeCode
|
|
||||||
? cpRelationTypeFromPresentationJson(presentationJson) || defaultCPRelationType
|
|
||||||
: "";
|
|
||||||
return {
|
return {
|
||||||
chargeAssetType: gift.chargeAssetType || "COIN",
|
chargeAssetType: gift.chargeAssetType || "COIN",
|
||||||
coinPrice: gift.coinPrice === 0 || gift.coinPrice ? String(gift.coinPrice) : "",
|
coinPrice: gift.coinPrice === 0 || gift.coinPrice ? String(gift.coinPrice) : "",
|
||||||
cpRelationType,
|
cpRelationType: giftTypeCode === cpGiftTypeCode ? cpRelationType : "",
|
||||||
effectTypes: gift.effectTypes || [],
|
effectTypes: gift.effectTypes || [],
|
||||||
effectiveFrom: msToDatetimeLocal(gift.effectiveFromMs),
|
effectiveFrom: msToDatetimeLocal(gift.effectiveFromMs),
|
||||||
effectiveTo: msToDatetimeLocal(gift.effectiveToMs),
|
effectiveTo: msToDatetimeLocal(gift.effectiveToMs),
|
||||||
@ -174,6 +171,18 @@ export function cpRelationTypeFromPresentationJson(presentationJson) {
|
|||||||
return relationType || "";
|
return relationType || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function cpRelationTypeFromGift(gift = {}) {
|
||||||
|
if (gift?.giftTypeCode !== cpGiftTypeCode) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return validCPRelationType(gift.cpRelationType) || cpRelationTypeFromPresentationJson(gift.presentationJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cpRelationTypeShortLabel(value) {
|
||||||
|
const label = cpRelationTypeLabels[validCPRelationType(value)] || String(value || "").trim();
|
||||||
|
return label.endsWith("礼物") ? label.slice(0, -2) : label;
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeGiftPresentationJson(presentationJson, giftTypeCode, cpRelationType) {
|
export function normalizeGiftPresentationJson(presentationJson, giftTypeCode, cpRelationType) {
|
||||||
const rawValue = String(presentationJson || "").trim();
|
const rawValue = String(presentationJson || "").trim();
|
||||||
const isCPGift = giftTypeCode === cpGiftTypeCode;
|
const isCPGift = giftTypeCode === cpGiftTypeCode;
|
||||||
@ -239,8 +248,12 @@ function parseGiftPresentationObject(presentationJson) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function normalizedCPRelationType(value) {
|
function normalizedCPRelationType(value) {
|
||||||
|
return validCPRelationType(value) || defaultCPRelationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validCPRelationType(value) {
|
||||||
const relationType = String(value || "").trim().toLowerCase();
|
const relationType = String(value || "").trim().toLowerCase();
|
||||||
return cpRelationTypeValues.has(relationType) ? relationType : defaultCPRelationType;
|
return cpRelationTypeValues.has(relationType) ? relationType : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function cpPresentationJson(basePresentation, cpRelationType) {
|
function cpPresentationJson(basePresentation, cpRelationType) {
|
||||||
@ -1629,9 +1642,11 @@ function buildResourceGroupPayload(form) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildGiftPayload(form) {
|
function buildGiftPayload(form) {
|
||||||
|
const cpRelationType = form.giftTypeCode === cpGiftTypeCode ? normalizedCPRelationType(form.cpRelationType) : "";
|
||||||
return {
|
return {
|
||||||
chargeAssetType: form.chargeAssetType,
|
chargeAssetType: form.chargeAssetType,
|
||||||
coinPrice: Number(form.coinPrice),
|
coinPrice: Number(form.coinPrice),
|
||||||
|
cpRelationType,
|
||||||
effectiveAtMs: Date.now(),
|
effectiveAtMs: Date.now(),
|
||||||
effectiveFromMs: datetimeLocalToMs(form.effectiveFrom),
|
effectiveFromMs: datetimeLocalToMs(form.effectiveFrom),
|
||||||
effectiveToMs: datetimeLocalToMs(form.effectiveTo),
|
effectiveToMs: datetimeLocalToMs(form.effectiveTo),
|
||||||
@ -1649,9 +1664,11 @@ function buildGiftPayload(form) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildGiftInlineSortPayload(gift, sortOrder) {
|
function buildGiftInlineSortPayload(gift, sortOrder) {
|
||||||
|
const cpRelationType = cpRelationTypeFromGift(gift);
|
||||||
return {
|
return {
|
||||||
chargeAssetType: gift.chargeAssetType || "COIN",
|
chargeAssetType: gift.chargeAssetType || "COIN",
|
||||||
coinPrice: Number(gift.coinPrice || 0),
|
coinPrice: Number(gift.coinPrice || 0),
|
||||||
|
cpRelationType: gift.giftTypeCode === cpGiftTypeCode ? cpRelationType || defaultCPRelationType : "",
|
||||||
effectiveAtMs: Date.now(),
|
effectiveAtMs: Date.now(),
|
||||||
effectiveFromMs: Number(gift.effectiveFromMs || 0),
|
effectiveFromMs: Number(gift.effectiveFromMs || 0),
|
||||||
effectiveToMs: Number(gift.effectiveToMs || 0),
|
effectiveToMs: Number(gift.effectiveToMs || 0),
|
||||||
|
|||||||
@ -2,7 +2,9 @@ import { expect, test, vi } from "vitest";
|
|||||||
import {
|
import {
|
||||||
applyGiftPriceDefaults,
|
applyGiftPriceDefaults,
|
||||||
applyGiftResourceSelection,
|
applyGiftResourceSelection,
|
||||||
|
cpRelationTypeFromGift,
|
||||||
cpRelationTypeFromPresentationJson,
|
cpRelationTypeFromPresentationJson,
|
||||||
|
cpRelationTypeShortLabel,
|
||||||
fetchAllOptionPages,
|
fetchAllOptionPages,
|
||||||
normalizeGiftPresentationJson,
|
normalizeGiftPresentationJson,
|
||||||
} from "./useResourcePages.js";
|
} from "./useResourcePages.js";
|
||||||
@ -67,6 +69,24 @@ test("reads CP relation type from gift presentation json", () => {
|
|||||||
expect(cpRelationTypeFromPresentationJson('{"cp_relation_type":"unknown"}')).toBe("");
|
expect(cpRelationTypeFromPresentationJson('{"cp_relation_type":"unknown"}')).toBe("");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("prefers explicit CP relation type and formats compact list label", () => {
|
||||||
|
expect(
|
||||||
|
cpRelationTypeFromGift({
|
||||||
|
cpRelationType: "brother",
|
||||||
|
giftTypeCode: "cp",
|
||||||
|
presentationJson: '{"cp_relation_type":"sister"}',
|
||||||
|
}),
|
||||||
|
).toBe("brother");
|
||||||
|
expect(
|
||||||
|
cpRelationTypeFromGift({
|
||||||
|
giftTypeCode: "cp",
|
||||||
|
presentationJson: '{"cp_relation_type":"sister"}',
|
||||||
|
}),
|
||||||
|
).toBe("sister");
|
||||||
|
expect(cpRelationTypeShortLabel("brother")).toBe("兄弟");
|
||||||
|
expect(cpRelationTypeShortLabel("cp")).toBe("CP");
|
||||||
|
});
|
||||||
|
|
||||||
test("normalizes CP gift presentation json for submit", () => {
|
test("normalizes CP gift presentation json for submit", () => {
|
||||||
const nextJson = normalizeGiftPresentationJson(
|
const nextJson = normalizeGiftPresentationJson(
|
||||||
'{"other":1,"cp_relation_type":"brother","cpRelationLabel":"old"}',
|
'{"other":1,"cp_relation_type":"brother","cpRelationLabel":"old"}',
|
||||||
|
|||||||
@ -34,14 +34,17 @@ import { createRegionColumnFilter } from "@/shared/ui/RegionFilterControl.jsx";
|
|||||||
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
|
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
|
||||||
import { formatMillis } from "@/shared/utils/time.js";
|
import { formatMillis } from "@/shared/utils/time.js";
|
||||||
import {
|
import {
|
||||||
cpRelationTypeLabels,
|
|
||||||
cpRelationTypeOptions,
|
cpRelationTypeOptions,
|
||||||
defaultGiftTypeOptions,
|
defaultGiftTypeOptions,
|
||||||
resourceStatusFilters,
|
resourceStatusFilters,
|
||||||
} from "@/features/resources/constants.js";
|
} from "@/features/resources/constants.js";
|
||||||
import { GiftTypeConfigDialog } from "@/features/resources/components/GiftTypeConfigDialog.jsx";
|
import { GiftTypeConfigDialog } from "@/features/resources/components/GiftTypeConfigDialog.jsx";
|
||||||
import { ResourceSelectField } from "@/features/resources/components/ResourceSelectDrawer.jsx";
|
import { ResourceSelectField } from "@/features/resources/components/ResourceSelectDrawer.jsx";
|
||||||
import { cpRelationTypeFromPresentationJson, useGiftListPage } from "@/features/resources/hooks/useResourcePages.js";
|
import {
|
||||||
|
cpRelationTypeFromGift,
|
||||||
|
cpRelationTypeShortLabel,
|
||||||
|
useGiftListPage,
|
||||||
|
} from "@/features/resources/hooks/useResourcePages.js";
|
||||||
import styles from "@/features/resources/resources.module.css";
|
import styles from "@/features/resources/resources.module.css";
|
||||||
|
|
||||||
const effectOptions = [
|
const effectOptions = [
|
||||||
@ -667,13 +670,10 @@ function giftTypeLabel(value, options = defaultGiftTypeOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function GiftTypeIdentity({ gift, giftTypeOptions }) {
|
function GiftTypeIdentity({ gift, giftTypeOptions }) {
|
||||||
const relationType = gift.giftTypeCode === "cp" ? cpRelationTypeFromPresentationJson(gift.presentationJson) : "";
|
const typeLabel = giftTypeLabel(gift.giftTypeCode, giftTypeOptions);
|
||||||
return (
|
const relationType = gift.giftTypeCode === "cp" ? cpRelationTypeFromGift(gift) || "cp" : "";
|
||||||
<div className={styles.stack}>
|
const relationLabel = relationType ? cpRelationTypeShortLabel(relationType) : "";
|
||||||
<span>{giftTypeLabel(gift.giftTypeCode, giftTypeOptions)}</span>
|
return <span>{relationLabel ? `${typeLabel}(${relationLabel})` : typeLabel}</span>;
|
||||||
{relationType ? <span className="admin-tag">{cpRelationTypeLabels[relationType] || relationType}</span> : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function giftPriceLabel(gift) {
|
function giftPriceLabel(gift) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user