From ee0a14d5b7757ae9c8b94eb9f9527aa017ddf1e9 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 18 Jun 2026 14:19:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=90=86=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- databi/src/styles/layout.css | 21 ++++++- src/features/agency-opening/api.ts | 15 +++++ .../pages/AgencyOpeningPage.jsx | 57 ++++++++++++++++++- 3 files changed, 90 insertions(+), 3 deletions(-) diff --git a/databi/src/styles/layout.css b/databi/src/styles/layout.css index d1e7a90..4031705 100644 --- a/databi/src/styles/layout.css +++ b/databi/src/styles/layout.css @@ -8,8 +8,9 @@ .databi-screen { --analysis-row-height: 320px; --business-metric-row-height: 104px; + --robot-gift-metric-row-height: 104px; 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; min-height: 0; } @@ -751,6 +752,14 @@ 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 { display: grid; grid-template-columns: minmax(max-content, 1fr) max-content; @@ -759,6 +768,10 @@ 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 { grid-template-columns: minmax(0, 1fr) 96px; grid-template-rows: 16px 28px; @@ -799,6 +812,12 @@ 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 { grid-column: 1; grid-row: 2; diff --git a/src/features/agency-opening/api.ts b/src/features/agency-opening/api.ts index 3aaff2f..34b319a 100644 --- a/src/features/agency-opening/api.ts +++ b/src/features/agency-opening/api.ts @@ -52,6 +52,10 @@ export interface AgencyOpeningApplicationDto { walletTransactionId: string; failureReason: string; appliedAtMs: number; + approvedAtMs: number; + scoreStartMs: number; + scoreEndMs: number; + reviewedByAdminId: number; grantedAtMs: number; updatedAtMs: number; } @@ -94,6 +98,13 @@ export function listAgencyOpeningApplications(query: QueryParams = {}) { ).then((page) => ({ ...page, items: (page.items || []).map(normalizeApplication) })); } +export function approveAgencyOpeningApplication(applicationId: string) { + return apiRequest( + `/v1/admin/activity/agency-opening/applications/${encodeURIComponent(applicationId)}/approve`, + { method: "POST" }, + ).then(normalizeApplication); +} + function normalizeCycle(item: Raw): AgencyOpeningCycleDto { return { cycleId: stringValue(item.cycleId ?? item.cycle_id), @@ -138,6 +149,10 @@ function normalizeApplication(item: Raw): AgencyOpeningApplicationDto { walletTransactionId: stringValue(item.walletTransactionId ?? item.wallet_transaction_id), failureReason: stringValue(item.failureReason ?? item.failure_reason), 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), updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms), }; diff --git a/src/features/agency-opening/pages/AgencyOpeningPage.jsx b/src/features/agency-opening/pages/AgencyOpeningPage.jsx index 9ab4626..057cfd7 100644 --- a/src/features/agency-opening/pages/AgencyOpeningPage.jsx +++ b/src/features/agency-opening/pages/AgencyOpeningPage.jsx @@ -1,4 +1,5 @@ import AddOutlined from "@mui/icons-material/AddOutlined"; +import CheckCircleOutlineOutlined from "@mui/icons-material/CheckCircleOutlineOutlined"; import DeleteOutlineOutlined from "@mui/icons-material/DeleteOutlineOutlined"; import EditOutlined from "@mui/icons-material/EditOutlined"; import RefreshOutlined from "@mui/icons-material/RefreshOutlined"; @@ -12,6 +13,7 @@ import TextField from "@mui/material/TextField"; import Typography from "@mui/material/Typography"; import { useEffect, useState } from "react"; import { + approveAgencyOpeningApplication, createAgencyOpeningCycle, listAgencyOpeningApplications, 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) { setForm((current) => ({ ...current, @@ -388,16 +401,54 @@ export function AgencyOpeningPage() { width: "180px", render: (item) => , }, + { + key: "score-window", + label: "计分窗口", + width: "240px", + render: (item) => + item.scoreStartMs ? ( +
+ + + 至 + +
+ ) : ( + "-" + ), + }, { key: "granted", label: "发奖时间", width: "180px", render: (item) => (item.grantedAtMs ? : "-"), }, + { + key: "actions", + label: "操作", + width: "112px", + fixed: "right", + resizable: false, + render: (item) => + item.status === "applied" && abilities.canUpdate ? ( + + + + ) : ( + "-" + ), + }, ]} emptyLabel={applicationsLoading ? "加载中..." : "暂无申请记录"} items={applications} - minWidth="1210px" + minWidth="1560px" rowKey={(item) => item.applicationId} /> @@ -541,10 +592,12 @@ function statusColor(status) { function applicationStatusLabel(status) { return ( { - applied: "已申请", + applied: "待审核", + approved: "计分中", pending: "待发奖", granted: "已发奖", failed: "发奖失败", + expired: "已过期", }[status] || status || "-"