财务口径
This commit is contained in:
parent
31804f5e34
commit
ad4d4151f5
@ -4506,6 +4506,98 @@
|
||||
"x-permissions": ["finance-withdrawal:audit"]
|
||||
}
|
||||
},
|
||||
"/admin/operations/withdrawal-applications": {
|
||||
"get": {
|
||||
"operationId": "listOperationsWithdrawalApplications",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "app_code",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "keyword",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "page",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "page_size",
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/FinanceWithdrawalApplicationPageResponse"
|
||||
}
|
||||
},
|
||||
"x-permission": "operations-withdrawal:view",
|
||||
"x-permissions": ["operations-withdrawal:view", "operations-withdrawal:audit"]
|
||||
}
|
||||
},
|
||||
"/admin/operations/withdrawal-applications/{application_id}/approve": {
|
||||
"post": {
|
||||
"operationId": "approveOperationsWithdrawalApplication",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "application_id",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"$ref": "#/components/requestBodies/OperationsWithdrawalAuditRequest"
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/FinanceWithdrawalApplicationResponse"
|
||||
}
|
||||
},
|
||||
"x-permission": "operations-withdrawal:audit",
|
||||
"x-permissions": ["operations-withdrawal:audit"]
|
||||
}
|
||||
},
|
||||
"/admin/operations/withdrawal-applications/{application_id}/reject": {
|
||||
"post": {
|
||||
"operationId": "rejectOperationsWithdrawalApplication",
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "application_id",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"$ref": "#/components/requestBodies/OperationsWithdrawalAuditRequest"
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/FinanceWithdrawalApplicationResponse"
|
||||
}
|
||||
},
|
||||
"x-permission": "operations-withdrawal:audit",
|
||||
"x-permissions": ["operations-withdrawal:audit"]
|
||||
}
|
||||
},
|
||||
"/admin/finance/orders/coin-seller-recharges": {
|
||||
"get": {
|
||||
"operationId": "listFinanceCoinSellerRechargeOrders",
|
||||
@ -8640,6 +8732,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"OperationsWithdrawalAuditRequest": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"auditRemark": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MenuRequest": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
@ -14055,6 +14161,27 @@
|
||||
"status": {
|
||||
"type": "string"
|
||||
},
|
||||
"operationsStatus": {
|
||||
"enum": ["pending", "approved", "rejected"],
|
||||
"type": "string"
|
||||
},
|
||||
"operationsReviewerUserId": {
|
||||
"nullable": true,
|
||||
"type": "integer"
|
||||
},
|
||||
"operationsReviewerName": {
|
||||
"type": "string"
|
||||
},
|
||||
"operationsAuditRemark": {
|
||||
"type": "string"
|
||||
},
|
||||
"operationsAuditTransactionId": {
|
||||
"type": "string"
|
||||
},
|
||||
"operationsReviewedAtMs": {
|
||||
"nullable": true,
|
||||
"type": "integer"
|
||||
},
|
||||
"approverUserId": {
|
||||
"nullable": true,
|
||||
"type": "integer"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
approveFinanceWithdrawalApplication,
|
||||
approveOperationsWithdrawalApplication,
|
||||
createFinanceCoinSellerRechargeOrder,
|
||||
exportFinanceRechargeBills,
|
||||
fetchFinanceOptions,
|
||||
@ -15,9 +16,11 @@ import {
|
||||
listFinanceRechargeDetails,
|
||||
listFinanceRechargeRegions,
|
||||
listFinanceWithdrawalApplications,
|
||||
listOperationsWithdrawalApplications,
|
||||
refreshFinanceGoogleRechargePaid,
|
||||
replaceFinanceCoinSellerRechargeExchangeRate,
|
||||
rejectFinanceWithdrawalApplication,
|
||||
rejectOperationsWithdrawalApplication,
|
||||
quoteFinanceCoinSellerRechargeOrder,
|
||||
upsertFinanceUSDTAddress,
|
||||
verifyFinanceCoinSellerRechargeReceipt,
|
||||
@ -41,7 +44,63 @@ const emptyOptions = { apps: [] };
|
||||
const pageSize = 50;
|
||||
const DAY_MS = 86_400_000;
|
||||
const CHINA_OFFSET_MS = 8 * 3_600_000;
|
||||
const FINANCE_VIEWS = new Set(["overview", "rechargeDetails", "recon"]);
|
||||
const RECHARGE_VIEWS = new Set(["overview", "rechargeDetails", "recon"]);
|
||||
const FINANCE_VIEW_ALIASES = new Map([["withdrawals", "withdrawalFinance"]]);
|
||||
|
||||
function requestedFinanceView() {
|
||||
const requested = new URLSearchParams(window.location.search).get("view") || "";
|
||||
return FINANCE_VIEW_ALIASES.get(requested) || requested;
|
||||
}
|
||||
|
||||
function canAccessFinanceView(session, view) {
|
||||
if (RECHARGE_VIEWS.has(view)) {
|
||||
return Boolean(session?.canViewAppRechargeDetails);
|
||||
}
|
||||
if (view === "coinSellerRechargeOrders") {
|
||||
return Boolean(session?.canViewCoinSellerRechargeOrders);
|
||||
}
|
||||
if (view === "withdrawalOperations") {
|
||||
return Boolean(session?.canViewOperationsWithdrawalApplications);
|
||||
}
|
||||
if (view === "withdrawalFinance") {
|
||||
return Boolean(session?.canViewWithdrawalApplications);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function defaultFinanceView(session) {
|
||||
if (session?.canViewAppRechargeDetails) {
|
||||
return "overview";
|
||||
}
|
||||
if (session?.canViewCoinSellerRechargeOrders) {
|
||||
return "coinSellerRechargeOrders";
|
||||
}
|
||||
if (session?.canViewOperationsWithdrawalApplications) {
|
||||
return "withdrawalOperations";
|
||||
}
|
||||
if (session?.canViewWithdrawalApplications) {
|
||||
return "withdrawalFinance";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function resolvedFinanceView(session) {
|
||||
const requested = requestedFinanceView();
|
||||
return canAccessFinanceView(session, requested) ? requested : defaultFinanceView(session);
|
||||
}
|
||||
|
||||
function syncFinanceView(view) {
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
const url = new URL(window.location.href);
|
||||
if (url.searchParams.get("view") === view) {
|
||||
return;
|
||||
}
|
||||
// 工作台是独立 HTML 入口,内部视图只同步 query;保留其他筛选参数和 hash,避免点击菜单破坏外部深链上下文。
|
||||
url.searchParams.set("view", view);
|
||||
window.history.replaceState(window.history.state, "", `${url.pathname}${url.search}${url.hash}`);
|
||||
}
|
||||
|
||||
function chinaDayStart(timestamp) {
|
||||
return Math.floor((timestamp + CHINA_OFFSET_MS) / DAY_MS) * DAY_MS - CHINA_OFFSET_MS;
|
||||
|
||||
@ -29,6 +29,8 @@ export async function fetchFinanceSession() {
|
||||
const permissions = Array.isArray(session.permissions) ? session.permissions : [];
|
||||
const canAuditWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.auditWithdrawalApplications);
|
||||
const canViewWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.viewWithdrawalApplications) || canAuditWithdrawalApplications;
|
||||
const canAuditOperationsWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.auditOperationsWithdrawalApplications);
|
||||
const canViewOperationsWithdrawalApplications = permissions.includes(FINANCE_PERMISSIONS.viewOperationsWithdrawalApplications) || canAuditOperationsWithdrawalApplications;
|
||||
const canViewAppRechargeDetails = permissions.includes(FINANCE_PERMISSIONS.viewAppRechargeDetails);
|
||||
const canViewCoinSellerRechargeOrders = permissions.includes(FINANCE_PERMISSIONS.viewCoinSellerRechargeOrders);
|
||||
const canCreateCoinSellerRechargeOrder = permissions.includes(FINANCE_PERMISSIONS.createCoinSellerRechargeOrder);
|
||||
@ -41,8 +43,10 @@ export async function fetchFinanceSession() {
|
||||
...session,
|
||||
canAccessFinance:
|
||||
canViewWithdrawalApplications ||
|
||||
canViewOperationsWithdrawalApplications ||
|
||||
canViewAppRechargeDetails ||
|
||||
canViewCoinSellerRechargeOrders,
|
||||
canAuditOperationsWithdrawalApplications,
|
||||
canAuditWithdrawalApplications,
|
||||
canConfigureCoinSellerRechargeExchangeRate,
|
||||
canCreateCoinSellerRechargeOrder,
|
||||
@ -51,6 +55,7 @@ export async function fetchFinanceSession() {
|
||||
canVerifyCoinSellerRechargeOrder,
|
||||
canViewAppRechargeDetails,
|
||||
canViewCoinSellerRechargeOrders,
|
||||
canViewOperationsWithdrawalApplications,
|
||||
canViewWithdrawalApplications,
|
||||
permissions
|
||||
};
|
||||
@ -82,6 +87,15 @@ export async function listFinanceWithdrawalApplications(query = {}) {
|
||||
return normalizeWithdrawalApplicationPage(data);
|
||||
}
|
||||
|
||||
export async function listOperationsWithdrawalApplications(query = {}) {
|
||||
const endpoint = API_ENDPOINTS.listOperationsWithdrawalApplications;
|
||||
const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listOperationsWithdrawalApplications), {
|
||||
method: endpoint.method,
|
||||
query
|
||||
});
|
||||
return normalizeWithdrawalApplicationPage(data);
|
||||
}
|
||||
|
||||
export async function listFinanceCoinSellerRechargeOrders(query = {}) {
|
||||
const endpoint = API_ENDPOINTS.listFinanceCoinSellerRechargeOrders;
|
||||
const data = await apiRequest(apiEndpointPath(API_OPERATIONS.listFinanceCoinSellerRechargeOrders), {
|
||||
@ -305,6 +319,22 @@ export async function rejectFinanceWithdrawalApplication(applicationId, payload)
|
||||
});
|
||||
}
|
||||
|
||||
export async function approveOperationsWithdrawalApplication(applicationId, payload) {
|
||||
const endpoint = API_ENDPOINTS.approveOperationsWithdrawalApplication;
|
||||
return apiRequest(apiEndpointPath(API_OPERATIONS.approveOperationsWithdrawalApplication, { application_id: applicationId }), {
|
||||
body: payload,
|
||||
method: endpoint.method
|
||||
});
|
||||
}
|
||||
|
||||
export async function rejectOperationsWithdrawalApplication(applicationId, payload) {
|
||||
const endpoint = API_ENDPOINTS.rejectOperationsWithdrawalApplication;
|
||||
return apiRequest(apiEndpointPath(API_OPERATIONS.rejectOperationsWithdrawalApplication, { application_id: applicationId }), {
|
||||
body: payload,
|
||||
method: endpoint.method
|
||||
});
|
||||
}
|
||||
|
||||
async function currentSession() {
|
||||
try {
|
||||
return await refreshSession();
|
||||
|
||||
@ -8,7 +8,17 @@ import { useEffect, useState } from "react";
|
||||
import { AppIdentity } from "@/shared/ui/AppIdentity.jsx";
|
||||
import { UploadField } from "@/shared/ui/UploadField.jsx";
|
||||
|
||||
export function FinanceAuditDialog({ application, apps = [], loading, onClose, onSubmit, open, requireApprovalImage = false, requireRejectRemark = false }) {
|
||||
export function FinanceAuditDialog({
|
||||
application,
|
||||
apps = [],
|
||||
loading,
|
||||
onClose,
|
||||
onSubmit,
|
||||
open,
|
||||
requireApprovalImage = false,
|
||||
requireRejectRemark = false,
|
||||
reviewLabel = "财务",
|
||||
}) {
|
||||
const [remark, setRemark] = useState("");
|
||||
const [auditImageUrl, setAuditImageUrl] = useState("");
|
||||
const decision = application?.decision || "approved";
|
||||
@ -29,7 +39,7 @@ export function FinanceAuditDialog({ application, apps = [], loading, onClose, o
|
||||
|
||||
return (
|
||||
<Dialog fullWidth maxWidth="sm" open={open} onClose={loading ? undefined : onClose}>
|
||||
<DialogTitle>{decision === "approved" ? "通过申请" : "拒绝申请"}</DialogTitle>
|
||||
<DialogTitle>{decision === "approved" ? `通过${reviewLabel}审核` : `拒绝${reviewLabel}审核`}</DialogTitle>
|
||||
<DialogContent className="finance-audit-dialog">
|
||||
<div className="finance-audit-summary">
|
||||
<AppIdentity
|
||||
|
||||
@ -19,7 +19,10 @@ const NAV_GROUPS = [
|
||||
},
|
||||
{
|
||||
label: "审批",
|
||||
views: [{ icon: PaymentsOutlined, id: "withdrawals", label: "用户提现申请" }],
|
||||
views: [
|
||||
{ icon: PaymentsOutlined, id: "withdrawalOperations", label: "用户提现运营审核" },
|
||||
{ icon: PaymentsOutlined, id: "withdrawalFinance", label: "用户提现财务审核" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@ -28,7 +31,8 @@ const VIEW_TITLES = {
|
||||
overview: "财务概览",
|
||||
recon: "渠道对账",
|
||||
rechargeDetails: "充值流水",
|
||||
withdrawals: "用户提现申请",
|
||||
withdrawalFinance: "用户提现财务审核",
|
||||
withdrawalOperations: "用户提现运营审核",
|
||||
};
|
||||
|
||||
export function FinanceShell({
|
||||
@ -36,7 +40,8 @@ export function FinanceShell({
|
||||
appBar,
|
||||
canViewCoinSellerRechargeOrders,
|
||||
canViewRechargeDetails,
|
||||
canViewWithdrawals,
|
||||
canViewFinanceWithdrawals,
|
||||
canViewOperationsWithdrawals,
|
||||
children,
|
||||
loading,
|
||||
onViewChange,
|
||||
@ -51,8 +56,11 @@ export function FinanceShell({
|
||||
if (viewId === "coinSellerRechargeOrders") {
|
||||
return canViewCoinSellerRechargeOrders;
|
||||
}
|
||||
if (viewId === "withdrawals") {
|
||||
return canViewWithdrawals;
|
||||
if (viewId === "withdrawalFinance") {
|
||||
return canViewFinanceWithdrawals;
|
||||
}
|
||||
if (viewId === "withdrawalOperations") {
|
||||
return canViewOperationsWithdrawals;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -15,8 +15,20 @@ import { AppIdentity } from "@/shared/ui/AppIdentity.jsx";
|
||||
import { useToast } from "@/shared/ui/ToastProvider.jsx";
|
||||
import { formatAmount, formatTime, statusLabel } from "../format.js";
|
||||
|
||||
export function FinanceWithdrawalApplicationList({ applications, canAudit, error, filters, loading, onAudit, onFiltersChange, onReload, options }) {
|
||||
export function FinanceWithdrawalApplicationList({
|
||||
applications,
|
||||
canAudit,
|
||||
error,
|
||||
filters,
|
||||
loading,
|
||||
onAudit,
|
||||
onFiltersChange,
|
||||
onReload,
|
||||
options,
|
||||
reviewStage = "finance",
|
||||
}) {
|
||||
const { showToast } = useToast();
|
||||
const isOperationsReview = reviewStage === "operations";
|
||||
const items = applications.items || [];
|
||||
const page = Number(applications.page || filters.page || 1);
|
||||
const pageSize = Number(applications.pageSize || 50);
|
||||
@ -66,9 +78,20 @@ export function FinanceWithdrawalApplicationList({ applications, canAudit, error
|
||||
<TableCell>提现方式</TableCell>
|
||||
<TableCell>提现地址</TableCell>
|
||||
<TableCell className="finance-time-cell">申请时间</TableCell>
|
||||
<TableCell>审批人</TableCell>
|
||||
<TableCell className="finance-time-cell">审批时间</TableCell>
|
||||
<TableCell>审核原因</TableCell>
|
||||
{isOperationsReview ? (
|
||||
<>
|
||||
<TableCell>运营审核人</TableCell>
|
||||
<TableCell className="finance-time-cell">运营审核时间</TableCell>
|
||||
<TableCell>运营审核原因</TableCell>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableCell>运营审核</TableCell>
|
||||
<TableCell>财务审核人</TableCell>
|
||||
<TableCell className="finance-time-cell">财务审核时间</TableCell>
|
||||
<TableCell>财务审核原因</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableCell align="right">操作</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
@ -104,30 +127,73 @@ export function FinanceWithdrawalApplicationList({ applications, canAudit, error
|
||||
) : "-"}
|
||||
</TableCell>
|
||||
<TableCell className="finance-time-cell">{formatTime(item.createdAtMs)}</TableCell>
|
||||
<TableCell>
|
||||
<Stacked primary={item.approverName || "-"} secondary={item.approverUserId || ""} />
|
||||
</TableCell>
|
||||
<TableCell className="finance-time-cell">{formatTime(item.approvedAtMs)}</TableCell>
|
||||
<TableCell>{item.auditRemark || "-"}</TableCell>
|
||||
{isOperationsReview ? (
|
||||
<>
|
||||
<TableCell>
|
||||
<Stacked
|
||||
primary={item.operationsReviewerName || "-"}
|
||||
secondary={item.operationsReviewerUserId || ""}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell className="finance-time-cell">{formatTime(item.operationsReviewedAtMs)}</TableCell>
|
||||
<TableCell>{item.operationsAuditRemark || "-"}</TableCell>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<TableCell>
|
||||
<ReviewContext application={item} />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Stacked primary={item.approverName || "-"} secondary={item.approverUserId || ""} />
|
||||
</TableCell>
|
||||
<TableCell className="finance-time-cell">{formatTime(item.approvedAtMs)}</TableCell>
|
||||
<TableCell>{item.auditRemark || "-"}</TableCell>
|
||||
</>
|
||||
)}
|
||||
<TableCell align="right">
|
||||
{item.status === "pending" && canAudit ? (
|
||||
{(isOperationsReview ? item.operationsStatus : item.status) === "pending" && canAudit ? (
|
||||
<span className="finance-row-actions">
|
||||
<Button size="small" variant="contained" onClick={() => onAudit({ ...item, decision: "approved", operation: "用户提现", targetUserId: item.userId })}>
|
||||
<Button
|
||||
size="small"
|
||||
variant="contained"
|
||||
onClick={() =>
|
||||
onAudit({
|
||||
...item,
|
||||
decision: "approved",
|
||||
operation: isOperationsReview ? "用户提现运营审核" : "用户提现财务审核",
|
||||
reviewStage,
|
||||
targetUserId: item.userId,
|
||||
})
|
||||
}
|
||||
>
|
||||
通过
|
||||
</Button>
|
||||
<Button color="error" size="small" variant="outlined" onClick={() => onAudit({ ...item, decision: "rejected", operation: "用户提现", targetUserId: item.userId })}>
|
||||
<Button
|
||||
color="error"
|
||||
size="small"
|
||||
variant="outlined"
|
||||
onClick={() =>
|
||||
onAudit({
|
||||
...item,
|
||||
decision: "rejected",
|
||||
operation: isOperationsReview ? "用户提现运营审核" : "用户提现财务审核",
|
||||
reviewStage,
|
||||
targetUserId: item.userId,
|
||||
})
|
||||
}
|
||||
>
|
||||
拒绝
|
||||
</Button>
|
||||
</span>
|
||||
) : (
|
||||
statusLabel(item.status)
|
||||
statusLabel(isOperationsReview ? item.operationsStatus : item.status)
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell align="center" colSpan={10}>
|
||||
<TableCell align="center" colSpan={isOperationsReview ? 10 : 11}>
|
||||
当前无数据
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@ -153,6 +219,19 @@ export function FinanceWithdrawalApplicationList({ applications, canAudit, error
|
||||
);
|
||||
}
|
||||
|
||||
function ReviewContext({ application }) {
|
||||
return (
|
||||
<span className="finance-review-context">
|
||||
<Stacked
|
||||
primary={application.operationsReviewerName || statusLabel(application.operationsStatus)}
|
||||
secondary={application.operationsReviewerUserId || ""}
|
||||
/>
|
||||
<small>{formatTime(application.operationsReviewedAtMs)}</small>
|
||||
<small title={application.operationsAuditRemark || ""}>{application.operationsAuditRemark || "-"}</small>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function Stacked({ primary, secondary }) {
|
||||
return (
|
||||
<span className="finance-stack">
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
export const FINANCE_PERMISSIONS = {
|
||||
auditWithdrawalApplications: "finance-withdrawal:audit",
|
||||
auditOperationsWithdrawalApplications: "operations-withdrawal:audit",
|
||||
configureCoinSellerRechargeExchangeRate: "coin-seller:exchange-rate",
|
||||
createCoinSellerRechargeOrder: "finance-order:coin-seller-recharge:create",
|
||||
grantCoinSellerRechargeOrder: "finance-order:coin-seller-recharge:grant",
|
||||
@ -7,6 +8,7 @@ export const FINANCE_PERMISSIONS = {
|
||||
verifyCoinSellerRechargeOrder: "finance-order:coin-seller-recharge:verify",
|
||||
viewCoinSellerRechargeOrders: "finance-order:coin-seller-recharge:view",
|
||||
viewAppRechargeDetails: "payment-bill:view",
|
||||
viewOperationsWithdrawalApplications: "operations-withdrawal:view",
|
||||
viewWithdrawalApplications: "finance-withdrawal:view",
|
||||
};
|
||||
|
||||
|
||||
@ -22,6 +22,14 @@ export function normalizeWithdrawalApplication(item = {}) {
|
||||
createdAtMs: numberOrNull(item.createdAtMs ?? item.created_at_ms),
|
||||
freezeTransactionId: stringValue(item.freezeTransactionId ?? item.freeze_transaction_id),
|
||||
id: item.id ?? item.withdrawalApplicationId ?? item.withdrawal_application_id,
|
||||
operationsAuditRemark: stringValue(item.operationsAuditRemark ?? item.operations_audit_remark),
|
||||
operationsAuditTransactionId: stringValue(
|
||||
item.operationsAuditTransactionId ?? item.operations_audit_transaction_id,
|
||||
),
|
||||
operationsReviewedAtMs: numberOrNull(item.operationsReviewedAtMs ?? item.operations_reviewed_at_ms),
|
||||
operationsReviewerName: stringValue(item.operationsReviewerName ?? item.operations_reviewer_name),
|
||||
operationsReviewerUserId: item.operationsReviewerUserId ?? item.operations_reviewer_user_id,
|
||||
operationsStatus: stringValue(item.operationsStatus ?? item.operations_status),
|
||||
salaryAssetType: stringValue(item.salaryAssetType ?? item.salary_asset_type),
|
||||
status: stringValue(item.status),
|
||||
updatedAtMs: numberOrNull(item.updatedAtMs ?? item.updated_at_ms),
|
||||
|
||||
@ -462,6 +462,20 @@ a {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* 财务审核必须能在同一行确认前置运营结论;上下文收敛在单元格内,避免为备注额外拉宽整张审批表。 */
|
||||
.finance-review-context {
|
||||
display: grid;
|
||||
min-width: 180px;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.finance-review-context > small {
|
||||
max-width: 220px;
|
||||
overflow: hidden;
|
||||
color: var(--text-tertiary);
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.finance-address-wrap {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@ -51,6 +51,8 @@ export const PERMISSIONS = {
|
||||
financeView: "finance:view",
|
||||
financeWithdrawalView: "finance-withdrawal:view",
|
||||
financeWithdrawalAudit: "finance-withdrawal:audit",
|
||||
operationsWithdrawalView: "operations-withdrawal:view",
|
||||
operationsWithdrawalAudit: "operations-withdrawal:audit",
|
||||
financeOrderCoinSellerRechargeView: "finance-order:coin-seller-recharge:view",
|
||||
financeOrderCoinSellerRechargeCreate: "finance-order:coin-seller-recharge:create",
|
||||
financeOrderCoinSellerRechargeVerify: "finance-order:coin-seller-recharge:verify",
|
||||
|
||||
@ -27,6 +27,7 @@ export const API_OPERATIONS = {
|
||||
appListUsers: "appListUsers",
|
||||
approveCoinSellerSubApplication: "approveCoinSellerSubApplication",
|
||||
approveFinanceWithdrawalApplication: "approveFinanceWithdrawalApplication",
|
||||
approveOperationsWithdrawalApplication: "approveOperationsWithdrawalApplication",
|
||||
appSetPassword: "appSetPassword",
|
||||
appUnbanUser: "appUnbanUser",
|
||||
appUpdateUser: "appUpdateUser",
|
||||
@ -238,6 +239,7 @@ export const API_OPERATIONS = {
|
||||
listLuckyGiftPoolBalances: "listLuckyGiftPoolBalances",
|
||||
listManagers: "listManagers",
|
||||
listOperationLogs: "listOperationLogs",
|
||||
listOperationsWithdrawalApplications: "listOperationsWithdrawalApplications",
|
||||
listPermissions: "listPermissions",
|
||||
listPlatformGrantRecords: "listPlatformGrantRecords",
|
||||
listPlatformGrantUsers: "listPlatformGrantUsers",
|
||||
@ -300,6 +302,7 @@ export const API_OPERATIONS = {
|
||||
refreshGoogleRechargePaid: "refreshGoogleRechargePaid",
|
||||
rejectCoinSellerSubApplication: "rejectCoinSellerSubApplication",
|
||||
rejectFinanceWithdrawalApplication: "rejectFinanceWithdrawalApplication",
|
||||
rejectOperationsWithdrawalApplication: "rejectOperationsWithdrawalApplication",
|
||||
renameCountryCode: "renameCountryCode",
|
||||
replaceCoinSellerSalaryRates: "replaceCoinSellerSalaryRates",
|
||||
replaceFinanceCoinSellerRechargeExchangeRate: "replaceFinanceCoinSellerRechargeExchangeRate",
|
||||
@ -513,6 +516,13 @@ export const API_ENDPOINTS: Record<ApiOperationId, ApiEndpoint> = {
|
||||
permission: "finance-withdrawal:audit",
|
||||
permissions: ["finance-withdrawal:audit"]
|
||||
},
|
||||
approveOperationsWithdrawalApplication: {
|
||||
method: "POST",
|
||||
operationId: API_OPERATIONS.approveOperationsWithdrawalApplication,
|
||||
path: "/v1/admin/operations/withdrawal-applications/{application_id}/approve",
|
||||
permission: "operations-withdrawal:audit",
|
||||
permissions: ["operations-withdrawal:audit"]
|
||||
},
|
||||
appSetPassword: {
|
||||
method: "POST",
|
||||
operationId: API_OPERATIONS.appSetPassword,
|
||||
@ -1986,6 +1996,13 @@ export const API_ENDPOINTS: Record<ApiOperationId, ApiEndpoint> = {
|
||||
permission: "log:view",
|
||||
permissions: ["log:view"]
|
||||
},
|
||||
listOperationsWithdrawalApplications: {
|
||||
method: "GET",
|
||||
operationId: API_OPERATIONS.listOperationsWithdrawalApplications,
|
||||
path: "/v1/admin/operations/withdrawal-applications",
|
||||
permission: "operations-withdrawal:view",
|
||||
permissions: ["operations-withdrawal:view","operations-withdrawal:audit"]
|
||||
},
|
||||
listPermissions: {
|
||||
method: "GET",
|
||||
operationId: API_OPERATIONS.listPermissions,
|
||||
@ -2408,6 +2425,13 @@ export const API_ENDPOINTS: Record<ApiOperationId, ApiEndpoint> = {
|
||||
permission: "finance-withdrawal:audit",
|
||||
permissions: ["finance-withdrawal:audit"]
|
||||
},
|
||||
rejectOperationsWithdrawalApplication: {
|
||||
method: "POST",
|
||||
operationId: API_OPERATIONS.rejectOperationsWithdrawalApplication,
|
||||
path: "/v1/admin/operations/withdrawal-applications/{application_id}/reject",
|
||||
permission: "operations-withdrawal:audit",
|
||||
permissions: ["operations-withdrawal:audit"]
|
||||
},
|
||||
renameCountryCode: {
|
||||
method: "POST",
|
||||
operationId: API_OPERATIONS.renameCountryCode,
|
||||
|
||||
107
src/shared/api/generated/schema.d.ts
vendored
107
src/shared/api/generated/schema.d.ts
vendored
@ -2556,6 +2556,54 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/operations/withdrawal-applications": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: operations["listOperationsWithdrawalApplications"];
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/operations/withdrawal-applications/{application_id}/approve": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["approveOperationsWithdrawalApplication"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/operations/withdrawal-applications/{application_id}/reject": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["rejectOperationsWithdrawalApplication"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/admin/finance/orders/coin-seller-recharges": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@ -6485,6 +6533,13 @@ export interface components {
|
||||
freezeTransactionId?: string;
|
||||
auditTransactionId?: string;
|
||||
status?: string;
|
||||
/** @enum {string} */
|
||||
operationsStatus?: "pending" | "approved" | "rejected";
|
||||
operationsReviewerUserId?: number | null;
|
||||
operationsReviewerName?: string;
|
||||
operationsAuditRemark?: string;
|
||||
operationsAuditTransactionId?: string;
|
||||
operationsReviewedAtMs?: number | null;
|
||||
approverUserId?: number | null;
|
||||
approverName?: string;
|
||||
auditRemark?: string;
|
||||
@ -7928,6 +7983,13 @@ export interface components {
|
||||
};
|
||||
};
|
||||
};
|
||||
OperationsWithdrawalAuditRequest: {
|
||||
content: {
|
||||
"application/json": {
|
||||
auditRemark?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
MenuRequest: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["MenuInput"];
|
||||
@ -11220,6 +11282,51 @@ export interface operations {
|
||||
200: components["responses"]["FinanceWithdrawalApplicationResponse"];
|
||||
};
|
||||
};
|
||||
listOperationsWithdrawalApplications: {
|
||||
parameters: {
|
||||
query?: {
|
||||
app_code?: string;
|
||||
keyword?: string;
|
||||
page?: number;
|
||||
page_size?: number;
|
||||
};
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
200: components["responses"]["FinanceWithdrawalApplicationPageResponse"];
|
||||
};
|
||||
};
|
||||
approveOperationsWithdrawalApplication: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
application_id: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: components["requestBodies"]["OperationsWithdrawalAuditRequest"];
|
||||
responses: {
|
||||
200: components["responses"]["FinanceWithdrawalApplicationResponse"];
|
||||
};
|
||||
};
|
||||
rejectOperationsWithdrawalApplication: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
application_id: number;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: components["requestBodies"]["OperationsWithdrawalAuditRequest"];
|
||||
responses: {
|
||||
200: components["responses"]["FinanceWithdrawalApplicationResponse"];
|
||||
};
|
||||
};
|
||||
listFinanceCoinSellerRechargeOrders: {
|
||||
parameters: {
|
||||
query?: {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user