修复房间奖励
This commit is contained in:
parent
0be921409d
commit
723258a3aa
@ -29,6 +29,7 @@ import {
|
|||||||
} from "@/shared/ui/AdminListLayout.jsx";
|
} from "@/shared/ui/AdminListLayout.jsx";
|
||||||
import { DataState } from "@/shared/ui/DataState.jsx";
|
import { DataState } from "@/shared/ui/DataState.jsx";
|
||||||
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
||||||
|
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
|
||||||
import { TimeText } from "@/shared/ui/TimeText.jsx";
|
import { TimeText } from "@/shared/ui/TimeText.jsx";
|
||||||
|
|
||||||
const statusOptions = [
|
const statusOptions = [
|
||||||
@ -117,8 +118,8 @@ export function AgencyOpeningPage() {
|
|||||||
cycleId: cycle.cycleId,
|
cycleId: cycle.cycleId,
|
||||||
title: cycle.title,
|
title: cycle.title,
|
||||||
status: cycle.status || "draft",
|
status: cycle.status || "draft",
|
||||||
startMs: millisToInput(cycle.startMs),
|
startMs: cycle.startMs || "",
|
||||||
endMs: millisToInput(cycle.endMs),
|
endMs: cycle.endMs || "",
|
||||||
minHostCount: String(cycle.minHostCount || 10),
|
minHostCount: String(cycle.minHostCount || 10),
|
||||||
maxAgencyAgeDays: String(cycle.maxAgencyAgeDays || 0),
|
maxAgencyAgeDays: String(cycle.maxAgencyAgeDays || 0),
|
||||||
rewards: (cycle.rewards?.length ? cycle.rewards : emptyForm.rewards).map((reward) => ({
|
rewards: (cycle.rewards?.length ? cycle.rewards : emptyForm.rewards).map((reward) => ({
|
||||||
@ -136,12 +137,20 @@ export function AgencyOpeningPage() {
|
|||||||
if (!abilities.canUpdate && form.cycleId) return;
|
if (!abilities.canUpdate && form.cycleId) return;
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
try {
|
try {
|
||||||
|
const startMs = Number(form.startMs || 0);
|
||||||
|
const endMs = Number(form.endMs || 0);
|
||||||
|
if (startMs <= 0 || endMs <= 0) {
|
||||||
|
throw new Error("请选择活动开始和结束时间");
|
||||||
|
}
|
||||||
|
if (endMs <= startMs) {
|
||||||
|
throw new Error("结束时间必须晚于开始时间");
|
||||||
|
}
|
||||||
const payload = {
|
const payload = {
|
||||||
cycle_id: form.cycleId || undefined,
|
cycle_id: form.cycleId || undefined,
|
||||||
title: form.title.trim(),
|
title: form.title.trim(),
|
||||||
status: form.status,
|
status: form.status,
|
||||||
start_ms: inputToMillis(form.startMs),
|
start_ms: startMs,
|
||||||
end_ms: inputToMillis(form.endMs),
|
end_ms: endMs,
|
||||||
min_host_count: Number(form.minHostCount || 0),
|
min_host_count: Number(form.minHostCount || 0),
|
||||||
max_agency_age_days: Number(form.maxAgencyAgeDays || 0),
|
max_agency_age_days: Number(form.maxAgencyAgeDays || 0),
|
||||||
rewards: normalizeRewardPayload(form.rewards),
|
rewards: normalizeRewardPayload(form.rewards),
|
||||||
@ -421,22 +430,16 @@ export function AgencyOpeningPage() {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</TextField>
|
</TextField>
|
||||||
<TextField
|
<div className="weekly-star-time-range">
|
||||||
label="开始时间"
|
<TimeRangeFilter
|
||||||
required
|
className="weekly-star-time-range__control"
|
||||||
type="datetime-local"
|
label="活动时间"
|
||||||
value={form.startMs}
|
value={{ endMs: form.endMs, startMs: form.startMs }}
|
||||||
onChange={(event) => setForm({ ...form, startMs: event.target.value })}
|
onChange={(range) =>
|
||||||
InputLabelProps={{ shrink: true }}
|
setForm({ ...form, endMs: range.endMs, startMs: range.startMs })
|
||||||
/>
|
}
|
||||||
<TextField
|
/>
|
||||||
label="结束时间"
|
</div>
|
||||||
required
|
|
||||||
type="datetime-local"
|
|
||||||
value={form.endMs}
|
|
||||||
onChange={(event) => setForm({ ...form, endMs: event.target.value })}
|
|
||||||
InputLabelProps={{ shrink: true }}
|
|
||||||
/>
|
|
||||||
<TextField
|
<TextField
|
||||||
label="主播数必须大于"
|
label="主播数必须大于"
|
||||||
required
|
required
|
||||||
@ -548,16 +551,6 @@ function applicationStatusLabel(status) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function millisToInput(ms) {
|
|
||||||
if (!ms) return "";
|
|
||||||
const local = new Date(ms - new Date(ms).getTimezoneOffset() * 60000);
|
|
||||||
return local.toISOString().slice(0, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
function inputToMillis(value) {
|
|
||||||
return value ? new Date(value).getTime() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeRewardPayload(rewards) {
|
function normalizeRewardPayload(rewards) {
|
||||||
const payload = (rewards || []).map((reward, index) => {
|
const payload = (rewards || []).map((reward, index) => {
|
||||||
const thresholdCoinSpent = Number(reward.thresholdCoinSpent || 0);
|
const thresholdCoinSpent = Number(reward.thresholdCoinSpent || 0);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ export interface RoomTurnoverRewardSettlementDto {
|
|||||||
settlementId: string;
|
settlementId: string;
|
||||||
roomId: string;
|
roomId: string;
|
||||||
ownerUserId: string;
|
ownerUserId: string;
|
||||||
|
ownerUser?: Record<string, unknown>;
|
||||||
periodStartMs: number;
|
periodStartMs: number;
|
||||||
periodEndMs: number;
|
periodEndMs: number;
|
||||||
coinSpent: number;
|
coinSpent: number;
|
||||||
@ -59,6 +60,8 @@ export interface RoomTurnoverRewardSettlementDto {
|
|||||||
export interface RoomTurnoverRewardSettlementQuery extends PageQuery {
|
export interface RoomTurnoverRewardSettlementQuery extends PageQuery {
|
||||||
status?: string;
|
status?: string;
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
|
owner_user_keyword?: string;
|
||||||
|
owner_user_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawConfig = RoomTurnoverRewardConfigDto & Record<string, unknown>;
|
type RawConfig = RoomTurnoverRewardConfigDto & Record<string, unknown>;
|
||||||
@ -141,6 +144,7 @@ function normalizeSettlement(item: RawSettlement): RoomTurnoverRewardSettlementD
|
|||||||
settlementId: stringValue(item.settlementId ?? item.settlement_id),
|
settlementId: stringValue(item.settlementId ?? item.settlement_id),
|
||||||
roomId: stringValue(item.roomId ?? item.room_id),
|
roomId: stringValue(item.roomId ?? item.room_id),
|
||||||
ownerUserId: stringValue(item.ownerUserId ?? item.owner_user_id),
|
ownerUserId: stringValue(item.ownerUserId ?? item.owner_user_id),
|
||||||
|
ownerUser: objectValue(item.ownerUser ?? item.owner_user),
|
||||||
periodStartMs: numberValue(item.periodStartMs ?? item.period_start_ms),
|
periodStartMs: numberValue(item.periodStartMs ?? item.period_start_ms),
|
||||||
periodEndMs: numberValue(item.periodEndMs ?? item.period_end_ms),
|
periodEndMs: numberValue(item.periodEndMs ?? item.period_end_ms),
|
||||||
coinSpent: numberValue(item.coinSpent ?? item.coin_spent),
|
coinSpent: numberValue(item.coinSpent ?? item.coin_spent),
|
||||||
@ -166,3 +170,7 @@ function numberValue(value: unknown) {
|
|||||||
const number = Number(value || 0);
|
const number = Number(value || 0);
|
||||||
return Number.isFinite(number) ? number : 0;
|
return Number.isFinite(number) ? number : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function objectValue(value: unknown) {
|
||||||
|
return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
|
||||||
|
}
|
||||||
|
|||||||
@ -29,9 +29,13 @@ export function useRoomTurnoverRewardPage() {
|
|||||||
const [configSaving, setConfigSaving] = useState(false);
|
const [configSaving, setConfigSaving] = useState(false);
|
||||||
const [retryingSettlementId, setRetryingSettlementId] = useState("");
|
const [retryingSettlementId, setRetryingSettlementId] = useState("");
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
|
const [ownerUserKeyword, setOwnerUserKeyword] = useState("");
|
||||||
const [status, setStatus] = useState("");
|
const [status, setStatus] = useState("");
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const filters = useMemo(() => ({ keyword: query, status }), [query, status]);
|
const filters = useMemo(
|
||||||
|
() => ({ keyword: query, owner_user_keyword: ownerUserKeyword, status }),
|
||||||
|
[ownerUserKeyword, query, status],
|
||||||
|
);
|
||||||
const {
|
const {
|
||||||
data: settlements = emptySettlements,
|
data: settlements = emptySettlements,
|
||||||
error: settlementsError,
|
error: settlementsError,
|
||||||
@ -83,6 +87,11 @@ export function useRoomTurnoverRewardPage() {
|
|||||||
setPage(1);
|
setPage(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const changeOwnerUserKeyword = (value) => {
|
||||||
|
setOwnerUserKeyword(value);
|
||||||
|
setPage(1);
|
||||||
|
};
|
||||||
|
|
||||||
const submitConfig = async (event) => {
|
const submitConfig = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (!abilities.canUpdate) {
|
if (!abilities.canUpdate) {
|
||||||
@ -129,6 +138,7 @@ export function useRoomTurnoverRewardPage() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
abilities,
|
abilities,
|
||||||
|
changeOwnerUserKeyword,
|
||||||
changeQuery,
|
changeQuery,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
closeConfigDrawer,
|
closeConfigDrawer,
|
||||||
@ -138,6 +148,7 @@ export function useRoomTurnoverRewardPage() {
|
|||||||
configSaving,
|
configSaving,
|
||||||
form,
|
form,
|
||||||
openConfigDrawer,
|
openConfigDrawer,
|
||||||
|
ownerUserKeyword,
|
||||||
page,
|
page,
|
||||||
query,
|
query,
|
||||||
reloadConfig,
|
reloadConfig,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { RoomTurnoverRewardConfigSummary } from "@/features/room-turnover-reward
|
|||||||
import { useRoomTurnoverRewardPage } from "@/features/room-turnover-reward/hooks/useRoomTurnoverRewardPage.js";
|
import { useRoomTurnoverRewardPage } from "@/features/room-turnover-reward/hooks/useRoomTurnoverRewardPage.js";
|
||||||
import styles from "@/features/room-turnover-reward/room-turnover-reward.module.css";
|
import styles from "@/features/room-turnover-reward/room-turnover-reward.module.css";
|
||||||
import { AdminActionIconButton, AdminListBody, AdminListPage } from "@/shared/ui/AdminListLayout.jsx";
|
import { AdminActionIconButton, AdminListBody, AdminListPage } from "@/shared/ui/AdminListLayout.jsx";
|
||||||
|
import { AdminUserIdentity } from "@/shared/ui/AdminUserIdentity.jsx";
|
||||||
import { DataState } from "@/shared/ui/DataState.jsx";
|
import { DataState } from "@/shared/ui/DataState.jsx";
|
||||||
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
import { DataTable } from "@/shared/ui/DataTable.jsx";
|
||||||
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
|
import { createOptionsColumnFilter, createTextColumnFilter } from "@/shared/ui/tableFilters.js";
|
||||||
@ -23,10 +24,15 @@ const columnsBase = [
|
|||||||
render: (item) => (
|
render: (item) => (
|
||||||
<div className={styles.stack}>
|
<div className={styles.stack}>
|
||||||
<span className={styles.name}>{item.roomId || "-"}</span>
|
<span className={styles.name}>{item.roomId || "-"}</span>
|
||||||
<span className={styles.meta}>房主 {item.ownerUserId || "-"}</span>
|
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "owner",
|
||||||
|
label: "房主信息",
|
||||||
|
width: "minmax(240px, 0.95fr)",
|
||||||
|
render: (item) => <OwnerUser item={item} />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "period",
|
key: "period",
|
||||||
label: "周期",
|
label: "周期",
|
||||||
@ -122,6 +128,16 @@ export function RoomTurnoverRewardPage() {
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (column.key === "owner") {
|
||||||
|
return {
|
||||||
|
...column,
|
||||||
|
filter: createTextColumnFilter({
|
||||||
|
placeholder: "搜索房主 ID、短号、名称",
|
||||||
|
value: page.ownerUserKeyword,
|
||||||
|
onChange: page.changeOwnerUserKeyword,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
if (column.key === "status") {
|
if (column.key === "status") {
|
||||||
return {
|
return {
|
||||||
...column,
|
...column,
|
||||||
@ -155,7 +171,7 @@ export function RoomTurnoverRewardPage() {
|
|||||||
retrySettlement: page.retrySettlement,
|
retrySettlement: page.retrySettlement,
|
||||||
}}
|
}}
|
||||||
items={page.settlements.items || []}
|
items={page.settlements.items || []}
|
||||||
minWidth="1480px"
|
minWidth="1700px"
|
||||||
pagination={
|
pagination={
|
||||||
total > 0
|
total > 0
|
||||||
? {
|
? {
|
||||||
@ -184,6 +200,11 @@ export function RoomTurnoverRewardPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function OwnerUser({ item }) {
|
||||||
|
const owner = item.ownerUser || {};
|
||||||
|
return <AdminUserIdentity openInAppUserDetail user={{ ...owner, userId: owner.userId || item.ownerUserId }} />;
|
||||||
|
}
|
||||||
|
|
||||||
function settlementStatusBadge(status) {
|
function settlementStatusBadge(status) {
|
||||||
const label = settlementStatusOptions.find(([value]) => value === status)?.[1] || status || "-";
|
const label = settlementStatusOptions.find(([value]) => value === status)?.[1] || status || "-";
|
||||||
const className =
|
const className =
|
||||||
|
|||||||
@ -29,7 +29,6 @@ function emptyForm() {
|
|||||||
minRobotCount: "6",
|
minRobotCount: "6",
|
||||||
normalGiftIntervalMs: "10000",
|
normalGiftIntervalMs: "10000",
|
||||||
ownerRobotUserId: "",
|
ownerRobotUserId: "",
|
||||||
roomName: "",
|
|
||||||
visibleRegionId: 0,
|
visibleRegionId: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -153,11 +153,6 @@ export function RoomRobotPage() {
|
|||||||
onClose={page.closeAction}
|
onClose={page.closeAction}
|
||||||
onSubmit={page.submitCreate}
|
onSubmit={page.submitCreate}
|
||||||
>
|
>
|
||||||
<TextField
|
|
||||||
label="房间名称"
|
|
||||||
value={page.form.roomName}
|
|
||||||
onChange={(event) => page.setForm({ ...page.form, roomName: event.target.value })}
|
|
||||||
/>
|
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
getOptionLabel={robotOptionLabel}
|
getOptionLabel={robotOptionLabel}
|
||||||
isOptionEqualToValue={(option, value) => option.userId === value.userId}
|
isOptionEqualToValue={(option, value) => option.userId === value.userId}
|
||||||
|
|||||||
@ -83,7 +83,6 @@ export const robotRoomCreateSchema = z
|
|||||||
minRobotCount: z.coerce.number().int().min(1, "机器人数量范围不正确"),
|
minRobotCount: z.coerce.number().int().min(1, "机器人数量范围不正确"),
|
||||||
normalGiftIntervalMs: z.coerce.number().int().min(1000, "普通礼物频次不正确"),
|
normalGiftIntervalMs: z.coerce.number().int().min(1000, "普通礼物频次不正确"),
|
||||||
ownerRobotUserId: z.coerce.number().int().positive("请选择房主机器人"),
|
ownerRobotUserId: z.coerce.number().int().positive("请选择房主机器人"),
|
||||||
roomName: z.string().trim().max(128, "房间名称不能超过 128 个字符").optional().default(""),
|
|
||||||
visibleRegionId: z.coerce.number().int().min(0, "区域 ID 不正确").default(0),
|
visibleRegionId: z.coerce.number().int().min(0, "区域 ID 不正确").default(0),
|
||||||
})
|
})
|
||||||
.refine((value) => value.maxRobotCount >= value.minRobotCount, {
|
.refine((value) => value.maxRobotCount >= value.minRobotCount, {
|
||||||
|
|||||||
@ -1048,10 +1048,11 @@
|
|||||||
.weekly-star-time-range {
|
.weekly-star-time-range {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
grid-column: 1 / -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weekly-star-time-range__control {
|
.weekly-star-time-range__control {
|
||||||
width: min(520px, 100%);
|
width: min(680px, 100%) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.weekly-star-config-card-grid {
|
.weekly-star-config-card-grid {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user