代理活动
This commit is contained in:
parent
9d930da859
commit
ee0a14d5b7
@ -8,8 +8,9 @@
|
|||||||
.databi-screen {
|
.databi-screen {
|
||||||
--analysis-row-height: 320px;
|
--analysis-row-height: 320px;
|
||||||
--business-metric-row-height: 104px;
|
--business-metric-row-height: 104px;
|
||||||
|
--robot-gift-metric-row-height: 104px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-rows: 72px 140px var(--business-metric-row-height) var(--analysis-row-height);
|
grid-template-rows: 72px 140px var(--business-metric-row-height) var(--robot-gift-metric-row-height) var(--analysis-row-height);
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
@ -751,6 +752,14 @@
|
|||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.robot-gift-metric-grid {
|
||||||
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.robot-gift-metric-grid .metric-card {
|
||||||
|
height: var(--robot-gift-metric-row-height);
|
||||||
|
}
|
||||||
|
|
||||||
.business-metric-grid .metric-content {
|
.business-metric-grid .metric-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(max-content, 1fr) max-content;
|
grid-template-columns: minmax(max-content, 1fr) max-content;
|
||||||
@ -759,6 +768,10 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.robot-gift-metric-grid .metric-content {
|
||||||
|
grid-template-columns: minmax(0, 1fr) max-content;
|
||||||
|
}
|
||||||
|
|
||||||
.business-metric-grid .metric-card.is-loading .metric-content {
|
.business-metric-grid .metric-card.is-loading .metric-content {
|
||||||
grid-template-columns: minmax(0, 1fr) 96px;
|
grid-template-columns: minmax(0, 1fr) 96px;
|
||||||
grid-template-rows: 16px 28px;
|
grid-template-rows: 16px 28px;
|
||||||
@ -799,6 +812,12 @@
|
|||||||
text-overflow: clip;
|
text-overflow: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.robot-gift-metric-grid .metric-label-row > span {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.business-metric-grid .metric-content strong {
|
.business-metric-grid .metric-content strong {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
grid-row: 2;
|
grid-row: 2;
|
||||||
|
|||||||
@ -52,6 +52,10 @@ export interface AgencyOpeningApplicationDto {
|
|||||||
walletTransactionId: string;
|
walletTransactionId: string;
|
||||||
failureReason: string;
|
failureReason: string;
|
||||||
appliedAtMs: number;
|
appliedAtMs: number;
|
||||||
|
approvedAtMs: number;
|
||||||
|
scoreStartMs: number;
|
||||||
|
scoreEndMs: number;
|
||||||
|
reviewedByAdminId: number;
|
||||||
grantedAtMs: number;
|
grantedAtMs: number;
|
||||||
updatedAtMs: number;
|
updatedAtMs: number;
|
||||||
}
|
}
|
||||||
@ -94,6 +98,13 @@ export function listAgencyOpeningApplications(query: QueryParams = {}) {
|
|||||||
).then((page) => ({ ...page, items: (page.items || []).map(normalizeApplication) }));
|
).then((page) => ({ ...page, items: (page.items || []).map(normalizeApplication) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function approveAgencyOpeningApplication(applicationId: string) {
|
||||||
|
return apiRequest<Raw, undefined>(
|
||||||
|
`/v1/admin/activity/agency-opening/applications/${encodeURIComponent(applicationId)}/approve`,
|
||||||
|
{ method: "POST" },
|
||||||
|
).then(normalizeApplication);
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeCycle(item: Raw): AgencyOpeningCycleDto {
|
function normalizeCycle(item: Raw): AgencyOpeningCycleDto {
|
||||||
return {
|
return {
|
||||||
cycleId: stringValue(item.cycleId ?? item.cycle_id),
|
cycleId: stringValue(item.cycleId ?? item.cycle_id),
|
||||||
@ -138,6 +149,10 @@ function normalizeApplication(item: Raw): AgencyOpeningApplicationDto {
|
|||||||
walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id),
|
walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id),
|
||||||
failureReason: stringValue(item.failureReason ?? item.failure_reason),
|
failureReason: stringValue(item.failureReason ?? item.failure_reason),
|
||||||
appliedAtMs: numberValue(item.appliedAtMs ?? item.applied_at_ms),
|
appliedAtMs: numberValue(item.appliedAtMs ?? item.applied_at_ms),
|
||||||
|
approvedAtMs: numberValue(item.approvedAtMs ?? item.approved_at_ms),
|
||||||
|
scoreStartMs: numberValue(item.scoreStartMs ?? item.score_start_ms),
|
||||||
|
scoreEndMs: numberValue(item.scoreEndMs ?? item.score_end_ms),
|
||||||
|
reviewedByAdminId: numberValue(item.reviewedByAdminId ?? item.reviewed_by_admin_id),
|
||||||
grantedAtMs: numberValue(item.grantedAtMs ?? item.granted_at_ms),
|
grantedAtMs: numberValue(item.grantedAtMs ?? item.granted_at_ms),
|
||||||
updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
|
updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import AddOutlined from "@mui/icons-material/AddOutlined";
|
import AddOutlined from "@mui/icons-material/AddOutlined";
|
||||||
|
import CheckCircleOutlineOutlined from "@mui/icons-material/CheckCircleOutlineOutlined";
|
||||||
import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined";
|
import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined";
|
||||||
import EditOutlined from "@mui/icons-material/EditOutlined";
|
import EditOutlined from "@mui/icons-material/EditOutlined";
|
||||||
import RefreshOutlined from "@mui/icons-material/RefreshOutlined";
|
import RefreshOutlined from "@mui/icons-material/RefreshOutlined";
|
||||||
@ -12,6 +13,7 @@ import TextField from "@mui/material/TextField";
|
|||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
|
approveAgencyOpeningApplication,
|
||||||
createAgencyOpeningCycle,
|
createAgencyOpeningCycle,
|
||||||
listAgencyOpeningApplications,
|
listAgencyOpeningApplications,
|
||||||
listAgencyOpeningCycles,
|
listAgencyOpeningCycles,
|
||||||
@ -182,6 +184,17 @@ export function AgencyOpeningPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function approveApplication(item) {
|
||||||
|
if (!abilities.canUpdate || item.status !== "applied") return;
|
||||||
|
try {
|
||||||
|
await approveAgencyOpeningApplication(item.applicationId);
|
||||||
|
setToast("已同意申请,计分窗口从当前时间开始");
|
||||||
|
await reloadApplications(selectedCycleId);
|
||||||
|
} catch (err) {
|
||||||
|
setToast(err instanceof Error ? err.message : "同意申请失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateReward(index, field, value) {
|
function updateReward(index, field, value) {
|
||||||
setForm((current) => ({
|
setForm((current) => ({
|
||||||
...current,
|
...current,
|
||||||
@ -388,16 +401,54 @@ export function AgencyOpeningPage() {
|
|||||||
width: "180px",
|
width: "180px",
|
||||||
render: (item) => <TimeText value={item.appliedAtMs} />,
|
render: (item) => <TimeText value={item.appliedAtMs} />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "score-window",
|
||||||
|
label: "计分窗口",
|
||||||
|
width: "240px",
|
||||||
|
render: (item) =>
|
||||||
|
item.scoreStartMs ? (
|
||||||
|
<div className="weekly-star-list-stack">
|
||||||
|
<TimeText value={item.scoreStartMs} />
|
||||||
|
<span className="weekly-star-list-meta">
|
||||||
|
至 <TimeText value={item.scoreEndMs} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: "granted",
|
key: "granted",
|
||||||
label: "发奖时间",
|
label: "发奖时间",
|
||||||
width: "180px",
|
width: "180px",
|
||||||
render: (item) => (item.grantedAtMs ? <TimeText value={item.grantedAtMs} /> : "-"),
|
render: (item) => (item.grantedAtMs ? <TimeText value={item.grantedAtMs} /> : "-"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: "actions",
|
||||||
|
label: "操作",
|
||||||
|
width: "112px",
|
||||||
|
fixed: "right",
|
||||||
|
resizable: false,
|
||||||
|
render: (item) =>
|
||||||
|
item.status === "applied" && abilities.canUpdate ? (
|
||||||
|
<AdminRowActions>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
startIcon={<CheckCircleOutlineOutlined fontSize="small" />}
|
||||||
|
variant="primary"
|
||||||
|
onClick={() => approveApplication(item)}
|
||||||
|
>
|
||||||
|
同意
|
||||||
|
</Button>
|
||||||
|
</AdminRowActions>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
),
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
emptyLabel={applicationsLoading ? "加载中..." : "暂无申请记录"}
|
emptyLabel={applicationsLoading ? "加载中..." : "暂无申请记录"}
|
||||||
items={applications}
|
items={applications}
|
||||||
minWidth="1210px"
|
minWidth="1560px"
|
||||||
rowKey={(item) => item.applicationId}
|
rowKey={(item) => item.applicationId}
|
||||||
/>
|
/>
|
||||||
</AdminListBody>
|
</AdminListBody>
|
||||||
@ -541,10 +592,12 @@ function statusColor(status) {
|
|||||||
function applicationStatusLabel(status) {
|
function applicationStatusLabel(status) {
|
||||||
return (
|
return (
|
||||||
{
|
{
|
||||||
applied: "已申请",
|
applied: "待审核",
|
||||||
|
approved: "计分中",
|
||||||
pending: "待发奖",
|
pending: "待发奖",
|
||||||
granted: "已发奖",
|
granted: "已发奖",
|
||||||
failed: "发奖失败",
|
failed: "发奖失败",
|
||||||
|
expired: "已过期",
|
||||||
}[status] ||
|
}[status] ||
|
||||||
status ||
|
status ||
|
||||||
"-"
|
"-"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user