This commit is contained in:
zhx 2026-07-03 18:07:52 +08:00
parent f6822d2411
commit ea78619f5f
2 changed files with 798 additions and 720 deletions

View File

@ -20,7 +20,7 @@ import {
listFinanceWithdrawalApplications, listFinanceWithdrawalApplications,
refreshFinanceGoogleRechargePaid, refreshFinanceGoogleRechargePaid,
rejectFinanceApplication, rejectFinanceApplication,
rejectFinanceWithdrawalApplication rejectFinanceWithdrawalApplication,
} from "./api.js"; } from "./api.js";
import { FinanceApplicationForm } from "./components/FinanceApplicationForm.jsx"; import { FinanceApplicationForm } from "./components/FinanceApplicationForm.jsx";
import { FinanceApplicationList } from "./components/FinanceApplicationList.jsx"; import { FinanceApplicationList } from "./components/FinanceApplicationList.jsx";
@ -36,7 +36,7 @@ import {
EMPTY_RECHARGE_OVERVIEW, EMPTY_RECHARGE_OVERVIEW,
EMPTY_RECHARGE_SUMMARY, EMPTY_RECHARGE_SUMMARY,
buildApplicationPayload, buildApplicationPayload,
validateApplicationPayload validateApplicationPayload,
} from "./format.js"; } from "./format.js";
import { downloadCsv } from "@/shared/api/download"; import { downloadCsv } from "@/shared/api/download";
import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx"; import { TimeRangeFilter } from "@/shared/ui/TimeRangeFilter.jsx";
@ -62,7 +62,7 @@ function timePresets() {
{ key: "7d", label: "近7天", range: { endMs: todayStart + DAY_MS, startMs: todayStart - 6 * DAY_MS } }, { key: "7d", label: "近7天", range: { endMs: todayStart + DAY_MS, startMs: todayStart - 6 * DAY_MS } },
{ key: "30d", label: "近30天", range: { endMs: todayStart + DAY_MS, startMs: todayStart - 29 * DAY_MS } }, { key: "30d", label: "近30天", range: { endMs: todayStart + DAY_MS, startMs: todayStart - 29 * DAY_MS } },
{ key: "month", label: "本月", range: { endMs: todayStart + DAY_MS, startMs: monthStart } }, { key: "month", label: "本月", range: { endMs: todayStart + DAY_MS, startMs: monthStart } },
{ key: "all", label: "不限", range: { endMs: "", startMs: "" } } { key: "all", label: "不限", range: { endMs: "", startMs: "" } },
]; ];
} }
@ -77,7 +77,7 @@ function reconMonthMeta(offset) {
endMs, endMs,
isCurrent: offset === 0, isCurrent: offset === 0,
label: `${startDate.getUTCFullYear()}${startDate.getUTCMonth() + 1}`, label: `${startDate.getUTCFullYear()}${startDate.getUTCMonth() + 1}`,
startMs startMs,
}; };
} }
@ -85,17 +85,45 @@ export function FinanceApp() {
const { showToast } = useToast(); const { showToast } = useToast();
const [sessionState, setSessionState] = useState({ error: "", loading: true, session: null }); const [sessionState, setSessionState] = useState({ error: "", loading: true, session: null });
const [optionsState, setOptionsState] = useState({ data: emptyOptions, error: "", loading: false }); const [optionsState, setOptionsState] = useState({ data: emptyOptions, error: "", loading: false });
const [rechargeDetailsState, setRechargeDetailsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false }); const [rechargeDetailsState, setRechargeDetailsState] = useState({
const [rechargeSummaryState, setRechargeSummaryState] = useState({ merged: EMPTY_RECHARGE_SUMMARY, loading: false, perApp: [], prev: null }); data: { items: [], page: 1, pageSize, total: 0 },
const [rechargeOverviewState, setRechargeOverviewState] = useState({ data: EMPTY_RECHARGE_OVERVIEW, loading: false }); error: "",
const [rechargeRegionsState, setRechargeRegionsState] = useState({ appCode: "", items: [], loading: false }); loading: false,
});
const [rechargeSummaryState, setRechargeSummaryState] = useState({
merged: EMPTY_RECHARGE_SUMMARY,
loading: false,
perApp: [],
prev: null,
});
const [rechargeOverviewState, setRechargeOverviewState] = useState({
data: EMPTY_RECHARGE_OVERVIEW,
loading: false,
});
const [rechargeRegionsState, setRechargeRegionsState] = useState({ byApp: {}, loading: false });
const [rechargeAppsState, setRechargeAppsState] = useState({ items: [], loaded: false }); const [rechargeAppsState, setRechargeAppsState] = useState({ items: [], loaded: false });
const [googlePaidRefreshing, setGooglePaidRefreshing] = useState(false); const [googlePaidRefreshing, setGooglePaidRefreshing] = useState(false);
const [reconMonthOffset, setReconMonthOffset] = useState(0); const [reconMonthOffset, setReconMonthOffset] = useState(0);
const [reconState, setReconState] = useState({ loading: false, overview: EMPTY_RECHARGE_OVERVIEW, summary: EMPTY_RECHARGE_SUMMARY }); const [reconState, setReconState] = useState({
const [myApplicationsState, setMyApplicationsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false }); loading: false,
const [applicationsState, setApplicationsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false }); overview: EMPTY_RECHARGE_OVERVIEW,
const [withdrawalsState, setWithdrawalsState] = useState({ data: { items: [], page: 1, pageSize, total: 0 }, error: "", loading: false }); summary: EMPTY_RECHARGE_SUMMARY,
});
const [myApplicationsState, setMyApplicationsState] = useState({
data: { items: [], page: 1, pageSize, total: 0 },
error: "",
loading: false,
});
const [applicationsState, setApplicationsState] = useState({
data: { items: [], page: 1, pageSize, total: 0 },
error: "",
loading: false,
});
const [withdrawalsState, setWithdrawalsState] = useState({
data: { items: [], page: 1, pageSize, total: 0 },
error: "",
loading: false,
});
const [activeView, setActiveView] = useState("create"); const [activeView, setActiveView] = useState("create");
const [rechargeDetailFilters, setRechargeDetailFilters] = useState(() => ({ const [rechargeDetailFilters, setRechargeDetailFilters] = useState(() => ({
appCode: "", appCode: "",
@ -105,7 +133,7 @@ export function FinanceApp() {
paidState: "", paidState: "",
rechargeType: "", rechargeType: "",
regionId: "", regionId: "",
timeRange: timePresets().find((preset) => preset.key === "30d").range timeRange: timePresets().find((preset) => preset.key === "30d").range,
})); }));
const [rechargeExporting, setRechargeExporting] = useState(false); const [rechargeExporting, setRechargeExporting] = useState(false);
const [myFilters, setMyFilters] = useState({ appCode: "", keyword: "", operation: "", page: 1, status: "" }); const [myFilters, setMyFilters] = useState({ appCode: "", keyword: "", operation: "", page: 1, status: "" });
@ -134,7 +162,7 @@ export function FinanceApp() {
? "applications" ? "applications"
: session.canCreateApplication : session.canCreateApplication
? "create" ? "create"
: "withdrawals" : "withdrawals",
); );
}) })
.catch((err) => { .catch((err) => {
@ -161,18 +189,18 @@ export function FinanceApp() {
region_id: rechargeDetailFilters.appCode ? rechargeDetailFilters.regionId : "", region_id: rechargeDetailFilters.appCode ? rechargeDetailFilters.regionId : "",
start_at_ms: rechargeDetailFilters.timeRange.startMs, start_at_ms: rechargeDetailFilters.timeRange.startMs,
stat_tz: "Asia/Shanghai", stat_tz: "Asia/Shanghai",
status: "succeeded" status: "succeeded",
}), }),
[rechargeDetailFilters] [rechargeDetailFilters],
); );
const rechargeDetailQuery = useMemo( const rechargeDetailQuery = useMemo(
() => ({ () => ({
...rechargeBaseQuery, ...rechargeBaseQuery,
page: rechargeDetailFilters.page, page: rechargeDetailFilters.page,
page_size: pageSize, page_size: pageSize,
paid_state: rechargeDetailFilters.paidState paid_state: rechargeDetailFilters.paidState,
}), }),
[rechargeBaseQuery, rechargeDetailFilters.page, rechargeDetailFilters.paidState] [rechargeBaseQuery, rechargeDetailFilters.page, rechargeDetailFilters.paidState],
); );
const myApplicationQuery = useMemo( const myApplicationQuery = useMemo(
() => ({ () => ({
@ -181,9 +209,9 @@ export function FinanceApp() {
operation: myFilters.operation, operation: myFilters.operation,
page: myFilters.page, page: myFilters.page,
page_size: pageSize, page_size: pageSize,
status: myFilters.status status: myFilters.status,
}), }),
[myFilters] [myFilters],
); );
const applicationQuery = useMemo( const applicationQuery = useMemo(
() => ({ () => ({
@ -192,18 +220,18 @@ export function FinanceApp() {
operation: filters.operation, operation: filters.operation,
page: filters.page, page: filters.page,
page_size: pageSize, page_size: pageSize,
status: filters.status status: filters.status,
}), }),
[filters] [filters],
); );
const withdrawalQuery = useMemo( const withdrawalQuery = useMemo(
() => ({ () => ({
app_code: withdrawalFilters.appCode, app_code: withdrawalFilters.appCode,
keyword: withdrawalFilters.keyword, keyword: withdrawalFilters.keyword,
page: withdrawalFilters.page, page: withdrawalFilters.page,
page_size: pageSize page_size: pageSize,
}), }),
[withdrawalFilters] [withdrawalFilters],
); );
const loadOptions = useCallback(async () => { const loadOptions = useCallback(async () => {
@ -228,14 +256,21 @@ export function FinanceApp() {
const data = await listMyFinanceApplications(myApplicationQuery); const data = await listMyFinanceApplications(myApplicationQuery);
setMyApplicationsState({ data, error: "", loading: false }); setMyApplicationsState({ data, error: "", loading: false });
} catch (err) { } catch (err) {
setMyApplicationsState((current) => ({ ...current, error: err.message || "加载我的申请列表失败", loading: false })); setMyApplicationsState((current) => ({
...current,
error: err.message || "加载我的申请列表失败",
loading: false,
}));
} }
}, [myApplicationQuery, session?.canCreateApplication]); }, [myApplicationQuery, session?.canCreateApplication]);
// App recharge-apps Yumi/Aslan legacy 退 App // App recharge-apps Yumi/Aslan legacy 退 App
const rechargeApps = useMemo( const rechargeApps = useMemo(
() => (rechargeAppsState.loaded && rechargeAppsState.items.length ? rechargeAppsState.items : optionsState.data.apps), () =>
[optionsState.data.apps, rechargeAppsState] rechargeAppsState.loaded && rechargeAppsState.items.length
? rechargeAppsState.items
: optionsState.data.apps,
[optionsState.data.apps, rechargeAppsState],
); );
const loadRechargeApps = useCallback(async () => { const loadRechargeApps = useCallback(async () => {
@ -259,7 +294,11 @@ export function FinanceApp() {
const data = await listFinanceRechargeDetails(rechargeDetailQuery, rechargeApps); const data = await listFinanceRechargeDetails(rechargeDetailQuery, rechargeApps);
setRechargeDetailsState({ data, error: "", loading: false }); setRechargeDetailsState({ data, error: "", loading: false });
} catch (err) { } catch (err) {
setRechargeDetailsState((current) => ({ ...current, error: err.message || "加载充值流水失败", loading: false })); setRechargeDetailsState((current) => ({
...current,
error: err.message || "加载充值流水失败",
loading: false,
}));
} }
}, [canViewFinance, rechargeApps, rechargeDetailQuery]); }, [canViewFinance, rechargeApps, rechargeDetailQuery]);
@ -307,13 +346,13 @@ export function FinanceApp() {
end_at_ms: month.endMs, end_at_ms: month.endMs,
keyword: "", keyword: "",
recharge_type: "", recharge_type: "",
start_at_ms: month.startMs start_at_ms: month.startMs,
}; };
setReconState((current) => ({ ...current, loading: true })); setReconState((current) => ({ ...current, loading: true }));
try { try {
const [{ merged }, overview] = await Promise.all([ const [{ merged }, overview] = await Promise.all([
fetchFinanceRechargeSummaries(query, rechargeApps), fetchFinanceRechargeSummaries(query, rechargeApps),
fetchFinanceRechargeOverview(query, rechargeApps) fetchFinanceRechargeOverview(query, rechargeApps),
]); ]);
setReconState({ loading: false, overview, summary: merged }); setReconState({ loading: false, overview, summary: merged });
} catch { } catch {
@ -322,19 +361,27 @@ export function FinanceApp() {
}, [activeView, canViewFinance, rechargeApps, rechargeBaseQuery, reconMonthOffset]); }, [activeView, canViewFinance, rechargeApps, rechargeBaseQuery, reconMonthOffset]);
const rechargeAppCode = rechargeDetailFilters.appCode; const rechargeAppCode = rechargeDetailFilters.appCode;
// App App App App
const loadRechargeRegions = useCallback(async () => { const loadRechargeRegions = useCallback(async () => {
if (!canViewFinance || !rechargeAppCode) { if (!canViewFinance || !rechargeApps.length) {
setRechargeRegionsState({ appCode: "", items: [], loading: false });
return; return;
} }
setRechargeRegionsState((current) => ({ ...current, appCode: rechargeAppCode, loading: true })); setRechargeRegionsState((current) => ({ ...current, loading: true }));
try { try {
const items = await listFinanceRechargeRegions(rechargeAppCode); const entries = await Promise.all(
setRechargeRegionsState({ appCode: rechargeAppCode, items, loading: false }); rechargeApps.map(async (app) => {
try {
return [app.appCode, await listFinanceRechargeRegions(app.appCode)];
} catch { } catch {
setRechargeRegionsState({ appCode: rechargeAppCode, items: [], loading: false }); return [app.appCode, []];
} }
}, [canViewFinance, rechargeAppCode]); }),
);
setRechargeRegionsState({ byApp: Object.fromEntries(entries), loading: false });
} catch {
setRechargeRegionsState((current) => ({ ...current, loading: false }));
}
}, [canViewFinance, rechargeApps]);
const refreshGooglePaid = useCallback( const refreshGooglePaid = useCallback(
async (transactionIds) => { async (transactionIds) => {
@ -347,8 +394,10 @@ export function FinanceApp() {
const failed = results.filter((item) => item.error).length; const failed = results.filter((item) => item.error).length;
const succeeded = results.length - failed; const succeeded = results.length - failed;
showToast( showToast(
failed ? `谷歌实付同步完成:成功 ${succeeded} 笔,失败 ${failed}` : `谷歌实付同步完成:${succeeded}`, failed
failed ? "warning" : "success" ? `谷歌实付同步完成:成功 ${succeeded} 笔,失败 ${failed}`
: `谷歌实付同步完成:${succeeded}`,
failed ? "warning" : "success",
); );
await Promise.all([loadRechargeDetails(), loadRechargeOverview()]); await Promise.all([loadRechargeDetails(), loadRechargeOverview()]);
} catch (err) { } catch (err) {
@ -357,7 +406,7 @@ export function FinanceApp() {
setGooglePaidRefreshing(false); setGooglePaidRefreshing(false);
} }
}, },
[googlePaidRefreshing, loadRechargeDetails, loadRechargeOverview, rechargeAppCode, showToast] [googlePaidRefreshing, loadRechargeDetails, loadRechargeOverview, rechargeAppCode, showToast],
); );
const exportRechargeBills = useCallback(async () => { const exportRechargeBills = useCallback(async () => {
@ -371,7 +420,7 @@ export function FinanceApp() {
.replaceAll(/[: ]/g, "-"); .replaceAll(/[: ]/g, "-");
await downloadCsv( await downloadCsv(
() => exportFinanceRechargeBills(rechargeAppCode, rechargeDetailQuery), () => exportFinanceRechargeBills(rechargeAppCode, rechargeDetailQuery),
`充值明细-${rechargeAppCode}-${timestamp}.csv` `充值明细-${rechargeAppCode}-${timestamp}.csv`,
); );
showToast("充值明细已导出", "success"); showToast("充值明细已导出", "success");
} catch (err) { } catch (err) {
@ -390,7 +439,11 @@ export function FinanceApp() {
const data = await listFinanceApplications(applicationQuery); const data = await listFinanceApplications(applicationQuery);
setApplicationsState({ data, error: "", loading: false }); setApplicationsState({ data, error: "", loading: false });
} catch (err) { } catch (err) {
setApplicationsState((current) => ({ ...current, error: err.message || "加载申请列表失败", loading: false })); setApplicationsState((current) => ({
...current,
error: err.message || "加载申请列表失败",
loading: false,
}));
} }
}, [applicationQuery, session?.canAuditApplication]); }, [applicationQuery, session?.canAuditApplication]);
@ -403,7 +456,11 @@ export function FinanceApp() {
const data = await listFinanceWithdrawalApplications(withdrawalQuery); const data = await listFinanceWithdrawalApplications(withdrawalQuery);
setWithdrawalsState({ data, error: "", loading: false }); setWithdrawalsState({ data, error: "", loading: false });
} catch (err) { } catch (err) {
setWithdrawalsState((current) => ({ ...current, error: err.message || "加载提现申请列表失败", loading: false })); setWithdrawalsState((current) => ({
...current,
error: err.message || "加载提现申请列表失败",
loading: false,
}));
} }
}, [session?.canViewWithdrawalApplications, withdrawalQuery]); }, [session?.canViewWithdrawalApplications, withdrawalQuery]);
@ -449,7 +506,7 @@ export function FinanceApp() {
const operationOptions = useMemo( const operationOptions = useMemo(
() => filterOperationsByPermissions(optionsState.data.operations, session?.permissions || []), () => filterOperationsByPermissions(optionsState.data.operations, session?.permissions || []),
[optionsState.data.operations, session?.permissions] [optionsState.data.operations, session?.permissions],
); );
const submitApplication = async (event) => { const submitApplication = async (event) => {
@ -471,7 +528,10 @@ export function FinanceApp() {
const result = await createFinanceApplication(cleanPayload(payload)); const result = await createFinanceApplication(cleanPayload(payload));
setForm({ ...DEFAULT_APPLICATION_FORM, appCode: payload.appCode }); setForm({ ...DEFAULT_APPLICATION_FORM, appCode: payload.appCode });
setCreateDialogOpen(false); setCreateDialogOpen(false);
showToast(result?.dingTalkNotified === false ? "申请已提交,钉钉通知未确认" : "申请已提交并通知财务", "success"); showToast(
result?.dingTalkNotified === false ? "申请已提交,钉钉通知未确认" : "申请已提交并通知财务",
"success",
);
await loadMyApplications(); await loadMyApplications();
if (session.canAuditApplication) { if (session.canAuditApplication) {
await loadApplications(); await loadApplications();
@ -507,7 +567,8 @@ export function FinanceApp() {
} }
setWithdrawalAuditLoading(true); setWithdrawalAuditLoading(true);
try { try {
const submitter = decision === "approved" ? approveFinanceWithdrawalApplication : rejectFinanceWithdrawalApplication; const submitter =
decision === "approved" ? approveFinanceWithdrawalApplication : rejectFinanceWithdrawalApplication;
await submitter(withdrawalAuditTarget.id, cleanPayload({ auditImageUrl, auditRemark: remark })); await submitter(withdrawalAuditTarget.id, cleanPayload({ auditImageUrl, auditRemark: remark }));
showToast(decision === "approved" ? "提现申请已通过" : "提现申请已拒绝", "success"); showToast(decision === "approved" ? "提现申请已通过" : "提现申请已拒绝", "success");
setWithdrawalAuditTarget(null); setWithdrawalAuditTarget(null);
@ -558,7 +619,7 @@ export function FinanceApp() {
const activePreset = presets.find( const activePreset = presets.find(
(preset) => (preset) =>
String(preset.range.startMs || "") === String(rechargeDetailFilters.timeRange.startMs || "") && String(preset.range.startMs || "") === String(rechargeDetailFilters.timeRange.startMs || "") &&
String(preset.range.endMs || "") === String(rechargeDetailFilters.timeRange.endMs || "") String(preset.range.endMs || "") === String(rechargeDetailFilters.timeRange.endMs || ""),
); );
const isFinanceView = FINANCE_VIEWS.has(activeView); const isFinanceView = FINANCE_VIEWS.has(activeView);
const financeToolbar = const financeToolbar =
@ -584,13 +645,15 @@ export function FinanceApp() {
<div className="finance-seg" role="group" aria-label="计价单位"> <div className="finance-seg" role="group" aria-label="计价单位">
{[ {[
["usd", "USD"], ["usd", "USD"],
["coin", "金币"] ["coin", "金币"],
].map(([value, label]) => ( ].map(([value, label]) => (
<button <button
className={rechargeDetailFilters.currency === value ? "is-on" : ""} className={rechargeDetailFilters.currency === value ? "is-on" : ""}
key={value} key={value}
type="button" type="button"
onClick={() => updateRechargeDetailFilters({ currency: value, page: rechargeDetailFilters.page })} onClick={() =>
updateRechargeDetailFilters({ currency: value, page: rechargeDetailFilters.page })
}
> >
{label} {label}
</button> </button>
@ -603,7 +666,9 @@ export function FinanceApp() {
isFinanceView && session.canViewAppRechargeDetails ? ( isFinanceView && session.canViewAppRechargeDetails ? (
<div className="finance-appbar"> <div className="finance-appbar">
<button <button
className={["finance-appchip", rechargeDetailFilters.appCode === "" ? "is-on" : ""].filter(Boolean).join(" ")} className={["finance-appchip", rechargeDetailFilters.appCode === "" ? "is-on" : ""]
.filter(Boolean)
.join(" ")}
type="button" type="button"
onClick={() => updateRechargeDetailFilters({ appCode: "", regionId: "" })} onClick={() => updateRechargeDetailFilters({ appCode: "", regionId: "" })}
> >
@ -611,7 +676,9 @@ export function FinanceApp() {
</button> </button>
{rechargeApps.map((app) => ( {rechargeApps.map((app) => (
<button <button
className={["finance-appchip", rechargeDetailFilters.appCode === app.appCode ? "is-on" : ""].filter(Boolean).join(" ")} className={["finance-appchip", rechargeDetailFilters.appCode === app.appCode ? "is-on" : ""]
.filter(Boolean)
.join(" ")}
key={app.appCode} key={app.appCode}
type="button" type="button"
onClick={() => updateRechargeDetailFilters({ appCode: app.appCode, regionId: "" })} onClick={() => updateRechargeDetailFilters({ appCode: app.appCode, regionId: "" })}
@ -629,7 +696,13 @@ export function FinanceApp() {
canCreate={session.canCreateApplication} canCreate={session.canCreateApplication}
canViewRechargeDetails={session.canViewAppRechargeDetails} canViewRechargeDetails={session.canViewAppRechargeDetails}
canViewWithdrawals={session.canViewWithdrawalApplications} canViewWithdrawals={session.canViewWithdrawalApplications}
loading={optionsState.loading || rechargeDetailsState.loading || myApplicationsState.loading || applicationsState.loading || withdrawalsState.loading} loading={
optionsState.loading ||
rechargeDetailsState.loading ||
myApplicationsState.loading ||
applicationsState.loading ||
withdrawalsState.loading
}
session={session} session={session}
subtitle={isFinanceView ? "中国时区 · 数据实时" : ""} subtitle={isFinanceView ? "中国时区 · 数据实时" : ""}
toolbar={financeToolbar} toolbar={financeToolbar}
@ -675,7 +748,8 @@ export function FinanceApp() {
filters={rechargeDetailFilters} filters={rechargeDetailFilters}
googlePaidRefreshing={googlePaidRefreshing} googlePaidRefreshing={googlePaidRefreshing}
loading={rechargeDetailsState.loading} loading={rechargeDetailsState.loading}
regions={rechargeRegionsState.items} regions={rechargeRegionsState.byApp[rechargeAppCode] || []}
regionsByApp={rechargeRegionsState.byApp}
summary={rechargeSummaryState.merged} summary={rechargeSummaryState.merged}
onExport={exportRechargeBills} onExport={exportRechargeBills}
onFiltersChange={updateRechargeDetailFilters} onFiltersChange={updateRechargeDetailFilters}

View File

@ -37,6 +37,7 @@ export function FinanceRechargeDetailList({
onRefreshGooglePaid, onRefreshGooglePaid,
onReload, onReload,
regions, regions,
regionsByApp,
summary, summary,
}) { }) {
const [expandedId, setExpandedId] = useState(""); const [expandedId, setExpandedId] = useState("");
@ -231,7 +232,7 @@ export function FinanceRechargeDetailList({
</AmountText> </AmountText>
</td> </td>
<td className="r num">{taxDeductionText(item)}</td> <td className="r num">{taxDeductionText(item)}</td>
<td>{regionText(item, regionNames)}</td> <td>{regionText(item, regionsByApp, apps, !filters.appCode)}</td>
</tr> </tr>
{expanded ? ( {expanded ? (
<tr className="finance-detailrow"> <tr className="finance-detailrow">
@ -445,12 +446,15 @@ function appName(appCode, apps) {
return (apps || []).find((app) => app.appCode === appCode)?.appName || appCode || "-"; return (apps || []).find((app) => app.appCode === appCode)?.appName || appCode || "-";
} }
function regionText(item, regionNames) { // regionText App App Lalu- App
function regionText(item, regionsByApp, apps, withAppPrefix) {
const regionId = item.targetRegionId || item.sellerRegionId; const regionId = item.targetRegionId || item.sellerRegionId;
if (!regionId) { if (!regionId) {
return "—"; return "—";
} }
return regionNames.get(String(regionId)) || `区域 ${regionId}`; const appRegions = (regionsByApp || {})[item.appCode] || [];
const name = appRegions.find((region) => String(region.regionId) === String(regionId))?.name || `区域 ${regionId}`;
return withAppPrefix ? `${appName(item.appCode, apps)}-${name}` : name;
} }
function secondaryOrderNo(item) { function secondaryOrderNo(item) {