diff --git a/contracts/admin-openapi.json b/contracts/admin-openapi.json index e6909f2..69aa964 100644 --- a/contracts/admin-openapi.json +++ b/contracts/admin-openapi.json @@ -2729,6 +2729,30 @@ "x-permissions": ["payment-product:delete"] } }, + "/admin/money/scope": { + "get": { + "operationId": "getMoneyScope", + "responses": { + "200": { + "$ref": "#/components/responses/EmptyResponse" + } + }, + "x-permission": "money:view", + "x-permissions": ["money:view"] + } + }, + "/admin/money/performance": { + "get": { + "operationId": "getMoneyPerformance", + "responses": { + "200": { + "$ref": "#/components/responses/EmptyResponse" + } + }, + "x-permission": "money:view", + "x-permissions": ["money:view"] + } + }, "/admin/payment/temporary-links": { "get": { "operationId": "listTemporaryPaymentLinks", @@ -2738,7 +2762,20 @@ } }, "x-permission": "payment-temporary-link:view", - "x-permissions": ["payment-temporary-link:view"] + "x-permissions": ["payment-temporary-link:view", "money:view"] + }, + "post": { + "operationId": "createTemporaryPaymentLink", + "requestBody": { + "$ref": "#/components/requestBodies/TemporaryPaymentLinkRequest" + }, + "responses": { + "200": { + "$ref": "#/components/responses/EmptyResponse" + } + }, + "x-permission": "money:payment-link:create", + "x-permissions": ["money:payment-link:create"] } }, "/admin/payment/temporary-links/{order_id}": { @@ -2760,7 +2797,7 @@ } ], "x-permission": "payment-temporary-link:view", - "x-permissions": ["payment-temporary-link:view"] + "x-permissions": ["payment-temporary-link:view", "money:view"] } }, "/admin/payment/third-party-channels": { @@ -2772,7 +2809,7 @@ } }, "x-permission": "payment-third-party:view", - "x-permissions": ["payment-third-party:view"] + "x-permissions": ["payment-third-party:view", "money:view"] } }, "/admin/payment/third-party-methods/{method_id}/status": { @@ -4518,6 +4555,41 @@ "x-permissions": ["user:update"] } }, + "/users/{id}/money-scopes": { + "get": { + "operationId": "listUserMoneyScopes", + "x-permission": "user:view", + "parameters": [ + { + "$ref": "#/components/parameters/Id" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/EmptyResponse" + } + }, + "x-permissions": ["user:view"] + }, + "put": { + "operationId": "replaceUserMoneyScopes", + "x-permission": "user:update", + "parameters": [ + { + "$ref": "#/components/parameters/Id" + } + ], + "requestBody": { + "$ref": "#/components/requestBodies/MoneyScopeRequest" + }, + "responses": { + "200": { + "$ref": "#/components/responses/EmptyResponse" + } + }, + "x-permissions": ["user:update"] + } + }, "/users/{id}/reset-password": { "post": { "operationId": "resetUserPassword", @@ -4822,6 +4894,24 @@ } } }, + "MoneyScopeRequest": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["scopes"], + "properties": { + "scopes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserMoneyScope" + } + } + } + } + } + } + }, "MenuRequest": { "content": { "application/json": { @@ -4924,6 +5014,39 @@ } } }, + "TemporaryPaymentLinkRequest": { + "content": { + "application/json": { + "schema": { + "type": "object", + "required": ["appCode", "regionId", "usdMinorAmount", "providerCode", "paymentMethodId"], + "properties": { + "appCode": { + "type": "string" + }, + "language": { + "type": "string" + }, + "paymentMethodId": { + "type": "integer" + }, + "providerCode": { + "type": "string" + }, + "regionId": { + "type": "integer" + }, + "returnUrl": { + "type": "string" + }, + "usdMinorAmount": { + "type": "integer" + } + } + } + } + } + }, "UserRequest": { "content": { "application/json": { @@ -5971,6 +6094,18 @@ "type": "object", "required": ["name"], "additionalProperties": true + }, + "UserMoneyScope": { + "type": "object", + "required": ["appCode", "regionId"], + "properties": { + "appCode": { + "type": "string" + }, + "regionId": { + "type": "integer" + } + } } } } diff --git a/money/src/MoneyApp.jsx b/money/src/MoneyApp.jsx index 73e9e5c..ca3138b 100644 --- a/money/src/MoneyApp.jsx +++ b/money/src/MoneyApp.jsx @@ -8,26 +8,32 @@ import { OperatorPerformancePanel } from "./components/OperatorPerformancePanel. import { PaymentLinkPanel } from "./components/PaymentLinkPanel.jsx"; import { PerformanceTable } from "./components/PerformanceTable.jsx"; import { - createPaymentLinkRecord, filterMoneyModules, - initialPaymentLinks, moneyAppOptions, moneyCountries, moneyOperators, - moneyScopeOptions, summarizeMoneyModules } from "./data.js"; +import { + appOptionsFromMasterData, + countryOptionsFromMasterData, + fetchMoneyMasterData, + regionOptionsFromMasterData +} from "./masterDataApi.js"; + +const emptyMasterData = { apps: [], countries: [], error: "", loading: false, modules: [], performanceSummary: {}, regions: [], scopes: [] }; export function MoneyApp() { const [sessionState, setSessionState] = useState({ error: "", loading: true, session: null }); + const [masterDataState, setMasterDataState] = useState(emptyMasterData); const [activeView, setActiveView] = useState("overview"); const [mode, setMode] = useState("finance"); const [activeOperatorId, setActiveOperatorId] = useState("sarah-ali"); const [appCode, setAppCode] = useState(""); const [countryCode, setCountryCode] = useState(""); - const [scope, setScope] = useState(""); + const [regionId, setRegionId] = useState(""); const [operatorKeyword, setOperatorKeyword] = useState(""); - const [links, setLinks] = useState(() => initialPaymentLinks); + const [links, setLinks] = useState([]); const [toast, setToast] = useState(""); useEffect(() => { @@ -48,6 +54,53 @@ export function MoneyApp() { }; }, []); + useEffect(() => { + if (!sessionState.session?.canViewMoney) { + return undefined; + } + let mounted = true; + setMasterDataState((current) => ({ ...current, error: "", loading: true })); + fetchMoneyMasterData() + .then((data) => { + if (mounted) { + setMasterDataState({ ...data, loading: false }); + } + }) + .catch((err) => { + if (mounted) { + setMasterDataState({ ...emptyMasterData, error: err.message || "主数据加载失败", loading: false }); + } + }); + return () => { + mounted = false; + }; + }, [sessionState.session?.canViewMoney]); + + const appOptions = useMemo(() => appOptionsFromMasterData(masterDataState.apps, moneyAppOptions), [masterDataState.apps]); + const countryOptions = useMemo( + () => countryOptionsFromMasterData(masterDataState.countries, moneyCountries), + [masterDataState.countries] + ); + const regionOptions = useMemo(() => regionOptionsFromMasterData(masterDataState.regions), [masterDataState.regions]); + + useEffect(() => { + if (appCode && !hasOption(appOptions, appCode)) { + setAppCode(""); + } + }, [appCode, appOptions]); + + useEffect(() => { + if (countryCode && !hasOption(countryOptions, countryCode)) { + setCountryCode(""); + } + }, [countryCode, countryOptions]); + + useEffect(() => { + if (regionId && !hasOption(regionOptions, regionId)) { + setRegionId(""); + } + }, [regionId, regionOptions]); + const filteredModules = useMemo( () => filterMoneyModules({ @@ -55,21 +108,24 @@ export function MoneyApp() { appCode, countryCode, mode, + modules: masterDataState.modules, operatorKeyword: mode === "finance" ? operatorKeyword : "", - scope + regionId, + regions: masterDataState.regions }), - [activeOperatorId, appCode, countryCode, mode, operatorKeyword, scope] + [activeOperatorId, appCode, countryCode, masterDataState.modules, masterDataState.regions, mode, operatorKeyword, regionId] ); const summary = useMemo(() => summarizeMoneyModules(filteredModules), [filteredModules]); const visibleModuleIds = useMemo(() => new Set(filteredModules.map((module) => module.id)), [filteredModules]); const visibleLinks = useMemo(() => links.filter((link) => visibleModuleIds.has(link.moduleId)), [links, visibleModuleIds]); - const activeOperator = moneyOperators.find((operator) => operator.id === activeOperatorId) || moneyOperators[0]; + const operators = useMemo(() => operatorsFromModules(masterDataState.modules), [masterDataState.modules]); + const activeOperator = operators.find((operator) => operator.id === activeOperatorId) || operators[0] || moneyOperators[0]; const view = MONEY_VIEWS.find((item) => item.id === activeView) || MONEY_VIEWS[0]; const resetFilters = () => { setAppCode(""); setCountryCode(""); - setScope(""); + setRegionId(""); setOperatorKeyword(""); }; @@ -78,20 +134,16 @@ export function MoneyApp() { window.setTimeout(() => setToast(""), 1600); }; - const createLink = (payload) => { - const nextLink = createPaymentLinkRecord({ - ...payload, - operatorName: mode === "operator" ? activeOperator.label : undefined - }); - setLinks((current) => [nextLink, ...current]); - showToast("支付链接已创建"); - }; - const copyLink = async (value) => { await copyText(value); showToast("链接已复制"); }; + const addPaymentLink = (link) => { + setLinks((current) => [link, ...current.filter((item) => (item.orderId || item.id) !== (link.orderId || link.id))]); + showToast("支付链接已创建"); + }; + const exportReport = () => { downloadTextFile(createCsv(filteredModules), `hyapp-money-${Date.now()}.csv`); showToast("财务报表已导出"); @@ -124,33 +176,45 @@ export function MoneyApp() { [country.code, country.label])]} + countryOptions={countryOptions} + masterDataError={masterDataState.error} + masterDataLoading={masterDataState.loading} mode={mode} onActiveOperatorChange={setActiveOperatorId} onAppChange={setAppCode} onCountryChange={setCountryCode} onExport={exportReport} onOperatorKeywordChange={setOperatorKeyword} + onRegionChange={setRegionId} onReset={resetFilters} - onScopeChange={setScope} operatorKeyword={operatorKeyword} - operators={moneyOperators} - scope={scope} - scopeOptions={moneyScopeOptions} + operators={operators} + regionId={regionId} + regionOptions={regionOptions} view={view} /> -
{renderContent(activeView, { copyLink, createLink, filteredModules, summary, visibleLinks })}
+
+ {renderContent(activeView, { + copyLink, + countries: masterDataState.countries, + filteredModules, + onPaymentLinkCreated: addPaymentLink, + regions: masterDataState.regions, + summary, + visibleLinks + })} +
{toast ?
{toast}
: null} ); } -function renderContent(activeView, { copyLink, createLink, filteredModules, summary, visibleLinks }) { +function renderContent(activeView, { copyLink, countries, filteredModules, onPaymentLinkCreated, regions, summary, visibleLinks }) { if (activeView === "modules") { - return ; + return ; } if (activeView === "operators") { @@ -158,16 +222,20 @@ function renderContent(activeView, { copyLink, createLink, filteredModules, summ } if (activeView === "payments") { - return ; + return ; } if (activeView === "countries") { - return ; + return ; } return ; } +function hasOption(options, value) { + return options.some(([optionValue]) => String(optionValue) === String(value)); +} + function StateScreen({ detail = "", title }) { return (
@@ -180,7 +248,7 @@ function StateScreen({ detail = "", title }) { } function createCsv(modules) { - const header = ["模块", "负责人", "国家", "充值USD", "流水USD", "存量工资USD", "新增", "日活", "当日目标USD", "当月目标USD"]; + const header = ["区域", "负责人", "国家", "充值USD", "流水USD", "存量工资USD", "新增", "日活", "当日目标USD", "当月目标USD"]; const rows = modules.map((module) => [ module.moduleName, module.operatorName, @@ -196,6 +264,23 @@ function createCsv(modules) { return [header, ...rows].map((row) => row.map(csvCell).join(",")).join("\n"); } +function operatorsFromModules(modules) { + const seen = new Set(); + return modules + .map((module) => ({ + department: module.department || "", + id: module.operatorId, + label: module.operatorName || module.operatorId + })) + .filter((operator) => { + if (!operator.id || seen.has(operator.id)) { + return false; + } + seen.add(operator.id); + return true; + }); +} + function csvCell(value) { const text = String(value ?? ""); return /[",\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text; diff --git a/money/src/api.js b/money/src/api.js index 1bb9926..c9bd23b 100644 --- a/money/src/api.js +++ b/money/src/api.js @@ -1,36 +1,73 @@ const API_BASE_URL = import.meta.env?.VITE_API_BASE_URL || "/api"; const TOKEN_KEY = "hyapp-admin.access-token"; +const APP_CODE_KEY = "hyapp-admin.app-code"; +const APP_CODE_HEADER = "X-App-Code"; const MONEY_PERMISSION = "money:view"; +const DEFAULT_APP_CODE = "lalu"; export async function fetchMoneySession() { - const response = await fetch(`${API_BASE_URL}/v1/auth/me`, { - credentials: "include", - headers: requestHeaders() - }); - const payload = await readJSON(response); - if (response.status === 401 || Number(payload?.code) === 40100) { - redirectToLogin(); - throw new Error("登录已失效"); - } - if (!response.ok || payload.code !== 0) { - throw new Error(payload.message || response.statusText || "会话校验失败"); - } - const session = payload.data || {}; + const session = await adminApiGet("/v1/auth/me"); return { ...session, canViewMoney: Array.isArray(session.permissions) && session.permissions.includes(MONEY_PERMISSION) }; } -function requestHeaders() { - const headers = {}; +export function adminApiGet(path, options = {}) { + return adminApiRequest(path, { ...options, method: "GET" }); +} + +export async function adminApiRequest(path, options = {}) { + const response = await fetch(adminApiUrl(path, options.query), { + body: requestBody(options.body), + credentials: "include", + headers: requestHeaders(options), + method: options.method || (options.body === undefined ? "GET" : "POST") + }); + const payload = await readJSON(response); + if (response.status === 401 || Number(payload?.code) === 40100) { + redirectToLogin(); + throw new Error("登录已失效"); + } + if (!response.ok || isApiFailure(payload)) { + throw new Error(payload.message || response.statusText || "会话校验失败"); + } + return Object.prototype.hasOwnProperty.call(payload, "data") ? payload.data : payload; +} + +function requestHeaders(options = {}) { + const headers = { ...(options.headers || {}) }; const token = window.localStorage.getItem(TOKEN_KEY); + const appCode = window.localStorage.getItem(APP_CODE_KEY) || DEFAULT_APP_CODE; if (token) { headers.Authorization = `Bearer ${token}`; } + if (appCode && !headers[APP_CODE_HEADER]) { + headers[APP_CODE_HEADER] = appCode; + } + if (options.body !== undefined && !(options.body instanceof FormData) && !headers["Content-Type"]) { + headers["Content-Type"] = "application/json"; + } return headers; } +function requestBody(body) { + if (body === undefined) { + return undefined; + } + return body instanceof FormData ? body : JSON.stringify(body); +} + +function adminApiUrl(path, query) { + const url = new URL(`${API_BASE_URL}${path}`, window.location.origin); + Object.entries(query || {}).forEach(([key, value]) => { + if (value !== undefined && value !== null && value !== "") { + url.searchParams.set(key, String(value)); + } + }); + return url.toString(); +} + async function readJSON(response) { const text = await response.text(); if (!text) { @@ -43,6 +80,17 @@ async function readJSON(response) { } } +function isApiFailure(payload) { + const code = payload?.code; + const errorCode = payload?.errorCode; + return ( + (typeof code === "number" && code !== 0) || + (typeof code === "string" && code !== "" && code !== "0" && code !== "OK") || + (typeof errorCode === "number" && errorCode !== 0) || + (typeof errorCode === "string" && errorCode !== "" && errorCode !== "0" && errorCode !== "OK") + ); +} + function redirectToLogin() { window.localStorage.removeItem(TOKEN_KEY); if (window.location.pathname !== "/login") { diff --git a/money/src/components/CountryChannelPanel.jsx b/money/src/components/CountryChannelPanel.jsx index cdecd6d..1e2e0dd 100644 --- a/money/src/components/CountryChannelPanel.jsx +++ b/money/src/components/CountryChannelPanel.jsx @@ -1,8 +1,8 @@ import { availableProvidersForCountry, moneyCountries, summarizeMoneyModules } from "../data.js"; import { formatNumber, formatPercent, formatUsd } from "../format.js"; -export function CountryChannelPanel({ links, modules }) { - const rows = moneyCountries +export function CountryChannelPanel({ countries = [], links, modules, regions = [] }) { + const rows = countryRows(countries, modules, links, regions) .map((country) => { const countryModules = modules.filter((module) => module.countryCode === country.code); const countryLinks = links.filter((link) => link.countryCode === country.code); @@ -33,7 +33,7 @@ export function CountryChannelPanel({ links, modules }) {
- +
{country.providers.map((provider) => ( @@ -50,6 +50,40 @@ export function CountryChannelPanel({ links, modules }) { ); } +function countryRows(countries, modules, links, regions) { + const fallbackCountries = new Map(moneyCountries.map((country) => [country.code, country])); + const realCountries = new Map(countries.map((country) => [country.countryCode, country])); + const codes = new Set([ + ...moneyCountries.map((country) => country.code), + ...modules.map((module) => module.countryCode), + ...links.map((link) => link.countryCode) + ]); + + return [...codes] + .filter((code) => code && code !== "ALL") + .map((code) => { + const fallback = fallbackCountries.get(code) || {}; + const real = realCountries.get(code) || {}; + return { + code, + currency: fallback.currency || real.currencyCode || "-", + label: real.countryDisplayName || real.countryName || fallback.label || code, + region: regionNameForCountry(code, regions) || fallback.region || "-" + }; + }); +} + +function regionNameForCountry(countryCode, regions) { + const normalizedCountryCode = String(countryCode || "").toUpperCase(); + const region = regions.find((item) => + (item.countries || []).some((code) => String(code || "").toUpperCase() === normalizedCountryCode) + ); + if (!region) { + return ""; + } + return [region.name, region.regionCode].filter(Boolean).join(" · "); +} + function Metric({ label, tone, value }) { return (
diff --git a/money/src/components/MoneyHeader.jsx b/money/src/components/MoneyHeader.jsx index e38859c..b00c3ef 100644 --- a/money/src/components/MoneyHeader.jsx +++ b/money/src/components/MoneyHeader.jsx @@ -6,18 +6,20 @@ export function MoneyHeader({ appOptions, countryCode, countryOptions, + masterDataError, + masterDataLoading, mode, onActiveOperatorChange, onAppChange, onCountryChange, onExport, onOperatorKeywordChange, + onRegionChange, onReset, - onScopeChange, operatorKeyword, operators, - scope, - scopeOptions, + regionId, + regionOptions, view }) { return ( @@ -27,9 +29,21 @@ export function MoneyHeader({
- - - + + + {mode === "finance" ? (
+
+
+ 支付方式 + {methodsForCountry.length} +
+
+ {methodsForCountry.length ? ( + methodsForCountry.map((method) => ( + onUpdate("methodId")(String(method.method_id))} + /> + )) + ) : ( +
{methodsState.loading ? "加载中" : methodsState.error || "当前无数据"}
+ )} +
+
+
+ {createState.error ? {createState.error} : } + +
+ + +
+ ); +} + function Select({ label, onChange, options, value }) { return ( ); } +function MethodButton({ active, method, onClick }) { + return ( + + ); +} + +function normalizeLinks(data, modules) { + const items = Array.isArray(data?.items) ? data.items : Array.isArray(data) ? data : []; + return items.map((item) => normalizeAdminLink(item, modules)).filter(Boolean); +} + +function normalizeAdminLink(item, modules = []) { + const order = item.order || item; + const id = stringValue(order.orderId ?? order.order_id ?? order.id); + if (!id) { + return null; + } + const appCode = stringValue(order.appCode ?? order.app_code); + const regionId = numberValue(order.regionId ?? order.region_id); + const ownerUserId = stringValue(order.ownerUserId ?? order.owner_user_id); + const module = moduleForLink(modules, appCode, regionId, ownerUserId); + const usdMinorAmount = order.usdMinorAmount ?? order.usd_minor_amount; + return { + amountUsd: usdMinorAmount === 0 || usdMinorAmount ? Number(usdMinorAmount) / 100 : Number(order.amountUsd ?? order.amount_usd ?? 0), + appCode, + countryCode: stringValue(order.countryCode ?? order.country_code), + countryName: stringValue(order.countryName ?? order.country_name ?? order.countryCode ?? order.country_code) || "-", + createdAtMs: order.createdAtMs ?? order.created_at_ms ?? order.createdAt ?? order.created_at, + id, + moduleId: module?.id || scopeKey(appCode, regionId), + moduleName: module?.moduleName || [appCode, regionId ? `区域 ${regionId}` : ""].filter(Boolean).join(" / ") || "Temporary Pay", + ownerUserId, + payUrl: stringValue(item.paymentLink ?? item.payment_link ?? order.payUrl ?? order.pay_url), + providerName: stringValue(order.providerName ?? order.provider_name ?? order.providerCode ?? order.provider_code) || "-", + region: module?.region || (regionId ? String(regionId) : ""), + regionId, + status: stringValue(order.status) + }; +} + +function normalizeLegacyLink(link, modules) { + if (!link) { + return null; + } + const module = moduleForLink(modules, link.appCode, link.regionId, link.ownerUserId) || modules.find((item) => item.id === link.moduleId); + return { + amountUsd: Number(link.amountUsd || 0), + appCode: link.appCode || module?.appCode || "", + countryCode: link.countryCode, + countryName: link.countryName || link.countryCode || "-", + createdAtMs: link.createdAtMs, + id: link.id, + moduleId: link.moduleId || module?.id || "", + moduleName: link.moduleName || module?.moduleName || "-", + ownerUserId: link.ownerUserId, + payUrl: link.payUrl || "", + providerName: link.providerName || "-", + region: link.region || module?.region || "", + regionId: link.regionId || module?.regionId || 0, + status: link.status || "" + }; +} + +function normalizeCreatedLink(data, { method, module }) { + return normalizeAdminLink(data, [module]) || { + amountUsd: dollarsToMinor("0") / 100, + appCode: module.appCode, + countryCode: temporaryCountryCode(method), + countryName: method.country_name || temporaryCountryCode(method), + createdAtMs: Date.now(), + id: `${module.appCode}:${module.regionId}:${Date.now()}`, + moduleId: module.id, + moduleName: module.moduleName, + payUrl: "", + providerName: stringValue(method.provider_name ?? method.provider_code) || "-", + region: module.region, + regionId: module.regionId, + status: "redirected" + }; +} + +function regionsForCountry(modules, appCode, countryCode) { + const normalizedAppCode = stringValue(appCode); + const normalizedCountryCode = stringValue(countryCode).toUpperCase(); + const byScope = new Map(); + modules.forEach((module) => { + if (module.appCode !== normalizedAppCode || Number(module.regionId) <= 0 || !moduleCoversCountry(module, normalizedCountryCode)) { + return; + } + const key = scopeKey(module.appCode, module.regionId); + if (!byScope.has(key)) { + byScope.set(key, { + label: `${module.moduleName} · ${module.region}`, + module, + value: key + }); + } + }); + return [...byScope.values()].sort((a, b) => a.label.localeCompare(b.label, "zh-Hans-CN")); +} + +function moduleCoversCountry(module, countryCode) { + if (!countryCode) { + return true; + } + const codes = Array.isArray(module.countryCodes) ? module.countryCodes : []; + return module.countryCode === "ALL" || module.countryCode === countryCode || codes.includes(countryCode); +} + +function moduleForLink(modules, appCode, regionId, ownerUserId) { + const normalizedOwner = stringValue(ownerUserId); + return ( + modules.find( + (module) => + module.appCode === appCode && + Number(module.regionId) === Number(regionId) && + normalizedOwner && + String(module.operatorId) === normalizedOwner + ) || + modules.find((module) => module.appCode === appCode && Number(module.regionId) === Number(regionId)) || + null + ); +} + +function appOptionsFromModules(modules) { + const byCode = new Map(); + modules.forEach((module) => { + const appCode = stringValue(module.appCode); + if (appCode && !byCode.has(appCode)) { + byCode.set(appCode, module.appName || appCode); + } + }); + return [...byCode.entries()].sort((a, b) => String(a[1]).localeCompare(String(b[1]), "zh-Hans-CN")); +} + +function mergeLinks(items) { + const byId = new Map(); + items.filter(Boolean).forEach((item) => { + if (!item.id || byId.has(item.id)) { + return; + } + byId.set(item.id, item); + }); + return [...byId.values()].sort((a, b) => Number(b.createdAtMs || 0) - Number(a.createdAtMs || 0)); +} + +function paymentStatusLabel(status) { + if (status === "paid") { + return "已支付"; + } + if (status === "redirected") { + return "已生成"; + } + if (status === "pending") { + return "待支付"; + } + if (status === "failed") { + return "失败"; + } + if (status === "credited") { + return "已入账"; + } + return status || "-"; +} + +function scopeKey(appCode, regionId) { + return `${appCode}:${Number(regionId || 0)}`; +} + +function numberValue(value) { + const number = Number(value); + return Number.isFinite(number) ? number : 0; +} + +function stringValue(value) { + return String(value ?? "").trim(); +} + function openLink(value) { if (value) { window.open(value, "_blank", "noopener,noreferrer"); diff --git a/money/src/components/PerformanceTable.jsx b/money/src/components/PerformanceTable.jsx index 5bef087..3983fec 100644 --- a/money/src/components/PerformanceTable.jsx +++ b/money/src/components/PerformanceTable.jsx @@ -1,13 +1,13 @@ import { formatNumber, formatPercent, formatUsd } from "../format.js"; -export function PerformanceTable({ meta = "", modules, summary, title = "运营模块绩效" }) { +export function PerformanceTable({ meta = "", modules, summary, title = "区域绩效" }) { const rows = [createTotalRow(summary), ...modules]; return (

{title}

- {meta || `${modules.length} modules`} + {meta || `${modules.length} 个区域`}
{modules.length}
@@ -15,9 +15,9 @@ export function PerformanceTable({ meta = "", modules, summary, title = "运营 - + - + @@ -83,7 +83,7 @@ function Stack({ primary, secondary }) { } function Scope({ scope }) { - const label = scope === "app" ? "App" : scope === "region" ? "地区" : "汇总"; + const label = scope === "app" ? "全站" : scope === "region" ? "区域" : "汇总"; return {label}; } diff --git a/money/src/data.js b/money/src/data.js index 1d40b57..4e234c1 100644 --- a/money/src/data.js +++ b/money/src/data.js @@ -6,10 +6,10 @@ export { initialPaymentLinks, moneyAppOptions, moneyCountries, + moneyModuleMatchesRegion, moneyModules, moneyOperators, moneyProviderOptions, - moneyScopeOptions, paymentStatusLabel, summarizeMoneyModules, trendLabels diff --git a/money/src/masterDataApi.js b/money/src/masterDataApi.js new file mode 100644 index 0000000..ca0ad17 --- /dev/null +++ b/money/src/masterDataApi.js @@ -0,0 +1,306 @@ +import { API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints"; +import { adminApiGet } from "./api.js"; + +export async function fetchMoneyMasterData() { + const [scopeResult, performanceResult] = await Promise.allSettled([fetchMoneyScope(), fetchMoneyPerformance()]); + const errors = [scopeResult, performanceResult] + .filter((result) => result.status === "rejected") + .map((result) => result.reason?.message || "主数据加载失败"); + const scope = scopeResult.status === "fulfilled" ? scopeResult.value : emptyScope(); + const performance = performanceResult.status === "fulfilled" ? performanceResult.value : { items: [], summary: {} }; + const modules = buildMoneyModules(scope, performance.items || []); + + return { + apps: scope.apps, + countries: scope.countries, + error: errors.join(";"), + modules, + performanceSummary: performance.summary || {}, + regions: scope.regions, + scopes: scope.scopes + }; +} + +export async function fetchMoneyScope() { + const data = await adminApiGet(apiEndpointPath(API_OPERATIONS.getMoneyScope)); + return { + all: Boolean(data?.all), + apps: normalizeAdminApps(data?.apps || []), + countries: normalizeCountries(data?.countries || []), + regions: normalizeRegions(data?.regions || []), + scopes: normalizeScopes(data?.scopes || []) + }; +} + +export async function fetchMoneyPerformance(query = {}) { + const data = await adminApiGet(apiEndpointPath(API_OPERATIONS.getMoneyPerformance), { query }); + return { + items: Array.isArray(data?.items) ? data.items : [], + summary: data?.summary || {} + }; +} + +export async function listMoneyApps() { + return normalizeAdminApps(await adminApiGet(apiEndpointPath(API_OPERATIONS.listApps))); +} + +export async function listMoneyCountries(query = {}) { + return normalizeCountries(await adminApiGet(apiEndpointPath(API_OPERATIONS.listCountries), { query })); +} + +export async function listMoneyRegions(query = {}) { + return normalizeRegions(await adminApiGet(apiEndpointPath(API_OPERATIONS.listRegions), { query })); +} + +export function normalizeAdminApps(data) { + return listItems(data) + .map((item) => { + const appCode = stringValue(item.appCode ?? item.app_code ?? item.code); + if (!appCode) { + return null; + } + return { + appCode, + appId: item.appId ?? item.app_id ?? item.id, + appName: stringValue(item.appName ?? item.app_name ?? item.name) || appCode, + packageName: stringValue(item.packageName ?? item.package_name), + platform: stringValue(item.platform), + status: item.status + }; + }) + .filter(Boolean); +} + +export function normalizeCountries(data) { + return listItems(data) + .map((item) => { + const countryCode = stringValue(item.countryCode ?? item.country_code ?? item.code).toUpperCase(); + if (!countryCode) { + return null; + } + return { + countryCode, + countryDisplayName: stringValue(item.countryDisplayName ?? item.country_display_name ?? item.displayName ?? item.display_name), + countryId: item.countryId ?? item.country_id ?? item.id, + countryName: stringValue(item.countryName ?? item.country_name ?? item.name), + enabled: item.enabled, + flag: stringValue(item.flag), + appCode: stringValue(item.appCode ?? item.app_code), + isoAlpha3: stringValue(item.isoAlpha3 ?? item.iso_alpha3), + isoNumeric: stringValue(item.isoNumeric ?? item.iso_numeric), + phoneCountryCode: stringValue(item.phoneCountryCode ?? item.phone_country_code), + regionId: numberValue(item.regionId ?? item.region_id), + sortOrder: numberValue(item.sortOrder ?? item.sort_order) + }; + }) + .filter(Boolean) + .sort((a, b) => a.sortOrder - b.sortOrder || countryLabel(a).localeCompare(countryLabel(b), "zh-Hans-CN")); +} + +export function normalizeRegions(data) { + return listItems(data) + .map((item) => { + const regionId = item.regionId ?? item.region_id ?? item.id; + const regionCode = stringValue(item.regionCode ?? item.region_code ?? item.code).toUpperCase(); + if (!(regionId === 0 || regionId) || regionCode === "GLOBAL") { + return null; + } + return { + appCode: stringValue(item.appCode ?? item.app_code), + countries: normalizeCountryCodes(item.countries ?? item.countryCodes ?? item.country_codes), + name: stringValue(item.name ?? item.regionName ?? item.region_name) || regionCode || `区域 ${regionId}`, + regionCode, + regionId, + sortOrder: numberValue(item.sortOrder ?? item.sort_order), + status: item.status + }; + }) + .filter(Boolean) + .sort((a, b) => a.sortOrder - b.sortOrder || String(a.name).localeCompare(String(b.name), "zh-Hans-CN")); +} + +export function appOptionsFromMasterData(apps, fallbackOptions) { + const options = uniqueOptions(apps.map((app) => [app.appCode, app.appName || app.appCode])); + return options.length ? [["", "全部 App"], ...options] : fallbackOptions; +} + +export function countryOptionsFromMasterData(countries, fallbackCountries) { + const options = uniqueOptions(countries.map((country) => [country.countryCode, countryLabel(country)])); + return options.length ? [["", "全部国家"], ...options] : [["", "全部国家"], ...fallbackCountries.map((country) => [country.code, country.label])]; +} + +export function regionOptionsFromMasterData(regions) { + return [ + ["", "全部区域"], + ...uniqueOptions( + regions.map((region) => [ + String(region.regionId), + [region.name, region.regionCode, region.regionId].filter(Boolean).join(" · ") + ]) + ) + ]; +} + +export function countryLabel(country) { + return [country.flag, country.countryDisplayName || country.countryName, country.countryCode].filter(Boolean).join(" · "); +} + +export function buildMoneyModules(scope, performanceItems = []) { + const apps = scope?.apps || []; + const regions = scope?.regions || []; + const countries = scope?.countries || []; + const performanceByRegion = new Map(); + performanceItems.forEach((item) => { + const key = `${stringValue(item.appCode ?? item.app_code)}:${Number(item.regionId ?? item.region_id ?? 0)}:${Number(item.operatorUserId ?? item.operator_user_id ?? 0)}`; + performanceByRegion.set(key, item); + }); + + const modules = []; + performanceByRegion.forEach((item) => { + modules.push(moduleFromPerformance(item, apps, regions, countries)); + }); + + scope.scopes + ?.filter((scopeItem) => Number(scopeItem.regionId) >= 0) + .forEach((scopeItem) => { + if (Number(scopeItem.regionId) === 0) { + const appRegions = regions.filter((region) => region.appCode === scopeItem.appCode); + if (appRegions.length) { + appRegions.forEach((region) => { + const hasRegionModule = modules.some( + (module) => module.appCode === scopeItem.appCode && Number(module.regionId) === Number(region.regionId) + ); + if (!hasRegionModule) { + modules.push(emptyModuleFromScope({ appCode: scopeItem.appCode, regionId: region.regionId }, apps, regions, countries)); + } + }); + return; + } + } + const hasModule = modules.some( + (module) => module.appCode === scopeItem.appCode && Number(module.regionId) === Number(scopeItem.regionId) + ); + if (!hasModule) { + modules.push(emptyModuleFromScope(scopeItem, apps, regions, countries)); + } + }); + + if (!modules.length && scope.all) { + regions.forEach((region) => modules.push(emptyModuleFromScope({ appCode: region.appCode, regionId: region.regionId }, apps, regions, countries))); + } + + return modules.sort((a, b) => b.rechargeUsd - a.rechargeUsd || a.moduleName.localeCompare(b.moduleName, "zh-Hans-CN")); +} + +function moduleFromPerformance(item, apps, regions, countries) { + const appCode = stringValue(item.appCode ?? item.app_code); + const regionId = Number(item.regionId ?? item.region_id ?? 0); + const app = apps.find((nextApp) => nextApp.appCode === appCode) || {}; + const region = regions.find((nextRegion) => nextRegion.appCode === appCode && Number(nextRegion.regionId) === regionId) || {}; + const regionCountries = countries.filter((country) => country.appCode === appCode && Number(country.regionId) === regionId); + const paidUsd = Number(item.paidUsdMinor ?? item.paid_usd_minor ?? 0) / 100; + const paidLinkCount = Number(item.paidLinkCount ?? item.paid_link_count ?? 0); + const operatorId = String(item.operatorUserId ?? item.operator_user_id ?? "0"); + const operatorName = stringValue(item.operatorName ?? item.operator_name ?? item.operatorAccount ?? item.operator_account) || "未归属"; + return { + appCode, + appName: app.appName || appCode, + coinIssued: 0, + countryCode: regionCountries[0]?.countryCode || "ALL", + countryCodes: regionCountries.map((country) => country.countryCode), + countryName: regionCountries.length ? regionCountries.map(countryLabel).join(" / ") : "全部国家", + dau: 0, + dayTargetUsd: 0, + department: stringValue(item.operatorAccount ?? item.operator_account), + id: `${appCode}:${regionId}:${operatorId}`, + linkCount: paidLinkCount, + moduleName: `${app.appName || appCode} / ${region.name || (regionId === 0 ? "全部区域" : `区域 ${regionId}`)}`, + monthActualUsd: paidUsd, + monthTargetUsd: 0, + newUsers: 0, + operatorId, + operatorName, + paidLinkCount, + paidUsers: paidLinkCount, + rechargeTrend: [0, 0, 0, 0, 0, 0, paidUsd], + rechargeUsd: paidUsd, + region: [region.name, region.regionCode].filter(Boolean).join(" · ") || (regionId === 0 ? "全部区域" : String(regionId)), + regionId, + retention1: 0, + retention7: 0, + retention30: 0, + revenueTrend: [0, 0, 0, 0, 0, 0, paidUsd], + revenueUsd: paidUsd, + salaryUsd: 0, + scope: regionId === 0 ? "app" : "region" + }; +} + +function emptyModuleFromScope(scopeItem, apps, regions, countries) { + return moduleFromPerformance( + { + appCode: scopeItem.appCode, + operatorName: "-", + paidLinkCount: 0, + paidUsdMinor: 0, + regionId: scopeItem.regionId + }, + apps, + regions, + countries + ); +} + +function normalizeScopes(scopes) { + return (Array.isArray(scopes) ? scopes : []) + .map((scope) => ({ + appCode: stringValue(scope.appCode ?? scope.app_code), + regionId: numberValue(scope.regionId ?? scope.region_id) + })) + .filter((scope) => scope.appCode && scope.regionId >= 0); +} + +function emptyScope() { + return { all: false, apps: [], countries: [], regions: [], scopes: [] }; +} + +function listItems(data) { + if (Array.isArray(data)) { + return data; + } + if (Array.isArray(data?.items)) { + return data.items; + } + if (Array.isArray(data?.list)) { + return data.list; + } + return []; +} + +function normalizeCountryCodes(value) { + if (!Array.isArray(value)) { + return []; + } + return [...new Set(value.map((item) => stringValue(item).toUpperCase()).filter(Boolean))]; +} + +function uniqueOptions(options) { + const seen = new Set(); + return options.filter(([value]) => { + const key = String(value || ""); + if (!key || seen.has(key)) { + return false; + } + seen.add(key); + return true; + }); +} + +function stringValue(value) { + return String(value ?? "").trim(); +} + +function numberValue(value) { + const nextValue = Number(value); + return Number.isFinite(nextValue) ? nextValue : 0; +} diff --git a/money/src/masterDataApi.test.js b/money/src/masterDataApi.test.js new file mode 100644 index 0000000..791f190 --- /dev/null +++ b/money/src/masterDataApi.test.js @@ -0,0 +1,112 @@ +import { afterEach, expect, test, vi } from "vitest"; +import { + countryOptionsFromMasterData, + fetchMoneyMasterData, + normalizeAdminApps, + normalizeCountries, + normalizeRegions, + regionOptionsFromMasterData +} from "./masterDataApi.js"; + +afterEach(() => { + window.localStorage.clear(); + vi.unstubAllGlobals(); +}); + +test("normalizes app country and region master data for money filters", () => { + expect(normalizeAdminApps({ items: [{ app_code: "lalu", name: "Lalu" }] })).toEqual([ + { appCode: "lalu", appId: undefined, appName: "Lalu", packageName: "", platform: "", status: undefined } + ]); + expect(normalizeCountries({ items: [{ country_code: "sa", country_display_name: "沙特", sort_order: 2 }] })).toEqual([ + { + appCode: "", + countryCode: "SA", + countryDisplayName: "沙特", + countryId: undefined, + countryName: "", + enabled: undefined, + flag: "", + isoAlpha3: "", + isoNumeric: "", + phoneCountryCode: "", + regionId: 0, + sortOrder: 2 + } + ]); + expect(normalizeRegions({ items: [{ countries: ["sa", "AE"], name: "中东", region_code: "me", region_id: 7 }] })).toEqual([ + { + appCode: "", + countries: ["SA", "AE"], + name: "中东", + regionCode: "ME", + regionId: 7, + sortOrder: 0, + status: undefined + } + ]); +}); + +test("builds select options from real money master data", () => { + const countries = normalizeCountries({ items: [{ countryCode: "BR", countryDisplayName: "巴西" }] }); + const regions = normalizeRegions({ items: [{ countries: ["BR"], name: "拉美", regionCode: "LATAM", regionId: 3 }] }); + + expect(countryOptionsFromMasterData(countries, [])).toEqual([ + ["", "全部国家"], + ["BR", "巴西 · BR"] + ]); + expect(regionOptionsFromMasterData(regions)).toEqual([ + ["", "全部区域"], + ["3", "拉美 · LATAM · 3"] + ]); +}); + +test("fetches money master data from real admin API paths", async () => { + const calls = []; + window.localStorage.setItem("hyapp-admin.access-token", "token-1"); + window.localStorage.setItem("hyapp-admin.app-code", "yumi"); + vi.stubGlobal( + "fetch", + vi.fn(async (input, init) => { + calls.push({ init, url: String(input) }); + const url = String(input); + if (url.includes("/v1/admin/money/scope")) { + return jsonResponse({ + all: false, + apps: [{ appCode: "lalu", appName: "Lalu" }], + countries: [{ appCode: "lalu", countryCode: "SA", countryDisplayName: "沙特", regionId: 2 }], + regions: [{ appCode: "lalu", countries: ["SA"], name: "中东", regionCode: "ME", regionId: 2 }], + scopes: [{ appCode: "lalu", regionId: 2 }] + }); + } + if (url.includes("/v1/admin/money/performance")) { + return jsonResponse({ + items: [{ appCode: "lalu", operatorName: "Admin", operatorUserId: 1, paidLinkCount: 1, paidUsdMinor: 1299, regionId: 2 }], + summary: { paidLinkCount: 1, paidUsdMinor: 1299 } + }); + } + return jsonResponse(null, 404); + }) + ); + + const data = await fetchMoneyMasterData(); + + expect(data.error).toBe(""); + expect(data.apps.map((app) => app.appCode)).toEqual(["lalu"]); + expect(data.countries.map((country) => country.countryCode)).toEqual(["SA"]); + expect(data.regions.map((region) => region.regionId)).toEqual([2]); + expect(data.modules).toHaveLength(1); + expect(data.modules[0].rechargeUsd).toBe(12.99); + expect(calls.map((call) => new URL(call.url).pathname).sort()).toEqual([ + "/api/v1/admin/money/performance", + "/api/v1/admin/money/scope" + ]); + expect(calls[0].init.headers.Authorization).toBe("Bearer token-1"); + expect(calls[0].init.headers["X-App-Code"]).toBe("yumi"); +}); + +function jsonResponse(data, status = 200) { + return new Response(JSON.stringify({ code: status === 200 ? 0 : status, data, message: status === 200 ? "" : "error" }), { + headers: { "content-type": "application/json" }, + status + }); +} diff --git a/money/src/model/data.js b/money/src/model/data.js index 7219b9a..62a78b9 100644 --- a/money/src/model/data.js +++ b/money/src/model/data.js @@ -22,12 +22,6 @@ export const moneyAppOptions = [ ["spark-chat", "Spark Chat"], ]; -export const moneyScopeOptions = [ - ["", "全部模块"], - ["app", "App 模块"], - ["region", "App 地区模块"], -]; - export const moneyProviderOptions = [ { code: "mifapay", label: "MiFaPay", countries: ["AE", "SA", "TR"] }, { code: "v5pay", label: "V5Pay", countries: ["BR", "MX", "ID"] }, @@ -256,25 +250,53 @@ export function filterMoneyModules({ mode = "finance", modules = moneyModules, operatorKeyword = "", - scope = "", + regionId = "", + regions = [], } = {}) { const normalizedKeyword = operatorKeyword.trim().toLowerCase(); return modules.filter((module) => { const matchesRole = mode !== "operator" || module.operatorId === activeOperatorId; const matchesApp = !appCode || module.appCode === appCode; - const matchesScope = !scope || module.scope === scope; const matchesCountry = !countryCode || module.countryCode === countryCode || (module.scope === "app" && module.countryCode === "ALL"); + const matchesRegion = !regionId || moneyModuleMatchesRegion(module, regionId, regions); const matchesOperator = !normalizedKeyword || module.operatorName.toLowerCase().includes(normalizedKeyword) || module.department.toLowerCase().includes(normalizedKeyword); - return matchesRole && matchesApp && matchesScope && matchesCountry && matchesOperator; + return matchesRole && matchesApp && matchesCountry && matchesRegion && matchesOperator; }); } +export function moneyModuleMatchesRegion(module, regionId, regions = []) { + if (module.scope === "app" && module.countryCode === "ALL") { + return true; + } + const normalizedRegionId = String(regionId || ""); + if (!normalizedRegionId) { + return true; + } + if ((module.regionId === 0 || module.regionId) && String(module.regionId) === normalizedRegionId) { + return true; + } + const region = regions.find((item) => String(item.regionId ?? item.value ?? item.id) === normalizedRegionId); + if (!region) { + return false; + } + const countryCodes = new Set( + (region.countries || region.countryCodes || region.country_codes || []) + .map((countryCode) => + String(countryCode || "") + .trim() + .toUpperCase(), + ) + .filter(Boolean), + ); + return countryCodes.has(String(module.countryCode || "").toUpperCase()); +} + export function summarizeMoneyModules(modules = []) { const rechargeUsd = sumBy(modules, "rechargeUsd"); const revenueUsd = sumBy(modules, "revenueUsd"); diff --git a/money/src/model/data.test.js b/money/src/model/data.test.js index c9a2c3a..b3d4baf 100644 --- a/money/src/model/data.test.js +++ b/money/src/model/data.test.js @@ -21,6 +21,16 @@ test("keeps app-level modules visible when filtering by country", () => { expect(modules.map((module) => module.id)).toEqual(["hy-live-app", "social-pro-brazil"]); }); +test("filters region modules from real region country mappings", () => { + const modules = filterMoneyModules({ + mode: "finance", + regionId: "2", + regions: [{ countries: ["SA", "AE"], name: "中东", regionCode: "ME", regionId: 2 }], + }); + + expect(modules.map((module) => module.id)).toEqual(["hy-live-app", "voice-party-ksa", "voice-party-uae"]); +}); + test("summarizes visible modules for KPI cards and progress bars", () => { const summary = summarizeMoneyModules(filterMoneyModules({ activeOperatorId: "leo-wang", mode: "operator" })); diff --git a/money/src/paymentLinksApi.js b/money/src/paymentLinksApi.js new file mode 100644 index 0000000..c0a262c --- /dev/null +++ b/money/src/paymentLinksApi.js @@ -0,0 +1,55 @@ +import { API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints"; +import { adminApiGet, adminApiRequest } from "./api.js"; + +const PAGE_SIZE = 50; + +export function listAdminTemporaryPaymentLinks({ appCode = "", keyword = "", operatorUserId = "", providerCode = "", regionId = "", status = "" } = {}) { + return adminApiGet(apiEndpointPath(API_OPERATIONS.listTemporaryPaymentLinks), { + query: { + app_code: appCode, + keyword, + operator_user_id: operatorUserId, + page: 1, + page_size: PAGE_SIZE, + provider_code: providerCode, + region_id: regionId, + status + } + }); +} + +export function getAdminTemporaryPaymentLink(orderId) { + return adminApiGet(apiEndpointPath(API_OPERATIONS.getTemporaryPaymentLink, { order_id: orderId })); +} + +export function createAdminTemporaryPaymentLink(payload) { + return adminApiRequest(apiEndpointPath(API_OPERATIONS.createTemporaryPaymentLink), { + body: payload, + method: "POST" + }); +} + +export async function listAdminPaymentMethods(appCode) { + const data = await adminApiGet(apiEndpointPath(API_OPERATIONS.listThirdPartyPaymentChannels), { + headers: appCode ? { "X-App-Code": appCode } : undefined + }); + const channels = Array.isArray(data?.items) ? data.items : []; + return channels.flatMap((channel) => + (Array.isArray(channel.methods) ? channel.methods : []).map((method) => ({ + ...method, + app_code: method.appCode ?? method.app_code ?? channel.appCode ?? channel.app_code, + country_code: method.countryCode ?? method.country_code, + country_name: method.countryName ?? method.country_name, + currency_code: method.currencyCode ?? method.currency_code, + logo_url: method.logoUrl ?? method.logo_url, + method_id: method.methodId ?? method.method_id, + method_name: method.methodName ?? method.method_name, + pay_type: method.payType ?? method.pay_type, + pay_way: method.payWay ?? method.pay_way, + provider_code: method.providerCode ?? method.provider_code ?? channel.providerCode ?? channel.provider_code, + provider_name: method.providerName ?? method.provider_name ?? channel.providerName ?? channel.provider_name, + sort_order: method.sortOrder ?? method.sort_order, + status: method.status + })) + ); +} diff --git a/money/src/styles/index.css b/money/src/styles/index.css index 6915418..3ebd940 100644 --- a/money/src/styles/index.css +++ b/money/src/styles/index.css @@ -372,6 +372,26 @@ button { min-width: 180px; } +.money-filter select:disabled, +.money-field select:disabled { + cursor: not-allowed; + background: #f8fafc; + color: #98a2b3; +} + +.money-filter-status { + display: inline-flex; + min-height: 28px; + align-items: center; + border: 1px solid rgba(183, 121, 31, 0.25); + border-radius: 999px; + background: rgba(183, 121, 31, 0.08); + padding: 0 10px; + color: var(--money-warning); + font-size: 12px; + font-weight: 820; +} + .money-filter select:hover, .money-filter input:hover, .money-field select:hover, @@ -728,6 +748,317 @@ button { color: var(--money-accent); } +.money-temp-grid { + display: grid; + align-items: start; + gap: 16px; + grid-template-columns: minmax(0, 1.15fr) minmax(360px, 0.78fr); +} + +.money-temp-form-panel, +.money-result-panel, +.money-temp-side { + min-width: 0; +} + +.money-temp-form, +.money-temp-side, +.money-order-result { + display: grid; + gap: 14px; +} + +.money-temp-row { + display: grid; + gap: 10px; + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.money-temp-row--wide { + grid-template-columns: minmax(180px, 0.8fr) minmax(260px, 1.2fr); +} + +.money-field--wide { + width: 100%; +} + +.money-segmented-field { + display: grid; + gap: 6px; +} + +.money-segmented-field > span { + color: var(--money-muted); + font-size: 10px; + font-weight: 780; + line-height: 1; +} + +.money-segmented { + display: grid; + gap: 5px; + grid-template-columns: repeat(3, minmax(0, 1fr)); + min-height: 38px; + padding: 4px; + border: 1px solid #cfd9e5; + border-radius: 10px; + background: #f7f9fc; +} + +.money-segmented button { + border: 0; + border-radius: 8px; + background: transparent; + color: #526070; + font-size: 12px; + font-weight: 820; +} + +.money-segmented button.is-active, +.money-segmented button:hover { + background: #ffffff; + color: var(--money-ink); + box-shadow: 0 4px 14px rgba(16, 24, 40, 0.08); +} + +.money-temp-picker { + display: grid; + gap: 10px; +} + +.money-temp-picker-head { + display: flex; + min-width: 0; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.money-temp-picker-head strong { + color: var(--money-ink); + font-size: 13px; + font-weight: 850; +} + +.money-temp-picker-head > span { + color: var(--money-muted); + font-size: 12px; + font-weight: 780; +} + +.money-temp-picker-head label { + display: flex; + width: min(280px, 100%); + align-items: center; + gap: 7px; + border: 1px solid #cfd9e5; + border-radius: 10px; + background: #ffffff; + padding: 0 10px; + color: var(--money-muted); +} + +.money-temp-picker-head input { + height: 34px; + min-width: 0; + border: 0; + outline: 0; + background: transparent; +} + +.money-country-options, +.money-method-options { + display: grid; + gap: 8px; + max-height: 312px; + overflow: auto; + padding-right: 2px; +} + +.money-country-options { + grid-template-columns: repeat(2, minmax(0, 1fr)); +} + +.money-country-options button, +.money-method-option { + min-width: 0; + border: 1px solid #e3eaf2; + border-radius: 12px; + background: #ffffff; + color: var(--money-ink); + text-align: left; + transition: background-color 150ms ease, border-color 150ms ease, box-shadow 150ms ease, transform 180ms ease; +} + +.money-country-options button { + display: grid; + gap: 4px; + padding: 10px; +} + +.money-country-options button:hover, +.money-country-options button.is-active, +.money-method-option:hover, +.money-method-option.is-active { + border-color: rgba(47, 109, 246, 0.44); + background: #f8fbff; +} + +.money-country-options button.is-active, +.money-method-option.is-active { + box-shadow: inset 3px 0 0 var(--money-accent); +} + +.money-country-options strong { + overflow: hidden; + font-size: 13px; + font-weight: 820; + text-overflow: ellipsis; + white-space: nowrap; +} + +.money-country-options span { + color: var(--money-muted); + font-size: 12px; + font-weight: 760; +} + +.money-method-option { + display: grid; + align-items: center; + gap: 12px; + grid-template-columns: 42px minmax(0, 1fr) auto; + padding: 11px; +} + +.money-method-logo { + display: grid; + width: 42px; + height: 42px; + place-items: center; + overflow: hidden; + border: 1px solid #dce5ef; + border-radius: 12px; + background: #f7f9fc; + color: var(--money-accent); + font-size: 12px; + font-weight: 900; +} + +.money-method-logo img { + width: 100%; + height: 100%; + object-fit: contain; + padding: 6px; +} + +.money-method-copy { + display: grid; + min-width: 0; + gap: 3px; +} + +.money-method-copy strong, +.money-method-copy small { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.money-method-copy strong { + color: var(--money-ink); + font-weight: 820; +} + +.money-method-copy small { + color: var(--money-muted); + font-size: 12px; +} + +.money-method-tags { + display: flex; + justify-content: flex-end; + gap: 6px; + flex-wrap: wrap; +} + +.money-method-tags b, +.money-method-tags em { + display: inline-flex; + min-height: 24px; + align-items: center; + border: 1px solid #dce5ef; + border-radius: 999px; + padding: 0 8px; + color: #526070; + font-size: 11px; + font-style: normal; + font-weight: 850; +} + +.money-method-tags b { + border-color: rgba(47, 109, 246, 0.24); + background: rgba(47, 109, 246, 0.1); + color: var(--money-accent); +} + +.money-payment-actions { + display: flex; + min-width: 0; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.money-payment-message { + color: var(--money-muted); + font-size: 12px; + font-weight: 800; +} + +.money-payment-message--success { + color: var(--money-success); +} + +.money-payment-message--error { + color: var(--money-warning); +} + +.money-payment-empty { + min-height: 46px; + display: grid; + place-items: center; + border: 1px dashed #cfd9e5; + border-radius: 12px; + background: #f8fafc; + color: var(--money-muted); + font-size: 12px; + font-weight: 780; +} + +.money-result-row { + display: grid; + min-width: 0; + gap: 5px; +} + +.money-result-row > strong { + color: var(--money-muted); + font-size: 12px; + font-weight: 830; +} + +.money-result-row > div { + min-width: 0; + overflow-wrap: anywhere; + border: 1px solid #e3eaf2; + border-radius: 12px; + background: #f8fafc; + padding: 10px 11px; + color: var(--money-ink); + line-height: 1.45; +} + .money-link-panel { display: grid; gap: 14px; @@ -801,6 +1132,12 @@ button { color: var(--money-success); } +.money-status--danger { + border-color: rgba(196, 47, 47, 0.26); + background: rgba(196, 47, 47, 0.08); + color: #b42318; +} + .money-table-panel { padding: 0; overflow: hidden; @@ -830,6 +1167,10 @@ button { min-width: 1120px; } +.money-table--payments { + min-width: 1380px; +} + .money-table th, .money-table td { height: 52px; @@ -875,6 +1216,177 @@ button { font-weight: 760; } +.money-link-table-head { + min-height: 68px; +} + +.money-link-toolbar { + display: flex; + min-width: 0; + align-items: center; + justify-content: flex-end; + gap: 8px; + flex-wrap: wrap; +} + +.money-link-toolbar .money-field { + min-width: 128px; +} + +.money-table-message, +.money-link-footer { + display: flex; + min-width: 0; + align-items: center; + justify-content: space-between; + gap: 10px; + padding: 10px 16px; + border-bottom: 1px solid #e3eaf2; + background: #fff8ed; + color: var(--money-warning); + font-size: 12px; + font-weight: 780; +} + +.money-link-footer { + justify-content: flex-start; + border-top: 1px solid #e3eaf2; + border-bottom: 0; + background: #f8fafc; + color: var(--money-muted); +} + +.money-row-actions, +.money-copyable, +.money-payment-url { + display: inline-flex; + min-width: 0; + align-items: center; + gap: 6px; +} + +.money-row-actions { + gap: 7px; +} + +.money-copyable > span, +.money-payment-url code { + overflow: hidden; + max-width: 260px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.money-payment-url code { + display: inline-block; + color: #475467; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; + font-size: 12px; +} + +.money-empty-cell { + height: 120px; + color: var(--money-muted); + text-align: center; +} + +.money-modal-backdrop { + position: fixed; + inset: 0; + z-index: 30; + display: grid; + place-items: center; + padding: 24px; + background: rgba(16, 24, 40, 0.38); + backdrop-filter: blur(8px); +} + +.money-payment-dialog { + width: min(920px, calc(100vw - 40px)); + max-height: calc(100vh - 48px); + overflow: hidden; + border: 1px solid rgba(207, 217, 229, 0.96); + border-radius: 16px; + background: #ffffff; + box-shadow: 0 28px 80px rgba(16, 24, 40, 0.26); +} + +.money-payment-dialog > header, +.money-create-form > footer { + display: flex; + min-width: 0; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 16px; +} + +.money-payment-dialog > header { + border-bottom: 1px solid #e3eaf2; +} + +.money-payment-dialog h2 { + margin: 0 0 3px; + font-size: 18px; + font-weight: 880; +} + +.money-payment-dialog header span { + color: var(--money-muted); + font-size: 12px; + font-weight: 820; +} + +.money-create-form { + display: grid; + max-height: calc(100vh - 138px); + overflow: auto; +} + +.money-create-grid { + display: grid; + gap: 12px; + grid-template-columns: repeat(4, minmax(0, 1fr)); + padding: 16px; +} + +.money-method-select { + display: grid; + gap: 10px; + padding: 0 16px 16px; +} + +.money-method-select-head { + display: flex; + min-width: 0; + align-items: center; + justify-content: space-between; + gap: 10px; +} + +.money-method-select-head strong { + color: var(--money-ink); + font-size: 13px; + font-weight: 850; +} + +.money-method-select-head span { + color: var(--money-muted); + font-size: 12px; + font-weight: 780; +} + +.money-method-options--dialog { + max-height: 320px; +} + +.money-create-form > footer { + position: sticky; + bottom: 0; + border-top: 1px solid #e3eaf2; + background: rgba(255, 255, 255, 0.96); +} + .money-scope--app { border-color: rgba(47, 109, 246, 0.34); background: rgba(47, 109, 246, 0.1); @@ -1030,9 +1542,12 @@ button { } .money-analysis, + .money-temp-grid, + .money-create-grid, .money-link-form, .money-workbench-grid, - .money-country-grid { + .money-country-grid, + .money-temp-row--wide { grid-template-columns: 1fr; } @@ -1069,7 +1584,8 @@ button { .money-header-tools, .money-filter-group, - .money-actions { + .money-actions, + .money-link-toolbar { width: 100%; justify-content: flex-start; } @@ -1088,6 +1604,10 @@ button { grid-template-columns: 1fr; } + .money-country-options { + grid-template-columns: 1fr; + } + .money-link-row aside { justify-items: start; } @@ -1110,10 +1630,20 @@ button { .money-retention, .money-signal-grid, .money-operator-cards, - .money-country-metrics { + .money-country-metrics, + .money-temp-row { grid-template-columns: 1fr; } + .money-method-option { + grid-template-columns: 38px minmax(0, 1fr); + } + + .money-method-tags { + grid-column: 1 / -1; + justify-content: flex-start; + } + .money-header-title h1 { font-size: 22px; } @@ -1145,6 +1675,14 @@ button { flex-direction: column; } + .money-payment-dialog { + width: calc(100vw - 24px); + } + + .money-modal-backdrop { + padding: 12px; + } + .money-trend-chart { height: 238px; } diff --git a/money/src/temporaryPaymentApi.js b/money/src/temporaryPaymentApi.js new file mode 100644 index 0000000..e373a20 --- /dev/null +++ b/money/src/temporaryPaymentApi.js @@ -0,0 +1,117 @@ +const RETURN_URL_BASE = "https://h5.global-interaction.com/recharge/index.html"; + +export const TEMPORARY_RETURN_APPS = ["lalu", "yumi", "aslan"]; + +export function defaultReturnUrl(appCode = "lalu") { + const url = new URL(RETURN_URL_BASE); + url.searchParams.set("app_code", String(appCode || "lalu").trim() || "lalu"); + return url.toString(); +} + +export function isKnownDefaultReturnUrl(value) { + const text = String(value || "").trim(); + return TEMPORARY_RETURN_APPS.some((appCode) => text === defaultReturnUrl(appCode)); +} + +export function dollarsToMinor(value) { + const text = String(value || "").trim(); + if (!/^\d+(\.\d{1,2})?$/.test(text)) { + return 0; + } + return Math.round(Number(text) * 100); +} + +export function extractOrderId(value) { + const text = String(value || "").trim(); + if (!text) { + return ""; + } + try { + const url = new URL(text, window.location.href); + const queryId = url.searchParams.get("order_id") || url.searchParams.get("orderId"); + if (queryId) { + return queryId.trim(); + } + const match = url.pathname.match(/temporary-pay\/([^/]+)\.html$/); + if (match) { + return decodeURIComponent(match[1]); + } + } catch { + // Plain order ids are valid input. + } + return text.replace(/^order_id=/, "").trim(); +} + +export function formatMinorUsd(value) { + if (!(value === 0 || value)) { + return "-"; + } + return `USD ${(Number(value) / 100).toLocaleString("zh-CN", { + maximumFractionDigits: 2, + minimumFractionDigits: 2 + })}`; +} + +export function buildTemporaryCountries(sourceMethods) { + const byCode = {}; + sourceMethods.forEach((method, index) => { + const code = temporaryCountryCode(method); + if (!code) { + return; + } + if (!byCode[code]) { + byCode[code] = { + code, + count: 0, + currency: method.currency_code || "", + firstSort: Number(method.sort_order || 0) || index, + name: method.country_name || code + }; + } + byCode[code].count += 1; + }); + return Object.keys(byCode) + .map((code) => byCode[code]) + .sort((a, b) => a.firstSort - b.firstSort); +} + +export function temporaryCountryCode(method) { + return String(method?.country_code || "") + .trim() + .toUpperCase(); +} + +export function temporaryCountryLabel(country) { + if (!country) { + return ""; + } + return country.name && country.name !== country.code ? `${country.name} · ${country.code}` : country.code; +} + +export function temporaryMethodLabel(method) { + return [method?.method_name, method?.pay_way, method?.pay_type, method?.provider_name].filter(Boolean).join(" "); +} + +export function temporaryLogoText(method) { + const value = method?.method_name || method?.pay_type || method?.provider_name || method?.provider_code || "Pay"; + return String(value).replace(/[^a-z0-9]/gi, "").slice(0, 2).toUpperCase(); +} + +export function temporaryStatusLabel(status) { + if (status === "paid") { + return "已支付"; + } + if (status === "redirected") { + return "已生成"; + } + if (status === "pending") { + return "待支付"; + } + if (status === "failed") { + return "失败"; + } + if (status === "credited") { + return "已入账"; + } + return status || "-"; +} diff --git a/money/src/temporaryPaymentApi.test.js b/money/src/temporaryPaymentApi.test.js new file mode 100644 index 0000000..aa698ae --- /dev/null +++ b/money/src/temporaryPaymentApi.test.js @@ -0,0 +1,35 @@ +import { expect, test } from "vitest"; +import { buildTemporaryCountries, defaultReturnUrl, dollarsToMinor, extractOrderId, temporaryStatusLabel } from "./temporaryPaymentApi.js"; + +test("converts usd text to minor amount with strict two-decimal validation", () => { + expect(dollarsToMinor("300")).toBe(30000); + expect(dollarsToMinor("9.99")).toBe(999); + expect(dollarsToMinor("9.999")).toBe(0); + expect(dollarsToMinor("abc")).toBe(0); +}); + +test("extracts temporary order id from plain text, query, and wrapped html url", () => { + expect(extractOrderId("ORDER-1")).toBe("ORDER-1"); + expect(extractOrderId("order_id=ORDER-2")).toBe("ORDER-2"); + expect(extractOrderId("https://pay.example/pay?order_id=ORDER-3")).toBe("ORDER-3"); + expect(extractOrderId("https://cos.example/temporary-pay/ORDER-4.html")).toBe("ORDER-4"); +}); + +test("builds country rows from temporary payment methods by first sort order", () => { + const countries = buildTemporaryCountries([ + { country_code: "BR", country_name: "Brazil", currency_code: "BRL", method_id: 2, sort_order: 20 }, + { country_code: "SA", country_name: "Saudi", currency_code: "SAR", method_id: 1, sort_order: 10 }, + { country_code: "BR", country_name: "Brazil", currency_code: "BRL", method_id: 3, sort_order: 30 } + ]); + + expect(countries).toEqual([ + { code: "SA", count: 1, currency: "SAR", firstSort: 10, name: "Saudi" }, + { code: "BR", count: 2, currency: "BRL", firstSort: 20, name: "Brazil" } + ]); +}); + +test("keeps h5 return app separate from payment app code", () => { + expect(defaultReturnUrl("yumi")).toBe("https://h5.global-interaction.com/recharge/index.html?app_code=yumi"); + expect(defaultReturnUrl("unknown")).toBe("https://h5.global-interaction.com/recharge/index.html?app_code=unknown"); + expect(temporaryStatusLabel("credited")).toBe("已入账"); +}); diff --git a/src/app/permissions.ts b/src/app/permissions.ts index 73a21e9..ed2e591 100644 --- a/src/app/permissions.ts +++ b/src/app/permissions.ts @@ -39,6 +39,7 @@ export const PERMISSIONS = { coinSellerStockCredit: "coin-seller:stock-credit", coinSellerExchangeRate: "coin-seller:exchange-rate", moneyView: "money:view", + moneyPaymentLinkCreate: "money:payment-link:create", coinLedgerView: "coin-ledger:view", coinSellerLedgerView: "coin-seller-ledger:view", coinAdjustmentView: "coin-adjustment:view", diff --git a/src/features/users/api.test.ts b/src/features/users/api.test.ts index 52c7d2f..fc586f5 100644 --- a/src/features/users/api.test.ts +++ b/src/features/users/api.test.ts @@ -1,6 +1,6 @@ import { afterEach, expect, test, vi } from "vitest"; import { setAccessToken } from "@/shared/api/request"; -import { listUsers, updateUserStatus } from "./api"; +import { getMoneyScopeCatalog, listUserMoneyScopes, listUsers, replaceUserMoneyScopes, updateUserStatus } from "./api"; afterEach(() => { setAccessToken(""); @@ -37,3 +37,23 @@ test("updateUserStatus sends generated endpoint path and payload", async () => { expect(init?.method).toBe("PATCH"); expect(JSON.parse(String(init?.body))).toEqual({ status: "locked" }); }); + +test("money scope APIs use generated endpoint paths", async () => { + vi.stubGlobal( + "fetch", + vi.fn(async () => new Response(JSON.stringify({ code: 0, data: { apps: [], items: [], total: 0 } }))) + ); + + await listUserMoneyScopes(9); + await replaceUserMoneyScopes(9, [{ appCode: "lalu", regionId: 2 }]); + await getMoneyScopeCatalog(); + + const calls = vi.mocked(fetch).mock.calls; + expect(String(calls[0][0])).toContain("/api/v1/users/9/money-scopes"); + expect(calls[0][1]?.method).toBe("GET"); + expect(String(calls[1][0])).toContain("/api/v1/users/9/money-scopes"); + expect(calls[1][1]?.method).toBe("PUT"); + expect(JSON.parse(String(calls[1][1]?.body))).toEqual({ scopes: [{ appCode: "lalu", regionId: 2 }] }); + expect(String(calls[2][0])).toContain("/api/v1/admin/money/scope"); + expect(calls[2][1]?.method).toBe("GET"); +}); diff --git a/src/features/users/api.ts b/src/features/users/api.ts index d38b734..c3b2661 100644 --- a/src/features/users/api.ts +++ b/src/features/users/api.ts @@ -8,6 +8,7 @@ import type { PageQuery, ResetPasswordResultDto, UserFormPayload, + UserMoneyScopeDto, UserStatus, UserUpdatePayload } from "@/shared/api/types"; @@ -63,3 +64,26 @@ export function batchUpdateUserStatus(ids: EntityId[], status: UserStatus): Prom export function exportUsers(query?: PageQuery): Promise { return apiRequest(apiEndpointPath(API_OPERATIONS.exportUsers), { query, raw: true }); } + +export interface MoneyScopeCatalogDto { + all?: boolean; + apps?: Array<{ appCode: string; appName?: string }>; + regions?: Array<{ appCode: string; countries?: string[]; name?: string; regionCode?: string; regionId: number }>; + countries?: Array<{ appCode: string; countryCode: string; countryDisplayName?: string; countryName?: string; regionId?: number }>; + scopes?: UserMoneyScopeDto[]; +} + +export function listUserMoneyScopes(id: EntityId): Promise<{ items: UserMoneyScopeDto[]; total: number }> { + return apiRequest<{ items: UserMoneyScopeDto[]; total: number }>(apiEndpointPath(API_OPERATIONS.listUserMoneyScopes, { id })); +} + +export function replaceUserMoneyScopes(id: EntityId, scopes: UserMoneyScopeDto[]): Promise<{ items: UserMoneyScopeDto[]; total: number }> { + return apiRequest<{ items: UserMoneyScopeDto[]; total: number }, { scopes: UserMoneyScopeDto[] }>(apiEndpointPath(API_OPERATIONS.replaceUserMoneyScopes, { id }), { + body: { scopes }, + method: "PUT" + }); +} + +export function getMoneyScopeCatalog(): Promise { + return apiRequest(apiEndpointPath(API_OPERATIONS.getMoneyScope)); +} diff --git a/src/features/users/components/UserFormDrawer.jsx b/src/features/users/components/UserFormDrawer.jsx index 5731db7..06d8d21 100644 --- a/src/features/users/components/UserFormDrawer.jsx +++ b/src/features/users/components/UserFormDrawer.jsx @@ -6,7 +6,9 @@ import { Button } from "@/shared/ui/Button.jsx"; export function UserFormDrawer({ editingUser, form, + moneyScopeCatalog, onClose, + onMoneyScopeChecked, onRoleChecked, onSubmit, open, @@ -34,6 +36,24 @@ export function UserFormDrawer({ ) : null} +
+
财务范围
+
+ {moneyScopeCatalog?.loading ? 加载中 : null} + {moneyScopeCatalog?.error ? {moneyScopeCatalog.error} : null} + {!moneyScopeCatalog?.loading && !moneyScopeCatalog?.error + ? (moneyScopeCatalog?.apps || []).map((app) => ( + region.appCode === app.appCode)} + /> + )) + : null} +
+
角色
@@ -67,3 +87,29 @@ export function UserFormDrawer({ ); } + +function MoneyScopeGroup({ app, checkedScopes, onChecked, regions }) { + const appCode = app.appCode; + const isChecked = (regionId) => + checkedScopes.some((scope) => scope.appCode === appCode && Number(scope.regionId) === Number(regionId)); + + return ( +
+ {app.appName || appCode} + + {regions.map((region) => ( + + ))} +
+ ); +} diff --git a/src/features/users/hooks/useUsersPage.js b/src/features/users/hooks/useUsersPage.js index 40fb5a7..26ae90c 100644 --- a/src/features/users/hooks/useUsersPage.js +++ b/src/features/users/hooks/useUsersPage.js @@ -12,7 +12,10 @@ import { batchUpdateUserStatus, createUser, exportUsers, + getMoneyScopeCatalog, + listUserMoneyScopes, listUsers, + replaceUserMoneyScopes, resetUserPassword, updateUser, updateUserStatus, @@ -29,6 +32,7 @@ const emptyForm = { name: "", password: "", roleIds: [], + moneyScopes: [], status: "active", team: "", username: "", @@ -44,6 +48,7 @@ export function useUsersPage() { const [editingUser, setEditingUser] = useState(null); const [profileUser, setProfileUser] = useState(null); const [form, setForm] = useState(emptyForm); + const [moneyScopeCatalog, setMoneyScopeCatalog] = useState({ apps: [], countries: [], error: "", loading: false, regions: [] }); const [mergedUsers, setMergedUsers] = useState(emptyUsers); const abilities = useUserAbilities(); const confirm = useConfirm(); @@ -133,10 +138,27 @@ export function useUsersPage() { setPage(1); }; + const loadMoneyScopeCatalog = useCallback(async () => { + setMoneyScopeCatalog((current) => ({ ...current, error: "", loading: true })); + try { + const catalog = await getMoneyScopeCatalog(); + setMoneyScopeCatalog({ + apps: Array.isArray(catalog?.apps) ? catalog.apps : [], + countries: Array.isArray(catalog?.countries) ? catalog.countries : [], + error: "", + loading: false, + regions: Array.isArray(catalog?.regions) ? catalog.regions : [], + }); + } catch (err) { + setMoneyScopeCatalog({ apps: [], countries: [], error: err.message || "加载财务范围失败", loading: false, regions: [] }); + } + }, []); + const openCreate = () => { setEditingUser(null); setForm(emptyForm); setFormOpen(true); + loadMoneyScopeCatalog(); }; const openEdit = (user) => { @@ -146,11 +168,23 @@ export function useUsersPage() { name: user.name, password: "", roleIds: user.roleIds || [], + moneyScopes: [], status: user.status, team: user.team || "", username: user.account, }); setFormOpen(true); + loadMoneyScopeCatalog(); + listUserMoneyScopes(user.id) + .then((data) => { + const scopes = Array.isArray(data?.items) ? data.items : []; + setForm((current) => + editingUser?.id === user.id || current.username === user.account + ? { ...current, moneyScopes: normalizeMoneyScopes(scopes) } + : current, + ); + }) + .catch((err) => showToast(err.message || "加载财务范围失败", "error")); }; const closeForm = () => { @@ -171,10 +205,14 @@ export function useUsersPage() { if (editingUser) { const payload = parseForm(userUpdateFormSchema, form); await updateUser(editingUser.id, payload); + await replaceUserMoneyScopes(editingUser.id, normalizeMoneyScopes(form.moneyScopes)); showToast("用户已更新", "success"); } else { const payload = parseForm(userCreateFormSchema, form); const result = await createUser(payload); + if (result?.user?.id) { + await replaceUserMoneyScopes(result.user.id, normalizeMoneyScopes(form.moneyScopes)); + } showToast(`用户已创建,初始密码:${result.initialPassword}`, "success"); } setFormOpen(false); @@ -263,6 +301,28 @@ export function useUsersPage() { })); }; + const setMoneyScopeChecked = (appCode, regionId, checked) => { + const normalizedAppCode = String(appCode || "").trim(); + const normalizedRegionId = Number(regionId || 0); + if (!normalizedAppCode || normalizedRegionId < 0) { + return; + } + setForm((current) => { + const scopes = normalizeMoneyScopes(current.moneyScopes); + const exists = scopes.some((scope) => scope.appCode === normalizedAppCode && Number(scope.regionId) === normalizedRegionId); + if (checked && !exists) { + return { ...current, moneyScopes: [...scopes, { appCode: normalizedAppCode, regionId: normalizedRegionId }] }; + } + if (!checked && exists) { + return { + ...current, + moneyScopes: scopes.filter((scope) => !(scope.appCode === normalizedAppCode && Number(scope.regionId) === normalizedRegionId)), + }; + } + return current; + }); + }; + return { abilities, batchStatus, @@ -277,6 +337,7 @@ export function useUsersPage() { form, formOpen, loading, + moneyScopeCatalog, navigate, openCreate, openEdit, @@ -292,6 +353,7 @@ export function useUsersPage() { roles, selectedIds, setForm, + setMoneyScopeChecked, setPage, setRoleChecked, setSelectedIds, @@ -303,3 +365,23 @@ export function useUsersPage() { users, }; } + +function normalizeMoneyScopes(scopes = []) { + const seen = new Set(); + return (Array.isArray(scopes) ? scopes : []) + .map((scope) => ({ + appCode: String(scope.appCode || scope.app_code || "").trim(), + regionId: Number(scope.regionId ?? scope.region_id ?? 0), + })) + .filter((scope) => { + if (!scope.appCode || scope.regionId < 0) { + return false; + } + const key = `${scope.appCode}:${scope.regionId}`; + if (seen.has(key)) { + return false; + } + seen.add(key); + return true; + }); +} diff --git a/src/features/users/pages/UserManagementPage.jsx b/src/features/users/pages/UserManagementPage.jsx index 64e525a..e1aa84e 100644 --- a/src/features/users/pages/UserManagementPage.jsx +++ b/src/features/users/pages/UserManagementPage.jsx @@ -94,7 +94,9 @@ export function UserManagementPage() { = { - adjustDicePool: { - method: "POST", - operationId: API_OPERATIONS.adjustDicePool, - path: "/v1/admin/game/self-games/{game_id}/pool/adjust", - permission: "game:update", - permissions: ["game:update"], - }, - appBanUser: { - method: "POST", - operationId: API_OPERATIONS.appBanUser, - path: "/v1/app/users/{id}/ban", - permission: "app-user:status", - permissions: ["app-user:status"], - }, - appGetUser: { - method: "GET", - operationId: API_OPERATIONS.appGetUser, - path: "/v1/app/users/{id}", - permission: "app-user:view", - permissions: ["app-user:view"], - }, - appListBannedUsers: { - method: "GET", - operationId: API_OPERATIONS.appListBannedUsers, - path: "/v1/app/users/bans", - permission: "app-user:view", - permissions: ["app-user:view"], - }, - appListLoginLogs: { - method: "GET", - operationId: API_OPERATIONS.appListLoginLogs, - path: "/v1/app/users/login-logs", - permission: "app-user:view", - permissions: ["app-user:view"], - }, - appListUserLoginLogs: { - method: "GET", - operationId: API_OPERATIONS.appListUserLoginLogs, - path: "/v1/app/users/{id}/login-logs", - permission: "app-user:view", - permissions: ["app-user:view"], - }, - appListUsers: { - method: "GET", - operationId: API_OPERATIONS.appListUsers, - path: "/v1/app/users", - permission: "app-user:view", - permissions: ["app-user:view"], - }, - appSetPassword: { - method: "POST", - operationId: API_OPERATIONS.appSetPassword, - path: "/v1/app/users/{id}/password", - permission: "app-user:password", - permissions: ["app-user:password"], - }, - appUnbanUser: { - method: "POST", - operationId: API_OPERATIONS.appUnbanUser, - path: "/v1/app/users/{id}/unban", - permission: "app-user:status", - permissions: ["app-user:status"], - }, - appUpdateUser: { - method: "PATCH", - operationId: API_OPERATIONS.appUpdateUser, - path: "/v1/app/users/{id}", - permission: "app-user:update", - permissions: ["app-user:update"], - }, - batchUpdateUserStatus: { - method: "POST", - operationId: API_OPERATIONS.batchUpdateUserStatus, - path: "/v1/users/batch/status", - permission: "user:status", - permissions: ["user:status"], - }, - cancelRoomPin: { - method: "DELETE", - operationId: API_OPERATIONS.cancelRoomPin, - path: "/v1/admin/rooms/pins/{pin_id}", - permission: "room-pin:cancel", - permissions: ["room-pin:cancel"], - }, - changePassword: { - method: "POST", - operationId: API_OPERATIONS.changePassword, - path: "/v1/auth/change-password", - }, - closeAgency: { - method: "POST", - operationId: API_OPERATIONS.closeAgency, - path: "/v1/admin/agencies/{agency_id}/close", - permission: "agency:status", - permissions: ["agency:status"], - }, - createAchievementDefinition: { - method: "POST", - operationId: API_OPERATIONS.createAchievementDefinition, - path: "/v1/admin/activity/achievements", - permission: "achievement:create", - permissions: ["achievement:create"], - }, - createAgency: { - method: "POST", - operationId: API_OPERATIONS.createAgency, - path: "/v1/admin/agencies", - permission: "agency:create", - permissions: ["agency:create"], - }, - createAppVersion: { - method: "POST", - operationId: API_OPERATIONS.createAppVersion, - path: "/v1/admin/app-config/versions", - permission: "app-version:create", - permissions: ["app-version:create"], - }, - createBanner: { - method: "POST", - operationId: API_OPERATIONS.createBanner, - path: "/v1/admin/app-config/banners", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - createBD: { - method: "POST", - operationId: API_OPERATIONS.createBD, - path: "/v1/admin/bds", - permission: "bd:create", - permissions: ["bd:create"], - }, - createBDLeader: { - method: "POST", - operationId: API_OPERATIONS.createBDLeader, - path: "/v1/admin/bd-leaders", - permission: "bd:create", - permissions: ["bd:create"], - }, - createCatalog: { - method: "POST", - operationId: API_OPERATIONS.createCatalog, - path: "/v1/admin/game/games", - permission: "game:create", - permissions: ["game:create"], - }, - createCoinAdjustment: { - method: "POST", - operationId: API_OPERATIONS.createCoinAdjustment, - path: "/v1/admin/operations/coin-adjustments", - permission: "coin-adjustment:create", - permissions: ["coin-adjustment:create"], - }, - createCoinSeller: { - method: "POST", - operationId: API_OPERATIONS.createCoinSeller, - path: "/v1/admin/coin-sellers", - permission: "coin-seller:create", - permissions: ["coin-seller:create"], - }, - createCountry: { - method: "POST", - operationId: API_OPERATIONS.createCountry, - path: "/v1/admin/countries", - permission: "country:create", - permissions: ["country:create"], - }, - createEmojiPack: { - method: "POST", - operationId: API_OPERATIONS.createEmojiPack, - path: "/v1/admin/emoji-packs", - permission: "emoji-pack:create", - permissions: ["emoji-pack:create"], - }, - createExploreTab: { - method: "POST", - operationId: API_OPERATIONS.createExploreTab, - path: "/v1/admin/app-config/explore-tabs", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - createFullServerNoticeFanout: { - method: "POST", - operationId: API_OPERATIONS.createFullServerNoticeFanout, - path: "/v1/admin/operations/full-server-notices/fanout", - permission: "full-server-notice:send", - permissions: ["full-server-notice:send"], - }, - createGift: { - method: "POST", - operationId: API_OPERATIONS.createGift, - path: "/v1/admin/gifts", - permission: "gift:create", - permissions: ["gift:create"], - }, - createH5Link: { - method: "POST", - operationId: API_OPERATIONS.createH5Link, - path: "/v1/admin/app-config/h5-links", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - createHostAgencyPolicy: { - method: "POST", - operationId: API_OPERATIONS.createHostAgencyPolicy, - path: "/v1/admin/host-agency-policies", - permission: "host-agency-policy:create", - permissions: ["host-agency-policy:create"], - }, - createManager: { - method: "POST", - operationId: API_OPERATIONS.createManager, - path: "/v1/admin/managers", - permission: "bd:create", - permissions: ["bd:create"], - }, - createMenu: { - method: "POST", - operationId: API_OPERATIONS.createMenu, - path: "/v1/system/menus", - permission: "menu:create", - permissions: ["menu:create"], - }, - createPermission: { - method: "POST", - operationId: API_OPERATIONS.createPermission, - path: "/v1/permissions", - permission: "permission:create", - permissions: ["permission:create"], - }, - createPlatform: { - method: "POST", - operationId: API_OPERATIONS.createPlatform, - path: "/v1/admin/game/platforms", - permission: "game:update", - permissions: ["game:update"], - }, - createPopup: { - method: "POST", - operationId: API_OPERATIONS.createPopup, - path: "/v1/admin/app-config/popups", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - createPrettyIdPool: { - method: "POST", - operationId: API_OPERATIONS.createPrettyIdPool, - path: "/v1/admin/users/pretty-id-pools", - permission: "pretty-id:update", - permissions: ["pretty-id:update"], - }, - createRechargeProduct: { - method: "POST", - operationId: API_OPERATIONS.createRechargeProduct, - path: "/v1/admin/payment/recharge-products", - permission: "payment-product:create", - permissions: ["payment-product:create"], - }, - createRegion: { - method: "POST", - operationId: API_OPERATIONS.createRegion, - path: "/v1/admin/regions", - permission: "region:create", - permissions: ["region:create"], - }, - createResource: { - method: "POST", - operationId: API_OPERATIONS.createResource, - path: "/v1/admin/resources", - permission: "resource:create", - permissions: ["resource:create"], - }, - createResourceGroup: { - method: "POST", - operationId: API_OPERATIONS.createResourceGroup, - path: "/v1/admin/resource-groups", - permission: "resource-group:create", - permissions: ["resource-group:create"], - }, - createRobotRoom: { - method: "POST", - operationId: API_OPERATIONS.createRobotRoom, - path: "/v1/admin/rooms/robot-rooms", - permission: "room-robot:create", - permissions: ["room-robot:create"], - }, - createRole: { - method: "POST", - operationId: API_OPERATIONS.createRole, - path: "/v1/roles", - permission: "role:create", - permissions: ["role:create", "role:manage"], - }, - createRoomPin: { - method: "POST", - operationId: API_OPERATIONS.createRoomPin, - path: "/v1/admin/rooms/pins", - permission: "room-pin:create", - permissions: ["room-pin:create"], - }, - createSplashScreen: { - method: "POST", - operationId: API_OPERATIONS.createSplashScreen, - path: "/v1/admin/app-config/splash-screens", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - createTaskDefinition: { - method: "POST", - operationId: API_OPERATIONS.createTaskDefinition, - path: "/v1/admin/activity/daily-tasks", - permission: "daily-task:create", - permissions: ["daily-task:create"], - }, - createTeamSalaryPolicy: { - method: "POST", - operationId: API_OPERATIONS.createTeamSalaryPolicy, - path: "/v1/admin/team-salary-policies", - permission: "team-salary-policy:create", - permissions: ["team-salary-policy:create"], - }, - createTier: { - method: "POST", - operationId: API_OPERATIONS.createTier, - path: "/v1/admin/users/level-config/tiers", - permission: "level-config:update", - permissions: ["level-config:update"], - }, - createUser: { - method: "POST", - operationId: API_OPERATIONS.createUser, - path: "/v1/users", - permission: "user:create", - permissions: ["user:create"], - }, - createWeeklyStarCycle: { - method: "POST", - operationId: API_OPERATIONS.createWeeklyStarCycle, - path: "/v1/admin/activity/weekly-star/cycles", - permission: "weekly-star:create", - permissions: ["weekly-star:create"], - }, - creditCoinSellerStock: { - method: "POST", - operationId: API_OPERATIONS.creditCoinSellerStock, - path: "/v1/admin/coin-sellers/{user_id}/stock-credits", - permission: "coin-seller:stock-credit", - permissions: ["coin-seller:stock-credit"], - }, - dashboardOverview: { - method: "GET", - operationId: API_OPERATIONS.dashboardOverview, - path: "/v1/dashboard/overview", - permission: "overview:view", - permissions: ["overview:view"], - }, - debitCoinSellerStock: { - method: "POST", - operationId: API_OPERATIONS.debitCoinSellerStock, - path: "/v1/admin/coin-sellers/{user_id}/stock-debits", - permission: "coin-seller:stock-credit", - permissions: ["coin-seller:stock-credit"], - }, - deleteAchievementDefinition: { - method: "DELETE", - operationId: API_OPERATIONS.deleteAchievementDefinition, - path: "/v1/admin/activity/achievements/{achievement_id}", - permission: "achievement:update", - permissions: ["achievement:update"], - }, - deleteAgency: { - method: "POST", - operationId: API_OPERATIONS.deleteAgency, - path: "/v1/admin/agencies/{agency_id}/delete", - permission: "agency:delete", - permissions: ["agency:delete"], - }, - deleteAppVersion: { - method: "DELETE", - operationId: API_OPERATIONS.deleteAppVersion, - path: "/v1/admin/app-config/versions/{version_id}", - permission: "app-version:delete", - permissions: ["app-version:delete"], - }, - deleteBanner: { - method: "DELETE", - operationId: API_OPERATIONS.deleteBanner, - path: "/v1/admin/app-config/banners/{banner_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - deleteBDLeader: { - method: "DELETE", - operationId: API_OPERATIONS.deleteBDLeader, - path: "/v1/admin/bd-leaders/{user_id}", - permission: "bd:update", - permissions: ["bd:update"], - }, - deleteCatalog: { - method: "DELETE", - operationId: API_OPERATIONS.deleteCatalog, - path: "/v1/admin/game/games/{game_id}", - permission: "game:delete", - permissions: ["game:delete"], - }, - deleteCountry: { - method: "DELETE", - operationId: API_OPERATIONS.deleteCountry, - path: "/v1/admin/countries/{country_id}", - permission: "country:status", - permissions: ["country:status"], - }, - deleteDiceRobot: { - method: "DELETE", - operationId: API_OPERATIONS.deleteDiceRobot, - path: "/v1/admin/game/robots/{user_id}", - permission: "game:delete", - permissions: ["game:delete"], - }, - deleteExploreTab: { - method: "DELETE", - operationId: API_OPERATIONS.deleteExploreTab, - path: "/v1/admin/app-config/explore-tabs/{tab_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - deleteGift: { - method: "DELETE", - operationId: API_OPERATIONS.deleteGift, - path: "/v1/admin/gifts/{gift_id}", - permission: "gift:delete", - permissions: ["gift:delete"], - }, - deleteH5Link: { - method: "DELETE", - operationId: API_OPERATIONS.deleteH5Link, - path: "/v1/admin/app-config/h5-links/{key}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - deleteHostAgencyPolicy: { - method: "DELETE", - operationId: API_OPERATIONS.deleteHostAgencyPolicy, - path: "/v1/admin/host-agency-policies/{policy_id}", - permission: "host-agency-policy:delete", - permissions: ["host-agency-policy:delete"], - }, - deleteMenu: { - method: "DELETE", - operationId: API_OPERATIONS.deleteMenu, - path: "/v1/system/menus/{id}", - permission: "menu:delete", - permissions: ["menu:delete"], - }, - deletePermission: { - method: "DELETE", - operationId: API_OPERATIONS.deletePermission, - path: "/v1/permissions/{id}", - permission: "permission:delete", - permissions: ["permission:delete"], - }, - deletePopup: { - method: "DELETE", - operationId: API_OPERATIONS.deletePopup, - path: "/v1/admin/app-config/popups/{popup_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - deleteRechargeProduct: { - method: "DELETE", - operationId: API_OPERATIONS.deleteRechargeProduct, - path: "/v1/admin/payment/recharge-products/{product_id}", - permission: "payment-product:delete", - permissions: ["payment-product:delete"], - }, - deleteRole: { - method: "DELETE", - operationId: API_OPERATIONS.deleteRole, - path: "/v1/roles/{id}", - permission: "role:delete", - permissions: ["role:delete", "role:manage"], - }, - deleteRoom: { - method: "DELETE", - operationId: API_OPERATIONS.deleteRoom, - path: "/v1/admin/rooms/{room_id}", - permission: "room:delete", - permissions: ["room:delete"], - }, - deleteSplashScreen: { - method: "DELETE", - operationId: API_OPERATIONS.deleteSplashScreen, - path: "/v1/admin/app-config/splash-screens/{splash_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - deleteTeamSalaryPolicy: { - method: "DELETE", - operationId: API_OPERATIONS.deleteTeamSalaryPolicy, - path: "/v1/admin/team-salary-policies/{policy_id}", - permission: "team-salary-policy:delete", - permissions: ["team-salary-policy:delete"], - }, - disableCountry: { - method: "POST", - operationId: API_OPERATIONS.disableCountry, - path: "/v1/admin/countries/{country_id}/disable", - permission: "country:status", - permissions: ["country:status"], - }, - disableGift: { - method: "POST", - operationId: API_OPERATIONS.disableGift, - path: "/v1/admin/gifts/{gift_id}/disable", - permission: "gift:status", - permissions: ["gift:status"], - }, - disableRegion: { - method: "DELETE", - operationId: API_OPERATIONS.disableRegion, - path: "/v1/admin/regions/{region_id}", - permission: "region:status", - permissions: ["region:status"], - }, - disableResource: { - method: "POST", - operationId: API_OPERATIONS.disableResource, - path: "/v1/admin/resources/{resource_id}/disable", - permission: "resource:update", - permissions: ["resource:update"], - }, - disableResourceGroup: { - method: "POST", - operationId: API_OPERATIONS.disableResourceGroup, - path: "/v1/admin/resource-groups/{group_id}/disable", - permission: "resource-group:update", - permissions: ["resource-group:update"], - }, - disableResourceShopItem: { - method: "POST", - operationId: API_OPERATIONS.disableResourceShopItem, - path: "/v1/admin/resource-shop/items/{shop_item_id}/disable", - permission: "resource-shop:update", - permissions: ["resource-shop:update"], - }, - enableCountry: { - method: "POST", - operationId: API_OPERATIONS.enableCountry, - path: "/v1/admin/countries/{country_id}/enable", - permission: "country:status", - permissions: ["country:status"], - }, - enableGift: { - method: "POST", - operationId: API_OPERATIONS.enableGift, - path: "/v1/admin/gifts/{gift_id}/enable", - permission: "gift:status", - permissions: ["gift:status"], - }, - enableRegion: { - method: "POST", - operationId: API_OPERATIONS.enableRegion, - path: "/v1/admin/regions/{region_id}/enable", - permission: "region:status", - permissions: ["region:status"], - }, - enableResource: { - method: "POST", - operationId: API_OPERATIONS.enableResource, - path: "/v1/admin/resources/{resource_id}/enable", - permission: "resource:update", - permissions: ["resource:update"], - }, - enableResourceGroup: { - method: "POST", - operationId: API_OPERATIONS.enableResourceGroup, - path: "/v1/admin/resource-groups/{group_id}/enable", - permission: "resource-group:update", - permissions: ["resource-group:update"], - }, - enableResourceShopItem: { - method: "POST", - operationId: API_OPERATIONS.enableResourceShopItem, - path: "/v1/admin/resource-shop/items/{shop_item_id}/enable", - permission: "resource-shop:update", - permissions: ["resource-shop:update"], - }, - expireRoomRpsChallenge: { - method: "POST", - operationId: API_OPERATIONS.expireRoomRpsChallenge, - path: "/v1/admin/game/room-rps/challenges/{challenge_id}/expire", - permission: "game:update", - permissions: ["game:update"], - }, - exportLoginLogs: { - method: "GET", - operationId: API_OPERATIONS.exportLoginLogs, - path: "/v1/logs/login/export", - permission: "log:export", - permissions: ["log:export"], - }, - exportOperationLogs: { - method: "GET", - operationId: API_OPERATIONS.exportOperationLogs, - path: "/v1/logs/operations/export", - permission: "log:export", - permissions: ["log:export"], - }, - exportUsers: { - method: "GET", - operationId: API_OPERATIONS.exportUsers, - path: "/v1/users/export", - permission: "user:export", - permissions: ["user:export"], - }, - generateDiceRobots: { - method: "POST", - operationId: API_OPERATIONS.generateDiceRobots, - path: "/v1/admin/game/robots/generate", - permission: "game:create", - permissions: ["game:create"], - }, - generatePrettyIds: { - method: "POST", - operationId: API_OPERATIONS.generatePrettyIds, - path: "/v1/admin/users/pretty-id-pools/{pool_id}/generate", - permission: "pretty-id:generate", - permissions: ["pretty-id:generate"], - }, - getCoinSellerSalaryRates: { - method: "GET", - operationId: API_OPERATIONS.getCoinSellerSalaryRates, - path: "/v1/admin/coin-seller-salary-rates/{region_id}", - permission: "coin-seller:exchange-rate", - permissions: ["coin-seller:exchange-rate"], - }, - getCountry: { - method: "GET", - operationId: API_OPERATIONS.getCountry, - path: "/v1/admin/countries/{country_id}", - permission: "country:view", - permissions: ["country:view"], - }, - getCPConfig: { - method: "GET", - operationId: API_OPERATIONS.getCPConfig, - path: "/v1/admin/activity/cp/config", - permission: "cp-config:view", - permissions: ["cp-config:view"], - }, - getCPWeeklyRankConfig: { - method: "GET", - operationId: API_OPERATIONS.getCPWeeklyRankConfig, - path: "/v1/admin/activity/cp-weekly-rank/config", - permission: "cp-weekly-rank:view", - permissions: ["cp-weekly-rank:view"], - }, - getCumulativeRechargeRewardConfig: { - method: "GET", - operationId: API_OPERATIONS.getCumulativeRechargeRewardConfig, - path: "/v1/admin/activity/cumulative-recharge-reward/config", - permission: "cumulative-recharge-reward:view", - permissions: ["cumulative-recharge-reward:view"], - }, - getFirstRechargeRewardConfig: { - method: "GET", - operationId: API_OPERATIONS.getFirstRechargeRewardConfig, - path: "/v1/admin/activity/first-recharge-reward/config", - permission: "first-recharge-reward:view", - permissions: ["first-recharge-reward:view"], - }, - getHumanRoomRobotConfig: { - method: "GET", - operationId: API_OPERATIONS.getHumanRoomRobotConfig, - path: "/v1/admin/rooms/robot-rooms/human-config", - permission: "room-robot:view", - permissions: ["room-robot:view"], - }, - getInviteActivityRewardConfig: { - method: "GET", - operationId: API_OPERATIONS.getInviteActivityRewardConfig, - path: "/v1/admin/activity/invite-reward/config", - permission: "invite-activity-reward:view", - permissions: ["invite-activity-reward:view"], - }, - getLuckyGiftConfig: { - method: "GET", - operationId: API_OPERATIONS.getLuckyGiftConfig, - path: "/v1/admin/activity/lucky-gifts/v2/config", - permission: "lucky-gift:view", - permissions: ["lucky-gift:view"], - }, - getLuckyGiftDrawSummary: { - method: "GET", - operationId: API_OPERATIONS.getLuckyGiftDrawSummary, - path: "/v1/admin/activity/lucky-gifts/v2/draw-summary", - permission: "lucky-gift:view", - permissions: ["lucky-gift:view"], - }, - getRedPacket: { - method: "GET", - operationId: API_OPERATIONS.getRedPacket, - path: "/v1/admin/activity/red-packets/{packet_id}", - permission: "red-packet:view", - permissions: ["red-packet:view"], - }, - getRedPacketConfig: { - method: "GET", - operationId: API_OPERATIONS.getRedPacketConfig, - path: "/v1/admin/activity/red-packets/config", - permission: "red-packet:view", - permissions: ["red-packet:view"], - }, - getRegion: { - method: "GET", - operationId: API_OPERATIONS.getRegion, - path: "/v1/admin/regions/{region_id}", - permission: "region:view", - permissions: ["region:view"], - }, - getRegistrationRewardConfig: { - method: "GET", - operationId: API_OPERATIONS.getRegistrationRewardConfig, - path: "/v1/admin/activity/registration-reward/config", - permission: "registration-reward:view", - permissions: ["registration-reward:view"], - }, - getResource: { - method: "GET", - operationId: API_OPERATIONS.getResource, - path: "/v1/admin/resources/{resource_id}", - permission: "resource:view", - permissions: ["resource:view"], - }, - getResourceGroup: { - method: "GET", - operationId: API_OPERATIONS.getResourceGroup, - path: "/v1/admin/resource-groups/{group_id}", - permission: "resource-group:view", - permissions: ["resource-group:view"], - }, - getResourceIdentityAutoGrantConfig: { - method: "GET", - operationId: API_OPERATIONS.getResourceIdentityAutoGrantConfig, - path: "/v1/admin/resource-groups/identity-auto-grant-config", - permission: "resource-group:view", - permissions: ["resource-group:view"], - }, - getRiskConfig: { - method: "GET", - operationId: API_OPERATIONS.getRiskConfig, - path: "/v1/admin/users/risk-config", - permission: "risk-config:view", - permissions: ["risk-config:view"], - }, - getRoleDataScopes: { - method: "GET", - operationId: API_OPERATIONS.getRoleDataScopes, - path: "/v1/roles/{id}/data-scopes", - permission: "role:data-scope", - permissions: ["role:data-scope"], - }, - getRoomConfig: { - method: "GET", - operationId: API_OPERATIONS.getRoomConfig, - path: "/v1/admin/rooms/config", - permission: "room-config:view", - permissions: ["room-config:view"], - }, - getRoomRocketConfig: { - method: "GET", - operationId: API_OPERATIONS.getRoomRocketConfig, - path: "/v1/admin/activity/room-rocket/config", - permission: "room-rocket:view", - permissions: ["room-rocket:view"], - }, - getRoomRpsChallenge: { - method: "GET", - operationId: API_OPERATIONS.getRoomRpsChallenge, - path: "/v1/admin/game/room-rps/challenges/{challenge_id}", - permission: "game:view", - permissions: ["game:view"], - }, - getRoomRpsConfig: { - method: "GET", - operationId: API_OPERATIONS.getRoomRpsConfig, - path: "/v1/admin/game/room-rps/config", - permission: "game:view", - permissions: ["game:view"], - }, - getRoomTurnoverRewardConfig: { - method: "GET", - operationId: API_OPERATIONS.getRoomTurnoverRewardConfig, - path: "/v1/admin/activity/room-turnover-reward/config", - permission: "room-turnover-reward:view", - permissions: ["room-turnover-reward:view"], - }, - getRoomWhitelistConfig: { - method: "GET", - operationId: API_OPERATIONS.getRoomWhitelistConfig, - path: "/v1/admin/rooms/whitelist", - permission: "room-whitelist:view", - permissions: ["room-whitelist:view"], - }, - getSevenDayCheckInConfig: { - method: "GET", - operationId: API_OPERATIONS.getSevenDayCheckInConfig, - path: "/v1/admin/activity/seven-day-checkin/config", - permission: "seven-day-checkin:view", - permissions: ["seven-day-checkin:view"], - }, - getTemporaryPaymentLink: { - method: "GET", - operationId: API_OPERATIONS.getTemporaryPaymentLink, - path: "/v1/admin/payment/temporary-links/{order_id}", - permission: "payment-temporary-link:view", - permissions: ["payment-temporary-link:view"], - }, - getUser: { - method: "GET", - operationId: API_OPERATIONS.getUser, - path: "/v1/users/{id}", - permission: "user:view", - permissions: ["user:view"], - }, - getWeeklyStarCycle: { - method: "GET", - operationId: API_OPERATIONS.getWeeklyStarCycle, - path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}", - permission: "weekly-star:view", - permissions: ["weekly-star:view"], - }, - getWheelConfig: { - method: "GET", - operationId: API_OPERATIONS.getWheelConfig, - path: "/v1/admin/activity/wheel/config", - permission: "wheel:view", - permissions: ["wheel:view"], - }, - getWheelDrawSummary: { - method: "GET", - operationId: API_OPERATIONS.getWheelDrawSummary, - path: "/v1/admin/activity/wheel/draw-summary", - permission: "wheel:view", - permissions: ["wheel:view"], - }, - grantPrettyId: { - method: "POST", - operationId: API_OPERATIONS.grantPrettyId, - path: "/v1/admin/users/pretty-ids/grant", - permission: "pretty-id:grant", - permissions: ["pretty-id:grant"], - }, - grantResource: { - method: "POST", - operationId: API_OPERATIONS.grantResource, - path: "/v1/admin/resource-grants/resource", - permission: "resource-grant:create", - permissions: ["resource-grant:create"], - }, - grantResourceGroup: { - method: "POST", - operationId: API_OPERATIONS.grantResourceGroup, - path: "/v1/admin/resource-grants/group", - permission: "resource-grant:create", - permissions: ["resource-grant:create"], - }, - listAchievementDefinitions: { - method: "GET", - operationId: API_OPERATIONS.listAchievementDefinitions, - path: "/v1/admin/activity/achievements", - permission: "achievement:view", - permissions: ["achievement:view"], - }, - listAgencies: { - method: "GET", - operationId: API_OPERATIONS.listAgencies, - path: "/v1/admin/agencies", - permission: "agency:view", - permissions: ["agency:view"], - }, - listApps: { - method: "GET", - operationId: API_OPERATIONS.listApps, - path: "/v1/admin/apps", - }, - listAppVersions: { - method: "GET", - operationId: API_OPERATIONS.listAppVersions, - path: "/v1/admin/app-config/versions", - permission: "app-version:view", - permissions: ["app-version:view"], - }, - listAvailableRoomRobots: { - method: "GET", - operationId: API_OPERATIONS.listAvailableRoomRobots, - path: "/v1/admin/rooms/robot-rooms/available-robots", - permission: "room-robot:view", - permissions: ["room-robot:view"], - }, - listBanners: { - method: "GET", - operationId: API_OPERATIONS.listBanners, - path: "/v1/admin/app-config/banners", - permission: "app-config:view", - permissions: ["app-config:view"], - }, - listBDLeaders: { - method: "GET", - operationId: API_OPERATIONS.listBDLeaders, - path: "/v1/admin/bd-leaders", - permission: "bd:view", - permissions: ["bd:view"], - }, - listBDs: { - method: "GET", - operationId: API_OPERATIONS.listBDs, - path: "/v1/admin/bds", - permission: "bd:view", - permissions: ["bd:view"], - }, - listCatalog: { - method: "GET", - operationId: API_OPERATIONS.listCatalog, - path: "/v1/admin/game/games", - permission: "game:view", - permissions: ["game:view"], - }, - listCoinAdjustments: { - method: "GET", - operationId: API_OPERATIONS.listCoinAdjustments, - path: "/v1/admin/operations/coin-adjustments", - permission: "coin-adjustment:view", - permissions: ["coin-adjustment:view"], - }, - listCoinLedger: { - method: "GET", - operationId: API_OPERATIONS.listCoinLedger, - path: "/v1/admin/operations/coin-ledger", - permission: "coin-ledger:view", - permissions: ["coin-ledger:view"], - }, - listCoinSellerLedger: { - method: "GET", - operationId: API_OPERATIONS.listCoinSellerLedger, - path: "/v1/admin/operations/coin-seller-ledger", - permission: "coin-seller-ledger:view", - permissions: ["coin-seller-ledger:view"], - }, - listCoinSellers: { - method: "GET", - operationId: API_OPERATIONS.listCoinSellers, - path: "/v1/admin/coin-sellers", - permission: "coin-seller:view", - permissions: ["coin-seller:view"], - }, - listCountries: { - method: "GET", - operationId: API_OPERATIONS.listCountries, - path: "/v1/admin/countries", - permission: "country:view", - permissions: ["country:view"], - }, - listCPApplications: { - method: "GET", - operationId: API_OPERATIONS.listCPApplications, - path: "/v1/admin/activity/cp/applications", - permission: "cp-config:view", - permissions: ["cp-config:view"], - }, - listCPRelationships: { - method: "GET", - operationId: API_OPERATIONS.listCPRelationships, - path: "/v1/admin/activity/cp/relationships", - permission: "cp-config:view", - permissions: ["cp-config:view"], - }, - listCPWeeklyRankSettlements: { - method: "GET", - operationId: API_OPERATIONS.listCPWeeklyRankSettlements, - path: "/v1/admin/activity/cp-weekly-rank/settlements", - permission: "cp-weekly-rank:view", - permissions: ["cp-weekly-rank:view"], - }, - listCumulativeRechargeRewardGrants: { - method: "GET", - operationId: API_OPERATIONS.listCumulativeRechargeRewardGrants, - path: "/v1/admin/activity/cumulative-recharge-reward/grants", - permission: "cumulative-recharge-reward:view", - permissions: ["cumulative-recharge-reward:view"], - }, - listDiceRobots: { - method: "GET", - operationId: API_OPERATIONS.listDiceRobots, - path: "/v1/admin/game/robots", - permission: "game:view", - permissions: ["game:view"], - }, - listEmojiPackCategories: { - method: "GET", - operationId: API_OPERATIONS.listEmojiPackCategories, - path: "/v1/admin/emoji-packs/categories", - permission: "emoji-pack:view", - permissions: ["emoji-pack:view"], - }, - listEmojiPacks: { - method: "GET", - operationId: API_OPERATIONS.listEmojiPacks, - path: "/v1/admin/emoji-packs", - permission: "emoji-pack:view", - permissions: ["emoji-pack:view"], - }, - listExploreTabs: { - method: "GET", - operationId: API_OPERATIONS.listExploreTabs, - path: "/v1/admin/app-config/explore-tabs", - permission: "app-config:view", - permissions: ["app-config:view"], - }, - listFirstRechargeRewardClaims: { - method: "GET", - operationId: API_OPERATIONS.listFirstRechargeRewardClaims, - path: "/v1/admin/activity/first-recharge-reward/claims", - permission: "first-recharge-reward:view", - permissions: ["first-recharge-reward:view"], - }, - listGifts: { - method: "GET", - operationId: API_OPERATIONS.listGifts, - path: "/v1/admin/gifts", - permission: "gift:view", - permissions: ["gift:view"], - }, - listGiftTypes: { - method: "GET", - operationId: API_OPERATIONS.listGiftTypes, - path: "/v1/admin/gift-types", - permission: "gift:view", - permissions: ["gift:view"], - }, - listH5Links: { - method: "GET", - operationId: API_OPERATIONS.listH5Links, - path: "/v1/admin/app-config/h5-links", - permission: "app-config:view", - permissions: ["app-config:view"], - }, - listHostAgencyPolicies: { - method: "GET", - operationId: API_OPERATIONS.listHostAgencyPolicies, - path: "/v1/admin/host-agency-policies", - permission: "host-agency-policy:view", - permissions: ["host-agency-policy:view"], - }, - listHosts: { - method: "GET", - operationId: API_OPERATIONS.listHosts, - path: "/v1/admin/hosts", - permission: "host:view", - permissions: ["host:view"], - }, - listHostSalarySettlements: { - method: "GET", - operationId: API_OPERATIONS.listHostSalarySettlements, - path: "/v1/admin/host-salary-settlements", - permission: "host-salary-settlement:view", - permissions: ["host-salary-settlement:view"], - }, - listInviteActivityRewardClaims: { - method: "GET", - operationId: API_OPERATIONS.listInviteActivityRewardClaims, - path: "/v1/admin/activity/invite-reward/claims", - permission: "invite-activity-reward:view", - permissions: ["invite-activity-reward:view"], - }, - listLevelConfig: { - method: "GET", - operationId: API_OPERATIONS.listLevelConfig, - path: "/v1/admin/users/level-config", - permission: "level-config:view", - permissions: ["level-config:view"], - }, - listLoginLogs: { - method: "GET", - operationId: API_OPERATIONS.listLoginLogs, - path: "/v1/logs/login", - permission: "log:view", - permissions: ["log:view"], - }, - listLuckyGiftConfigs: { - method: "GET", - operationId: API_OPERATIONS.listLuckyGiftConfigs, - path: "/v1/admin/activity/lucky-gifts/v2/configs", - permission: "lucky-gift:view", - permissions: ["lucky-gift:view"], - }, - listLuckyGiftDraws: { - method: "GET", - operationId: API_OPERATIONS.listLuckyGiftDraws, - path: "/v1/admin/activity/lucky-gifts/v2/draws", - permission: "lucky-gift:view", - permissions: ["lucky-gift:view"], - }, - listManagers: { - method: "GET", - operationId: API_OPERATIONS.listManagers, - path: "/v1/admin/managers", - permission: "bd:view", - permissions: ["bd:view"], - }, - listOperationLogs: { - method: "GET", - operationId: API_OPERATIONS.listOperationLogs, - path: "/v1/logs/operations", - permission: "log:view", - permissions: ["log:view"], - }, - listPermissions: { - method: "GET", - operationId: API_OPERATIONS.listPermissions, - path: "/v1/permissions", - permission: "permission:view", - permissions: ["permission:view", "role:permission", "role:manage"], - }, - listPlatforms: { - method: "GET", - operationId: API_OPERATIONS.listPlatforms, - path: "/v1/admin/game/platforms", - permission: "game:view", - permissions: ["game:view"], - }, - listPopups: { - method: "GET", - operationId: API_OPERATIONS.listPopups, - path: "/v1/admin/app-config/popups", - permission: "app-config:view", - permissions: ["app-config:view"], - }, - listPrettyIdPools: { - method: "GET", - operationId: API_OPERATIONS.listPrettyIdPools, - path: "/v1/admin/users/pretty-id-pools", - permission: "pretty-id:view", - permissions: ["pretty-id:view"], - }, - listPrettyIds: { - method: "GET", - operationId: API_OPERATIONS.listPrettyIds, - path: "/v1/admin/users/pretty-ids", - permission: "pretty-id:view", - permissions: ["pretty-id:view"], - }, - listRechargeBills: { - method: "GET", - operationId: API_OPERATIONS.listRechargeBills, - path: "/v1/admin/payment/recharge-bills", - permission: "payment-bill:view", - permissions: ["payment-bill:view"], - }, - listRechargeProducts: { - method: "GET", - operationId: API_OPERATIONS.listRechargeProducts, - path: "/v1/admin/payment/recharge-products", - permission: "payment-product:view", - permissions: ["payment-product:view"], - }, - listRedPackets: { - method: "GET", - operationId: API_OPERATIONS.listRedPackets, - path: "/v1/admin/activity/red-packets", - permission: "red-packet:view", - permissions: ["red-packet:view"], - }, - listRegionBlocks: { - method: "GET", - operationId: API_OPERATIONS.listRegionBlocks, - path: "/v1/admin/users/region-blocks", - permission: "region-block:view", - permissions: ["region-block:view"], - }, - listRegions: { - method: "GET", - operationId: API_OPERATIONS.listRegions, - path: "/v1/admin/regions", - permission: "region:view", - permissions: ["region:view"], - }, - listRegistrationRewardClaims: { - method: "GET", - operationId: API_OPERATIONS.listRegistrationRewardClaims, - path: "/v1/admin/activity/registration-reward/claims", - permission: "registration-reward:view", - permissions: ["registration-reward:view"], - }, - listReports: { - method: "GET", - operationId: API_OPERATIONS.listReports, - path: "/v1/admin/operations/reports", - permission: "report:view", - permissions: ["report:view"], - }, - listResourceGrants: { - method: "GET", - operationId: API_OPERATIONS.listResourceGrants, - path: "/v1/admin/resource-grants", - permission: "resource-grant:view", - permissions: ["resource-grant:view"], - }, - listResourceGroups: { - method: "GET", - operationId: API_OPERATIONS.listResourceGroups, - path: "/v1/admin/resource-groups", - permission: "resource-group:view", - permissions: ["resource-group:view"], - }, - listResources: { - method: "GET", - operationId: API_OPERATIONS.listResources, - path: "/v1/admin/resources", - permission: "resource:view", - permissions: ["resource:view"], - }, - listResourceShopItems: { - method: "GET", - operationId: API_OPERATIONS.listResourceShopItems, - path: "/v1/admin/resource-shop/items", - permission: "resource-shop:view", - permissions: ["resource-shop:view"], - }, - listResourceShopPurchaseOrders: { - method: "GET", - operationId: API_OPERATIONS.listResourceShopPurchaseOrders, - path: "/v1/admin/resource-shop/purchase-orders", - permission: "resource-shop:view", - permissions: ["resource-shop:view"], - }, - listRobotRooms: { - method: "GET", - operationId: API_OPERATIONS.listRobotRooms, - path: "/v1/admin/rooms/robot-rooms", - permission: "room-robot:view", - permissions: ["room-robot:view"], - }, - listRoles: { - method: "GET", - operationId: API_OPERATIONS.listRoles, - path: "/v1/roles", - permission: "role:view", - permissions: ["role:view"], - }, - listRoomPins: { - method: "GET", - operationId: API_OPERATIONS.listRoomPins, - path: "/v1/admin/rooms/pins", - permission: "room-pin:view", - permissions: ["room-pin:view"], - }, - listRoomRpsChallenges: { - method: "GET", - operationId: API_OPERATIONS.listRoomRpsChallenges, - path: "/v1/admin/game/room-rps/challenges", - permission: "game:view", - permissions: ["game:view"], - }, - listRooms: { - method: "GET", - operationId: API_OPERATIONS.listRooms, - path: "/v1/admin/rooms", - permission: "room:view", - permissions: ["room:view"], - }, - listRoomTurnoverRewardSettlements: { - method: "GET", - operationId: API_OPERATIONS.listRoomTurnoverRewardSettlements, - path: "/v1/admin/activity/room-turnover-reward/settlements", - permission: "room-turnover-reward:view", - permissions: ["room-turnover-reward:view"], - }, - listSelfGames: { - method: "GET", - operationId: API_OPERATIONS.listSelfGames, - path: "/v1/admin/game/self-games", - permission: "game:view", - permissions: ["game:view"], - }, - listSevenDayCheckInClaims: { - method: "GET", - operationId: API_OPERATIONS.listSevenDayCheckInClaims, - path: "/v1/admin/activity/seven-day-checkin/claims", - permission: "seven-day-checkin:view", - permissions: ["seven-day-checkin:view"], - }, - listSplashScreens: { - method: "GET", - operationId: API_OPERATIONS.listSplashScreens, - path: "/v1/admin/app-config/splash-screens", - permission: "app-config:view", - permissions: ["app-config:view"], - }, - listSystemMenus: { - method: "GET", - operationId: API_OPERATIONS.listSystemMenus, - path: "/v1/system/menus", - permission: "menu:view", - permissions: ["menu:view"], - }, - listTaskDefinitions: { - method: "GET", - operationId: API_OPERATIONS.listTaskDefinitions, - path: "/v1/admin/activity/daily-tasks", - permission: "daily-task:view", - permissions: ["daily-task:view"], - }, - listTeamSalaryPolicies: { - method: "GET", - operationId: API_OPERATIONS.listTeamSalaryPolicies, - path: "/v1/admin/team-salary-policies", - permission: "team-salary-policy:view", - permissions: ["team-salary-policy:view"], - }, - listTemporaryPaymentLinks: { - method: "GET", - operationId: API_OPERATIONS.listTemporaryPaymentLinks, - path: "/v1/admin/payment/temporary-links", - permission: "payment-temporary-link:view", - permissions: ["payment-temporary-link:view"], - }, - listThirdPartyPaymentChannels: { - method: "GET", - operationId: API_OPERATIONS.listThirdPartyPaymentChannels, - path: "/v1/admin/payment/third-party-channels", - permission: "payment-third-party:view", - permissions: ["payment-third-party:view"], - }, - listUserLeaderboards: { - method: "GET", - operationId: API_OPERATIONS.listUserLeaderboards, - path: "/v1/admin/activity/user-leaderboards", - permission: "user-leaderboard:view", - permissions: ["user-leaderboard:view"], - }, - listUsers: { - method: "GET", - operationId: API_OPERATIONS.listUsers, - path: "/v1/users", - permission: "user:view", - permissions: ["user:view"], - }, - listWeeklyStarCycles: { - method: "GET", - operationId: API_OPERATIONS.listWeeklyStarCycles, - path: "/v1/admin/activity/weekly-star/cycles", - permission: "weekly-star:view", - permissions: ["weekly-star:view"], - }, - listWeeklyStarLeaderboard: { - method: "GET", - operationId: API_OPERATIONS.listWeeklyStarLeaderboard, - path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/leaderboard", - permission: "weekly-star:view", - permissions: ["weekly-star:view"], - }, - listWeeklyStarSettlements: { - method: "GET", - operationId: API_OPERATIONS.listWeeklyStarSettlements, - path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/settlements", - permission: "weekly-star:settle", - permissions: ["weekly-star:settle"], - }, - listWheelDraws: { - method: "GET", - operationId: API_OPERATIONS.listWheelDraws, - path: "/v1/admin/activity/wheel/draws", - permission: "wheel:view", - permissions: ["wheel:view"], - }, - login: { - method: "POST", - operationId: API_OPERATIONS.login, - path: "/v1/auth/login", - }, - logout: { - method: "POST", - operationId: API_OPERATIONS.logout, - path: "/v1/auth/logout", - }, - lookupCoinAdjustmentTarget: { - method: "GET", - operationId: API_OPERATIONS.lookupCoinAdjustmentTarget, - path: "/v1/admin/operations/coin-adjustments/target", - permission: "coin-adjustment:create", - permissions: ["coin-adjustment:create"], - }, - lookupResourceGrantTarget: { - method: "GET", - operationId: API_OPERATIONS.lookupResourceGrantTarget, - path: "/v1/admin/resource-grants/target", - permission: "resource-grant:create", - permissions: ["resource-grant:create"], - }, - me: { - method: "GET", - operationId: API_OPERATIONS.me, - path: "/v1/auth/me", - }, - navigationMenus: { - method: "GET", - operationId: API_OPERATIONS.navigationMenus, - path: "/v1/navigation/menus", - }, - publishHostAgencyPolicy: { - method: "POST", - operationId: API_OPERATIONS.publishHostAgencyPolicy, - path: "/v1/admin/host-agency-policies/{policy_id}/publish", - permission: "host-agency-policy:publish", - permissions: ["host-agency-policy:publish"], - }, - refresh: { - method: "POST", - operationId: API_OPERATIONS.refresh, - path: "/v1/auth/refresh", - }, - replaceCoinSellerSalaryRates: { - method: "PUT", - operationId: API_OPERATIONS.replaceCoinSellerSalaryRates, - path: "/v1/admin/coin-seller-salary-rates/{region_id}", - permission: "coin-seller:exchange-rate", - permissions: ["coin-seller:exchange-rate"], - }, - replaceRegionBlocks: { - method: "PUT", - operationId: API_OPERATIONS.replaceRegionBlocks, - path: "/v1/admin/users/region-blocks", - permission: "region-block:update", - permissions: ["region-block:update"], - }, - replaceRegionCountries: { - method: "PUT", - operationId: API_OPERATIONS.replaceRegionCountries, - path: "/v1/admin/regions/{region_id}/countries", - permission: "region:update", - permissions: ["region:update"], - }, - replaceRoleDataScopes: { - method: "PUT", - operationId: API_OPERATIONS.replaceRoleDataScopes, - path: "/v1/roles/{id}/data-scopes", - permission: "role:data-scope", - permissions: ["role:data-scope"], - }, - replaceRolePermissions: { - method: "PUT", - operationId: API_OPERATIONS.replaceRolePermissions, - path: "/v1/roles/{id}/permissions", - permission: "role:permission", - permissions: ["role:permission", "role:manage"], - }, - resetUserPassword: { - method: "POST", - operationId: API_OPERATIONS.resetUserPassword, - path: "/v1/users/{id}/reset-password", - permission: "user:reset-password", - permissions: ["user:reset-password"], - }, - retryRedPacketRefund: { - method: "POST", - operationId: API_OPERATIONS.retryRedPacketRefund, - path: "/v1/admin/activity/red-packets/refund/retry", - permission: "red-packet:update", - permissions: ["red-packet:update"], - }, - retryRoomRpsSettlement: { - method: "POST", - operationId: API_OPERATIONS.retryRoomRpsSettlement, - path: "/v1/admin/game/room-rps/challenges/{challenge_id}/retry-settlement", - permission: "game:update", - permissions: ["game:update"], - }, - retryRoomTurnoverRewardSettlement: { - method: "POST", - operationId: API_OPERATIONS.retryRoomTurnoverRewardSettlement, - path: "/v1/admin/activity/room-turnover-reward/settlements/{settlement_id}/retry", - permission: "room-turnover-reward:retry", - permissions: ["room-turnover-reward:retry"], - }, - revokeResourceGrant: { - method: "POST", - operationId: API_OPERATIONS.revokeResourceGrant, - path: "/v1/admin/resource-grants/{grant_id}/revoke", - permission: "resource-grant:revoke", - permissions: ["resource-grant:revoke"], - }, - search: { - method: "GET", - operationId: API_OPERATIONS.search, - path: "/v1/search", - }, - setAgencyJoinEnabled: { - method: "POST", - operationId: API_OPERATIONS.setAgencyJoinEnabled, - path: "/v1/admin/agencies/{agency_id}/join-enabled", - permission: "agency:status", - permissions: ["agency:status"], - }, - setBDLeaderStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setBDLeaderStatus, - path: "/v1/admin/bd-leaders/{user_id}/status", - permission: "bd:update", - permissions: ["bd:update"], - }, - setBDStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setBDStatus, - path: "/v1/admin/bds/{user_id}/status", - permission: "bd:update", - permissions: ["bd:update"], - }, - setCoinSellerStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setCoinSellerStatus, - path: "/v1/admin/coin-sellers/{user_id}/status", - permission: "coin-seller:update", - permissions: ["coin-seller:update"], - }, - setDiceRobotStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setDiceRobotStatus, - path: "/v1/admin/game/robots/{user_id}/status", - permission: "game:update", - permissions: ["game:update"], - }, - setGameStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setGameStatus, - path: "/v1/admin/game/games/{game_id}/status", - permission: "game:status", - permissions: ["game:status"], - }, - setPrettyIdStatus: { - method: "POST", - operationId: API_OPERATIONS.setPrettyIdStatus, - path: "/v1/admin/users/pretty-ids/{pretty_id}/status", - permission: "pretty-id:update", - permissions: ["pretty-id:update"], - }, - setTaskDefinitionStatus: { - method: "POST", - operationId: API_OPERATIONS.setTaskDefinitionStatus, - path: "/v1/admin/activity/daily-tasks/{task_id}/status", - permission: "daily-task:status", - permissions: ["daily-task:status"], - }, - setThirdPartyPaymentMethodStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setThirdPartyPaymentMethodStatus, - path: "/v1/admin/payment/third-party-methods/{method_id}/status", - permission: "payment-third-party:update", - permissions: ["payment-third-party:update"], - }, - setWeeklyStarCycleStatus: { - method: "PATCH", - operationId: API_OPERATIONS.setWeeklyStarCycleStatus, - path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/status", - permission: "weekly-star:update", - permissions: ["weekly-star:update"], - }, - sortMenus: { - method: "PUT", - operationId: API_OPERATIONS.sortMenus, - path: "/v1/system/menus/sort", - permission: "menu:sort", - permissions: ["menu:sort"], - }, - startRobotRoom: { - method: "POST", - operationId: API_OPERATIONS.startRobotRoom, - path: "/v1/admin/rooms/robot-rooms/{room_id}/start", - permission: "room-robot:update", - permissions: ["room-robot:update"], - }, - stopRobotRoom: { - method: "POST", - operationId: API_OPERATIONS.stopRobotRoom, - path: "/v1/admin/rooms/robot-rooms/{room_id}/stop", - permission: "room-robot:update", - permissions: ["room-robot:update"], - }, - syncPermissions: { - method: "POST", - operationId: API_OPERATIONS.syncPermissions, - path: "/v1/permissions/sync", - permission: "permission:sync", - permissions: ["permission:sync"], - }, - syncThirdPartyPaymentMethods: { - method: "POST", - operationId: API_OPERATIONS.syncThirdPartyPaymentMethods, - path: "/v1/admin/payment/third-party-methods/sync", - permission: "payment-third-party:update", - permissions: ["payment-third-party:update"], - }, - syncThirdPartyPaymentRates: { - method: "POST", - operationId: API_OPERATIONS.syncThirdPartyPaymentRates, - path: "/v1/admin/payment/third-party-rates/sync", - permission: "payment-third-party:update", - permissions: ["payment-third-party:update"], - }, - updateAchievementDefinition: { - method: "PUT", - operationId: API_OPERATIONS.updateAchievementDefinition, - path: "/v1/admin/activity/achievements/{achievement_id}", - permission: "achievement:update", - permissions: ["achievement:update"], - }, - updateAppVersion: { - method: "PUT", - operationId: API_OPERATIONS.updateAppVersion, - path: "/v1/admin/app-config/versions/{version_id}", - permission: "app-version:update", - permissions: ["app-version:update"], - }, - updateBanner: { - method: "PUT", - operationId: API_OPERATIONS.updateBanner, - path: "/v1/admin/app-config/banners/{banner_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updateCatalog: { - method: "PATCH", - operationId: API_OPERATIONS.updateCatalog, - path: "/v1/admin/game/games/{game_id}", - permission: "game:update", - permissions: ["game:update"], - }, - updateCountry: { - method: "PATCH", - operationId: API_OPERATIONS.updateCountry, - path: "/v1/admin/countries/{country_id}", - permission: "country:update", - permissions: ["country:update"], - }, - updateCPConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateCPConfig, - path: "/v1/admin/activity/cp/config", - permission: "cp-config:update", - permissions: ["cp-config:update"], - }, - updateCPWeeklyRankConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateCPWeeklyRankConfig, - path: "/v1/admin/activity/cp-weekly-rank/config", - permission: "cp-weekly-rank:update", - permissions: ["cp-weekly-rank:update"], - }, - updateCumulativeRechargeRewardConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateCumulativeRechargeRewardConfig, - path: "/v1/admin/activity/cumulative-recharge-reward/config", - permission: "cumulative-recharge-reward:update", - permissions: ["cumulative-recharge-reward:update"], - }, - updateDiceConfig: { - method: "PATCH", - operationId: API_OPERATIONS.updateDiceConfig, - path: "/v1/admin/game/self-games/{game_id}/config", - permission: "game:update", - permissions: ["game:update"], - }, - updateExploreTab: { - method: "PUT", - operationId: API_OPERATIONS.updateExploreTab, - path: "/v1/admin/app-config/explore-tabs/{tab_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updateFirstRechargeRewardConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateFirstRechargeRewardConfig, - path: "/v1/admin/activity/first-recharge-reward/config", - permission: "first-recharge-reward:update", - permissions: ["first-recharge-reward:update"], - }, - updateGift: { - method: "PUT", - operationId: API_OPERATIONS.updateGift, - path: "/v1/admin/gifts/{gift_id}", - permission: "gift:update", - permissions: ["gift:update"], - }, - updateGiftType: { - method: "PUT", - operationId: API_OPERATIONS.updateGiftType, - path: "/v1/admin/gift-types/{type_code}", - permission: "gift:update", - permissions: ["gift:update"], - }, - updateGiftTypes: { - method: "PUT", - operationId: API_OPERATIONS.updateGiftTypes, - path: "/v1/admin/gift-types", - permission: "gift:update", - permissions: ["gift:update"], - }, - updateH5Link: { - method: "PUT", - operationId: API_OPERATIONS.updateH5Link, - path: "/v1/admin/app-config/h5-links/{key}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updateH5Links: { - method: "PUT", - operationId: API_OPERATIONS.updateH5Links, - path: "/v1/admin/app-config/h5-links", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updateHostAgencyPolicy: { - method: "PUT", - operationId: API_OPERATIONS.updateHostAgencyPolicy, - path: "/v1/admin/host-agency-policies/{policy_id}", - permission: "host-agency-policy:update", - permissions: ["host-agency-policy:update"], - }, - updateHumanRoomRobotConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateHumanRoomRobotConfig, - path: "/v1/admin/rooms/robot-rooms/human-config", - permission: "room-robot:update", - permissions: ["room-robot:update"], - }, - updateInviteActivityRewardConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateInviteActivityRewardConfig, - path: "/v1/admin/activity/invite-reward/config", - permission: "invite-activity-reward:update", - permissions: ["invite-activity-reward:update"], - }, - updateMenu: { - method: "PATCH", - operationId: API_OPERATIONS.updateMenu, - path: "/v1/system/menus/{id}", - permission: "menu:update", - permissions: ["menu:update"], - }, - updateMenuVisible: { - method: "PATCH", - operationId: API_OPERATIONS.updateMenuVisible, - path: "/v1/system/menus/{id}/visible", - permission: "menu:visible", - permissions: ["menu:visible"], - }, - updatePermission: { - method: "PATCH", - operationId: API_OPERATIONS.updatePermission, - path: "/v1/permissions/{id}", - permission: "permission:update", - permissions: ["permission:update"], - }, - updatePlatform: { - method: "PATCH", - operationId: API_OPERATIONS.updatePlatform, - path: "/v1/admin/game/platforms/{platform_code}", - permission: "game:update", - permissions: ["game:update"], - }, - updatePopup: { - method: "PUT", - operationId: API_OPERATIONS.updatePopup, - path: "/v1/admin/app-config/popups/{popup_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updatePrettyIdPool: { - method: "PUT", - operationId: API_OPERATIONS.updatePrettyIdPool, - path: "/v1/admin/users/pretty-id-pools/{pool_id}", - permission: "pretty-id:update", - permissions: ["pretty-id:update"], - }, - updateRechargeProduct: { - method: "PUT", - operationId: API_OPERATIONS.updateRechargeProduct, - path: "/v1/admin/payment/recharge-products/{product_id}", - permission: "payment-product:update", - permissions: ["payment-product:update"], - }, - updateRedPacketConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRedPacketConfig, - path: "/v1/admin/activity/red-packets/config", - permission: "red-packet:update", - permissions: ["red-packet:update"], - }, - updateRegion: { - method: "PATCH", - operationId: API_OPERATIONS.updateRegion, - path: "/v1/admin/regions/{region_id}", - permission: "region:update", - permissions: ["region:update"], - }, - updateRegistrationRewardConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRegistrationRewardConfig, - path: "/v1/admin/activity/registration-reward/config", - permission: "registration-reward:update", - permissions: ["registration-reward:update"], - }, - updateResource: { - method: "PUT", - operationId: API_OPERATIONS.updateResource, - path: "/v1/admin/resources/{resource_id}", - permission: "resource:update", - permissions: ["resource:update"], - }, - updateResourceGroup: { - method: "PUT", - operationId: API_OPERATIONS.updateResourceGroup, - path: "/v1/admin/resource-groups/{group_id}", - permission: "resource-group:update", - permissions: ["resource-group:update"], - }, - updateResourceGroupItems: { - method: "PUT", - operationId: API_OPERATIONS.updateResourceGroupItems, - path: "/v1/admin/resource-groups/{group_id}/items", - permission: "resource-group:update", - permissions: ["resource-group:update"], - }, - updateResourceIdentityAutoGrantConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateResourceIdentityAutoGrantConfig, - path: "/v1/admin/resource-groups/identity-auto-grant-config", - permission: "resource-group:update", - permissions: ["resource-group:update"], - }, - updateRiskConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRiskConfig, - path: "/v1/admin/users/risk-config", - permission: "risk-config:update", - permissions: ["risk-config:update"], - }, - updateRole: { - method: "PATCH", - operationId: API_OPERATIONS.updateRole, - path: "/v1/roles/{id}", - permission: "role:update", - permissions: ["role:update", "role:manage"], - }, - updateRoom: { - method: "PATCH", - operationId: API_OPERATIONS.updateRoom, - path: "/v1/admin/rooms/{room_id}", - permission: "room:update", - permissions: ["room:update"], - }, - updateRoomConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRoomConfig, - path: "/v1/admin/rooms/config", - permission: "room-config:update", - permissions: ["room-config:update"], - }, - updateRoomRocketConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRoomRocketConfig, - path: "/v1/admin/activity/room-rocket/config", - permission: "room-rocket:update", - permissions: ["room-rocket:update"], - }, - updateRoomRpsConfig: { - method: "PATCH", - operationId: API_OPERATIONS.updateRoomRpsConfig, - path: "/v1/admin/game/room-rps/config", - permission: "game:update", - permissions: ["game:update"], - }, - updateRoomTurnoverRewardConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRoomTurnoverRewardConfig, - path: "/v1/admin/activity/room-turnover-reward/config", - permission: "room-turnover-reward:update", - permissions: ["room-turnover-reward:update"], - }, - updateRoomWhitelistConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateRoomWhitelistConfig, - path: "/v1/admin/rooms/whitelist", - permission: "room-whitelist:update", - permissions: ["room-whitelist:update"], - }, - updateSevenDayCheckInConfig: { - method: "PUT", - operationId: API_OPERATIONS.updateSevenDayCheckInConfig, - path: "/v1/admin/activity/seven-day-checkin/config", - permission: "seven-day-checkin:update", - permissions: ["seven-day-checkin:update"], - }, - updateSplashScreen: { - method: "PUT", - operationId: API_OPERATIONS.updateSplashScreen, - path: "/v1/admin/app-config/splash-screens/{splash_id}", - permission: "app-config:update", - permissions: ["app-config:update"], - }, - updateTaskDefinition: { - method: "PUT", - operationId: API_OPERATIONS.updateTaskDefinition, - path: "/v1/admin/activity/daily-tasks/{task_id}", - permission: "daily-task:update", - permissions: ["daily-task:update"], - }, - updateTeamSalaryPolicy: { - method: "PUT", - operationId: API_OPERATIONS.updateTeamSalaryPolicy, - path: "/v1/admin/team-salary-policies/{policy_id}", - permission: "team-salary-policy:update", - permissions: ["team-salary-policy:update"], - }, - updateThirdPartyPaymentRate: { - method: "PATCH", - operationId: API_OPERATIONS.updateThirdPartyPaymentRate, - path: "/v1/admin/payment/third-party-rates/{method_id}", - permission: "payment-third-party:update", - permissions: ["payment-third-party:update"], - }, - updateTier: { - method: "PUT", - operationId: API_OPERATIONS.updateTier, - path: "/v1/admin/users/level-config/tiers/{tier_id}", - permission: "level-config:update", - permissions: ["level-config:update"], - }, - updateTrack: { - method: "PUT", - operationId: API_OPERATIONS.updateTrack, - path: "/v1/admin/users/level-config/tracks/{track}", - permission: "level-config:update", - permissions: ["level-config:update"], - }, - updateUser: { - method: "PATCH", - operationId: API_OPERATIONS.updateUser, - path: "/v1/users/{id}", - permission: "user:update", - permissions: ["user:update"], - }, - updateUserStatus: { - method: "PATCH", - operationId: API_OPERATIONS.updateUserStatus, - path: "/v1/users/{id}/status", - permission: "user:status", - permissions: ["user:status"], - }, - updateWeeklyStarCycle: { - method: "PUT", - operationId: API_OPERATIONS.updateWeeklyStarCycle, - path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}", - permission: "weekly-star:update", - permissions: ["weekly-star:update"], - }, - uploadFile: { - method: "POST", - operationId: API_OPERATIONS.uploadFile, - path: "/v1/admin/files/upload", - permission: "upload:create", - permissions: ["upload:create"], - }, - uploadImage: { - method: "POST", - operationId: API_OPERATIONS.uploadImage, - path: "/v1/admin/files/image/upload", - permission: "upload:create", - permissions: ["upload:create"], - }, - upsertLuckyGiftConfig: { - method: "PUT", - operationId: API_OPERATIONS.upsertLuckyGiftConfig, - path: "/v1/admin/activity/lucky-gifts/v2/config", - permission: "lucky-gift:update", - permissions: ["lucky-gift:update"], - }, - upsertResourceShopItems: { - method: "POST", - operationId: API_OPERATIONS.upsertResourceShopItems, - path: "/v1/admin/resource-shop/items", - permission: "resource-shop:update", - permissions: ["resource-shop:update"], - }, - upsertRule: { - method: "PUT", - operationId: API_OPERATIONS.upsertRule, - path: "/v1/admin/users/level-config/rules/{track}/{level}", - permission: "level-config:update", - permissions: ["level-config:update"], - }, - upsertWheelConfig: { - method: "PUT", - operationId: API_OPERATIONS.upsertWheelConfig, - path: "/v1/admin/activity/wheel/config", - permission: "wheel:update", - permissions: ["wheel:update"], - }, + adjustDicePool: { + method: "POST", + operationId: API_OPERATIONS.adjustDicePool, + path: "/v1/admin/game/self-games/{game_id}/pool/adjust", + permission: "game:update", + permissions: ["game:update"] + }, + appBanUser: { + method: "POST", + operationId: API_OPERATIONS.appBanUser, + path: "/v1/app/users/{id}/ban", + permission: "app-user:status", + permissions: ["app-user:status"] + }, + appGetUser: { + method: "GET", + operationId: API_OPERATIONS.appGetUser, + path: "/v1/app/users/{id}", + permission: "app-user:view", + permissions: ["app-user:view"] + }, + appListBannedUsers: { + method: "GET", + operationId: API_OPERATIONS.appListBannedUsers, + path: "/v1/app/users/bans", + permission: "app-user:view", + permissions: ["app-user:view"] + }, + appListLoginLogs: { + method: "GET", + operationId: API_OPERATIONS.appListLoginLogs, + path: "/v1/app/users/login-logs", + permission: "app-user:view", + permissions: ["app-user:view"] + }, + appListUserLoginLogs: { + method: "GET", + operationId: API_OPERATIONS.appListUserLoginLogs, + path: "/v1/app/users/{id}/login-logs", + permission: "app-user:view", + permissions: ["app-user:view"] + }, + appListUsers: { + method: "GET", + operationId: API_OPERATIONS.appListUsers, + path: "/v1/app/users", + permission: "app-user:view", + permissions: ["app-user:view"] + }, + appSetPassword: { + method: "POST", + operationId: API_OPERATIONS.appSetPassword, + path: "/v1/app/users/{id}/password", + permission: "app-user:password", + permissions: ["app-user:password"] + }, + appUnbanUser: { + method: "POST", + operationId: API_OPERATIONS.appUnbanUser, + path: "/v1/app/users/{id}/unban", + permission: "app-user:status", + permissions: ["app-user:status"] + }, + appUpdateUser: { + method: "PATCH", + operationId: API_OPERATIONS.appUpdateUser, + path: "/v1/app/users/{id}", + permission: "app-user:update", + permissions: ["app-user:update"] + }, + batchUpdateUserStatus: { + method: "POST", + operationId: API_OPERATIONS.batchUpdateUserStatus, + path: "/v1/users/batch/status", + permission: "user:status", + permissions: ["user:status"] + }, + cancelRoomPin: { + method: "DELETE", + operationId: API_OPERATIONS.cancelRoomPin, + path: "/v1/admin/rooms/pins/{pin_id}", + permission: "room-pin:cancel", + permissions: ["room-pin:cancel"] + }, + changePassword: { + method: "POST", + operationId: API_OPERATIONS.changePassword, + path: "/v1/auth/change-password" + }, + closeAgency: { + method: "POST", + operationId: API_OPERATIONS.closeAgency, + path: "/v1/admin/agencies/{agency_id}/close", + permission: "agency:status", + permissions: ["agency:status"] + }, + createAchievementDefinition: { + method: "POST", + operationId: API_OPERATIONS.createAchievementDefinition, + path: "/v1/admin/activity/achievements", + permission: "achievement:create", + permissions: ["achievement:create"] + }, + createAgency: { + method: "POST", + operationId: API_OPERATIONS.createAgency, + path: "/v1/admin/agencies", + permission: "agency:create", + permissions: ["agency:create"] + }, + createAppVersion: { + method: "POST", + operationId: API_OPERATIONS.createAppVersion, + path: "/v1/admin/app-config/versions", + permission: "app-version:create", + permissions: ["app-version:create"] + }, + createBanner: { + method: "POST", + operationId: API_OPERATIONS.createBanner, + path: "/v1/admin/app-config/banners", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + createBD: { + method: "POST", + operationId: API_OPERATIONS.createBD, + path: "/v1/admin/bds", + permission: "bd:create", + permissions: ["bd:create"] + }, + createBDLeader: { + method: "POST", + operationId: API_OPERATIONS.createBDLeader, + path: "/v1/admin/bd-leaders", + permission: "bd:create", + permissions: ["bd:create"] + }, + createCatalog: { + method: "POST", + operationId: API_OPERATIONS.createCatalog, + path: "/v1/admin/game/games", + permission: "game:create", + permissions: ["game:create"] + }, + createCoinAdjustment: { + method: "POST", + operationId: API_OPERATIONS.createCoinAdjustment, + path: "/v1/admin/operations/coin-adjustments", + permission: "coin-adjustment:create", + permissions: ["coin-adjustment:create"] + }, + createCoinSeller: { + method: "POST", + operationId: API_OPERATIONS.createCoinSeller, + path: "/v1/admin/coin-sellers", + permission: "coin-seller:create", + permissions: ["coin-seller:create"] + }, + createCountry: { + method: "POST", + operationId: API_OPERATIONS.createCountry, + path: "/v1/admin/countries", + permission: "country:create", + permissions: ["country:create"] + }, + createEmojiPack: { + method: "POST", + operationId: API_OPERATIONS.createEmojiPack, + path: "/v1/admin/emoji-packs", + permission: "emoji-pack:create", + permissions: ["emoji-pack:create"] + }, + createExploreTab: { + method: "POST", + operationId: API_OPERATIONS.createExploreTab, + path: "/v1/admin/app-config/explore-tabs", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + createFullServerNoticeFanout: { + method: "POST", + operationId: API_OPERATIONS.createFullServerNoticeFanout, + path: "/v1/admin/operations/full-server-notices/fanout", + permission: "full-server-notice:send", + permissions: ["full-server-notice:send"] + }, + createGift: { + method: "POST", + operationId: API_OPERATIONS.createGift, + path: "/v1/admin/gifts", + permission: "gift:create", + permissions: ["gift:create"] + }, + createH5Link: { + method: "POST", + operationId: API_OPERATIONS.createH5Link, + path: "/v1/admin/app-config/h5-links", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + createHostAgencyPolicy: { + method: "POST", + operationId: API_OPERATIONS.createHostAgencyPolicy, + path: "/v1/admin/host-agency-policies", + permission: "host-agency-policy:create", + permissions: ["host-agency-policy:create"] + }, + createManager: { + method: "POST", + operationId: API_OPERATIONS.createManager, + path: "/v1/admin/managers", + permission: "bd:create", + permissions: ["bd:create"] + }, + createMenu: { + method: "POST", + operationId: API_OPERATIONS.createMenu, + path: "/v1/system/menus", + permission: "menu:create", + permissions: ["menu:create"] + }, + createPermission: { + method: "POST", + operationId: API_OPERATIONS.createPermission, + path: "/v1/permissions", + permission: "permission:create", + permissions: ["permission:create"] + }, + createPlatform: { + method: "POST", + operationId: API_OPERATIONS.createPlatform, + path: "/v1/admin/game/platforms", + permission: "game:update", + permissions: ["game:update"] + }, + createPopup: { + method: "POST", + operationId: API_OPERATIONS.createPopup, + path: "/v1/admin/app-config/popups", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + createPrettyIdPool: { + method: "POST", + operationId: API_OPERATIONS.createPrettyIdPool, + path: "/v1/admin/users/pretty-id-pools", + permission: "pretty-id:update", + permissions: ["pretty-id:update"] + }, + createRechargeProduct: { + method: "POST", + operationId: API_OPERATIONS.createRechargeProduct, + path: "/v1/admin/payment/recharge-products", + permission: "payment-product:create", + permissions: ["payment-product:create"] + }, + createRegion: { + method: "POST", + operationId: API_OPERATIONS.createRegion, + path: "/v1/admin/regions", + permission: "region:create", + permissions: ["region:create"] + }, + createResource: { + method: "POST", + operationId: API_OPERATIONS.createResource, + path: "/v1/admin/resources", + permission: "resource:create", + permissions: ["resource:create"] + }, + createResourceGroup: { + method: "POST", + operationId: API_OPERATIONS.createResourceGroup, + path: "/v1/admin/resource-groups", + permission: "resource-group:create", + permissions: ["resource-group:create"] + }, + createRobotRoom: { + method: "POST", + operationId: API_OPERATIONS.createRobotRoom, + path: "/v1/admin/rooms/robot-rooms", + permission: "room-robot:create", + permissions: ["room-robot:create"] + }, + createRole: { + method: "POST", + operationId: API_OPERATIONS.createRole, + path: "/v1/roles", + permission: "role:create", + permissions: ["role:create","role:manage"] + }, + createRoomPin: { + method: "POST", + operationId: API_OPERATIONS.createRoomPin, + path: "/v1/admin/rooms/pins", + permission: "room-pin:create", + permissions: ["room-pin:create"] + }, + createSplashScreen: { + method: "POST", + operationId: API_OPERATIONS.createSplashScreen, + path: "/v1/admin/app-config/splash-screens", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + createTaskDefinition: { + method: "POST", + operationId: API_OPERATIONS.createTaskDefinition, + path: "/v1/admin/activity/daily-tasks", + permission: "daily-task:create", + permissions: ["daily-task:create"] + }, + createTeamSalaryPolicy: { + method: "POST", + operationId: API_OPERATIONS.createTeamSalaryPolicy, + path: "/v1/admin/team-salary-policies", + permission: "team-salary-policy:create", + permissions: ["team-salary-policy:create"] + }, + createTemporaryPaymentLink: { + method: "POST", + operationId: API_OPERATIONS.createTemporaryPaymentLink, + path: "/v1/admin/payment/temporary-links", + permission: "money:payment-link:create", + permissions: ["money:payment-link:create"] + }, + createTier: { + method: "POST", + operationId: API_OPERATIONS.createTier, + path: "/v1/admin/users/level-config/tiers", + permission: "level-config:update", + permissions: ["level-config:update"] + }, + createUser: { + method: "POST", + operationId: API_OPERATIONS.createUser, + path: "/v1/users", + permission: "user:create", + permissions: ["user:create"] + }, + createWeeklyStarCycle: { + method: "POST", + operationId: API_OPERATIONS.createWeeklyStarCycle, + path: "/v1/admin/activity/weekly-star/cycles", + permission: "weekly-star:create", + permissions: ["weekly-star:create"] + }, + creditCoinSellerStock: { + method: "POST", + operationId: API_OPERATIONS.creditCoinSellerStock, + path: "/v1/admin/coin-sellers/{user_id}/stock-credits", + permission: "coin-seller:stock-credit", + permissions: ["coin-seller:stock-credit"] + }, + dashboardOverview: { + method: "GET", + operationId: API_OPERATIONS.dashboardOverview, + path: "/v1/dashboard/overview", + permission: "overview:view", + permissions: ["overview:view"] + }, + debitCoinSellerStock: { + method: "POST", + operationId: API_OPERATIONS.debitCoinSellerStock, + path: "/v1/admin/coin-sellers/{user_id}/stock-debits", + permission: "coin-seller:stock-credit", + permissions: ["coin-seller:stock-credit"] + }, + deleteAchievementDefinition: { + method: "DELETE", + operationId: API_OPERATIONS.deleteAchievementDefinition, + path: "/v1/admin/activity/achievements/{achievement_id}", + permission: "achievement:update", + permissions: ["achievement:update"] + }, + deleteAgency: { + method: "POST", + operationId: API_OPERATIONS.deleteAgency, + path: "/v1/admin/agencies/{agency_id}/delete", + permission: "agency:delete", + permissions: ["agency:delete"] + }, + deleteAppVersion: { + method: "DELETE", + operationId: API_OPERATIONS.deleteAppVersion, + path: "/v1/admin/app-config/versions/{version_id}", + permission: "app-version:delete", + permissions: ["app-version:delete"] + }, + deleteBanner: { + method: "DELETE", + operationId: API_OPERATIONS.deleteBanner, + path: "/v1/admin/app-config/banners/{banner_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + deleteBDLeader: { + method: "DELETE", + operationId: API_OPERATIONS.deleteBDLeader, + path: "/v1/admin/bd-leaders/{user_id}", + permission: "bd:update", + permissions: ["bd:update"] + }, + deleteCatalog: { + method: "DELETE", + operationId: API_OPERATIONS.deleteCatalog, + path: "/v1/admin/game/games/{game_id}", + permission: "game:delete", + permissions: ["game:delete"] + }, + deleteCountry: { + method: "DELETE", + operationId: API_OPERATIONS.deleteCountry, + path: "/v1/admin/countries/{country_id}", + permission: "country:status", + permissions: ["country:status"] + }, + deleteDiceRobot: { + method: "DELETE", + operationId: API_OPERATIONS.deleteDiceRobot, + path: "/v1/admin/game/robots/{user_id}", + permission: "game:delete", + permissions: ["game:delete"] + }, + deleteExploreTab: { + method: "DELETE", + operationId: API_OPERATIONS.deleteExploreTab, + path: "/v1/admin/app-config/explore-tabs/{tab_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + deleteGift: { + method: "DELETE", + operationId: API_OPERATIONS.deleteGift, + path: "/v1/admin/gifts/{gift_id}", + permission: "gift:delete", + permissions: ["gift:delete"] + }, + deleteH5Link: { + method: "DELETE", + operationId: API_OPERATIONS.deleteH5Link, + path: "/v1/admin/app-config/h5-links/{key}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + deleteHostAgencyPolicy: { + method: "DELETE", + operationId: API_OPERATIONS.deleteHostAgencyPolicy, + path: "/v1/admin/host-agency-policies/{policy_id}", + permission: "host-agency-policy:delete", + permissions: ["host-agency-policy:delete"] + }, + deleteMenu: { + method: "DELETE", + operationId: API_OPERATIONS.deleteMenu, + path: "/v1/system/menus/{id}", + permission: "menu:delete", + permissions: ["menu:delete"] + }, + deletePermission: { + method: "DELETE", + operationId: API_OPERATIONS.deletePermission, + path: "/v1/permissions/{id}", + permission: "permission:delete", + permissions: ["permission:delete"] + }, + deletePopup: { + method: "DELETE", + operationId: API_OPERATIONS.deletePopup, + path: "/v1/admin/app-config/popups/{popup_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + deleteRechargeProduct: { + method: "DELETE", + operationId: API_OPERATIONS.deleteRechargeProduct, + path: "/v1/admin/payment/recharge-products/{product_id}", + permission: "payment-product:delete", + permissions: ["payment-product:delete"] + }, + deleteRole: { + method: "DELETE", + operationId: API_OPERATIONS.deleteRole, + path: "/v1/roles/{id}", + permission: "role:delete", + permissions: ["role:delete","role:manage"] + }, + deleteRoom: { + method: "DELETE", + operationId: API_OPERATIONS.deleteRoom, + path: "/v1/admin/rooms/{room_id}", + permission: "room:delete", + permissions: ["room:delete"] + }, + deleteSplashScreen: { + method: "DELETE", + operationId: API_OPERATIONS.deleteSplashScreen, + path: "/v1/admin/app-config/splash-screens/{splash_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + deleteTeamSalaryPolicy: { + method: "DELETE", + operationId: API_OPERATIONS.deleteTeamSalaryPolicy, + path: "/v1/admin/team-salary-policies/{policy_id}", + permission: "team-salary-policy:delete", + permissions: ["team-salary-policy:delete"] + }, + disableCountry: { + method: "POST", + operationId: API_OPERATIONS.disableCountry, + path: "/v1/admin/countries/{country_id}/disable", + permission: "country:status", + permissions: ["country:status"] + }, + disableGift: { + method: "POST", + operationId: API_OPERATIONS.disableGift, + path: "/v1/admin/gifts/{gift_id}/disable", + permission: "gift:status", + permissions: ["gift:status"] + }, + disableRegion: { + method: "DELETE", + operationId: API_OPERATIONS.disableRegion, + path: "/v1/admin/regions/{region_id}", + permission: "region:status", + permissions: ["region:status"] + }, + disableResource: { + method: "POST", + operationId: API_OPERATIONS.disableResource, + path: "/v1/admin/resources/{resource_id}/disable", + permission: "resource:update", + permissions: ["resource:update"] + }, + disableResourceGroup: { + method: "POST", + operationId: API_OPERATIONS.disableResourceGroup, + path: "/v1/admin/resource-groups/{group_id}/disable", + permission: "resource-group:update", + permissions: ["resource-group:update"] + }, + disableResourceShopItem: { + method: "POST", + operationId: API_OPERATIONS.disableResourceShopItem, + path: "/v1/admin/resource-shop/items/{shop_item_id}/disable", + permission: "resource-shop:update", + permissions: ["resource-shop:update"] + }, + enableCountry: { + method: "POST", + operationId: API_OPERATIONS.enableCountry, + path: "/v1/admin/countries/{country_id}/enable", + permission: "country:status", + permissions: ["country:status"] + }, + enableGift: { + method: "POST", + operationId: API_OPERATIONS.enableGift, + path: "/v1/admin/gifts/{gift_id}/enable", + permission: "gift:status", + permissions: ["gift:status"] + }, + enableRegion: { + method: "POST", + operationId: API_OPERATIONS.enableRegion, + path: "/v1/admin/regions/{region_id}/enable", + permission: "region:status", + permissions: ["region:status"] + }, + enableResource: { + method: "POST", + operationId: API_OPERATIONS.enableResource, + path: "/v1/admin/resources/{resource_id}/enable", + permission: "resource:update", + permissions: ["resource:update"] + }, + enableResourceGroup: { + method: "POST", + operationId: API_OPERATIONS.enableResourceGroup, + path: "/v1/admin/resource-groups/{group_id}/enable", + permission: "resource-group:update", + permissions: ["resource-group:update"] + }, + enableResourceShopItem: { + method: "POST", + operationId: API_OPERATIONS.enableResourceShopItem, + path: "/v1/admin/resource-shop/items/{shop_item_id}/enable", + permission: "resource-shop:update", + permissions: ["resource-shop:update"] + }, + expireRoomRpsChallenge: { + method: "POST", + operationId: API_OPERATIONS.expireRoomRpsChallenge, + path: "/v1/admin/game/room-rps/challenges/{challenge_id}/expire", + permission: "game:update", + permissions: ["game:update"] + }, + exportLoginLogs: { + method: "GET", + operationId: API_OPERATIONS.exportLoginLogs, + path: "/v1/logs/login/export", + permission: "log:export", + permissions: ["log:export"] + }, + exportOperationLogs: { + method: "GET", + operationId: API_OPERATIONS.exportOperationLogs, + path: "/v1/logs/operations/export", + permission: "log:export", + permissions: ["log:export"] + }, + exportUsers: { + method: "GET", + operationId: API_OPERATIONS.exportUsers, + path: "/v1/users/export", + permission: "user:export", + permissions: ["user:export"] + }, + generateDiceRobots: { + method: "POST", + operationId: API_OPERATIONS.generateDiceRobots, + path: "/v1/admin/game/robots/generate", + permission: "game:create", + permissions: ["game:create"] + }, + generatePrettyIds: { + method: "POST", + operationId: API_OPERATIONS.generatePrettyIds, + path: "/v1/admin/users/pretty-id-pools/{pool_id}/generate", + permission: "pretty-id:generate", + permissions: ["pretty-id:generate"] + }, + getCoinSellerSalaryRates: { + method: "GET", + operationId: API_OPERATIONS.getCoinSellerSalaryRates, + path: "/v1/admin/coin-seller-salary-rates/{region_id}", + permission: "coin-seller:exchange-rate", + permissions: ["coin-seller:exchange-rate"] + }, + getCountry: { + method: "GET", + operationId: API_OPERATIONS.getCountry, + path: "/v1/admin/countries/{country_id}", + permission: "country:view", + permissions: ["country:view"] + }, + getCPConfig: { + method: "GET", + operationId: API_OPERATIONS.getCPConfig, + path: "/v1/admin/activity/cp/config", + permission: "cp-config:view", + permissions: ["cp-config:view"] + }, + getCPWeeklyRankConfig: { + method: "GET", + operationId: API_OPERATIONS.getCPWeeklyRankConfig, + path: "/v1/admin/activity/cp-weekly-rank/config", + permission: "cp-weekly-rank:view", + permissions: ["cp-weekly-rank:view"] + }, + getCumulativeRechargeRewardConfig: { + method: "GET", + operationId: API_OPERATIONS.getCumulativeRechargeRewardConfig, + path: "/v1/admin/activity/cumulative-recharge-reward/config", + permission: "cumulative-recharge-reward:view", + permissions: ["cumulative-recharge-reward:view"] + }, + getFirstRechargeRewardConfig: { + method: "GET", + operationId: API_OPERATIONS.getFirstRechargeRewardConfig, + path: "/v1/admin/activity/first-recharge-reward/config", + permission: "first-recharge-reward:view", + permissions: ["first-recharge-reward:view"] + }, + getHumanRoomRobotConfig: { + method: "GET", + operationId: API_OPERATIONS.getHumanRoomRobotConfig, + path: "/v1/admin/rooms/robot-rooms/human-config", + permission: "room-robot:view", + permissions: ["room-robot:view"] + }, + getInviteActivityRewardConfig: { + method: "GET", + operationId: API_OPERATIONS.getInviteActivityRewardConfig, + path: "/v1/admin/activity/invite-reward/config", + permission: "invite-activity-reward:view", + permissions: ["invite-activity-reward:view"] + }, + getLuckyGiftConfig: { + method: "GET", + operationId: API_OPERATIONS.getLuckyGiftConfig, + path: "/v1/admin/activity/lucky-gifts/v2/config", + permission: "lucky-gift:view", + permissions: ["lucky-gift:view"] + }, + getLuckyGiftDrawSummary: { + method: "GET", + operationId: API_OPERATIONS.getLuckyGiftDrawSummary, + path: "/v1/admin/activity/lucky-gifts/v2/draw-summary", + permission: "lucky-gift:view", + permissions: ["lucky-gift:view"] + }, + getMoneyPerformance: { + method: "GET", + operationId: API_OPERATIONS.getMoneyPerformance, + path: "/v1/admin/money/performance", + permission: "money:view", + permissions: ["money:view"] + }, + getMoneyScope: { + method: "GET", + operationId: API_OPERATIONS.getMoneyScope, + path: "/v1/admin/money/scope", + permission: "money:view", + permissions: ["money:view"] + }, + getRedPacket: { + method: "GET", + operationId: API_OPERATIONS.getRedPacket, + path: "/v1/admin/activity/red-packets/{packet_id}", + permission: "red-packet:view", + permissions: ["red-packet:view"] + }, + getRedPacketConfig: { + method: "GET", + operationId: API_OPERATIONS.getRedPacketConfig, + path: "/v1/admin/activity/red-packets/config", + permission: "red-packet:view", + permissions: ["red-packet:view"] + }, + getRegion: { + method: "GET", + operationId: API_OPERATIONS.getRegion, + path: "/v1/admin/regions/{region_id}", + permission: "region:view", + permissions: ["region:view"] + }, + getRegistrationRewardConfig: { + method: "GET", + operationId: API_OPERATIONS.getRegistrationRewardConfig, + path: "/v1/admin/activity/registration-reward/config", + permission: "registration-reward:view", + permissions: ["registration-reward:view"] + }, + getResource: { + method: "GET", + operationId: API_OPERATIONS.getResource, + path: "/v1/admin/resources/{resource_id}", + permission: "resource:view", + permissions: ["resource:view"] + }, + getResourceGroup: { + method: "GET", + operationId: API_OPERATIONS.getResourceGroup, + path: "/v1/admin/resource-groups/{group_id}", + permission: "resource-group:view", + permissions: ["resource-group:view"] + }, + getResourceIdentityAutoGrantConfig: { + method: "GET", + operationId: API_OPERATIONS.getResourceIdentityAutoGrantConfig, + path: "/v1/admin/resource-groups/identity-auto-grant-config", + permission: "resource-group:view", + permissions: ["resource-group:view"] + }, + getRiskConfig: { + method: "GET", + operationId: API_OPERATIONS.getRiskConfig, + path: "/v1/admin/users/risk-config", + permission: "risk-config:view", + permissions: ["risk-config:view"] + }, + getRoleDataScopes: { + method: "GET", + operationId: API_OPERATIONS.getRoleDataScopes, + path: "/v1/roles/{id}/data-scopes", + permission: "role:data-scope", + permissions: ["role:data-scope"] + }, + getRoomConfig: { + method: "GET", + operationId: API_OPERATIONS.getRoomConfig, + path: "/v1/admin/rooms/config", + permission: "room-config:view", + permissions: ["room-config:view"] + }, + getRoomRocketConfig: { + method: "GET", + operationId: API_OPERATIONS.getRoomRocketConfig, + path: "/v1/admin/activity/room-rocket/config", + permission: "room-rocket:view", + permissions: ["room-rocket:view"] + }, + getRoomRpsChallenge: { + method: "GET", + operationId: API_OPERATIONS.getRoomRpsChallenge, + path: "/v1/admin/game/room-rps/challenges/{challenge_id}", + permission: "game:view", + permissions: ["game:view"] + }, + getRoomRpsConfig: { + method: "GET", + operationId: API_OPERATIONS.getRoomRpsConfig, + path: "/v1/admin/game/room-rps/config", + permission: "game:view", + permissions: ["game:view"] + }, + getRoomTurnoverRewardConfig: { + method: "GET", + operationId: API_OPERATIONS.getRoomTurnoverRewardConfig, + path: "/v1/admin/activity/room-turnover-reward/config", + permission: "room-turnover-reward:view", + permissions: ["room-turnover-reward:view"] + }, + getRoomWhitelistConfig: { + method: "GET", + operationId: API_OPERATIONS.getRoomWhitelistConfig, + path: "/v1/admin/rooms/whitelist", + permission: "room-whitelist:view", + permissions: ["room-whitelist:view"] + }, + getSevenDayCheckInConfig: { + method: "GET", + operationId: API_OPERATIONS.getSevenDayCheckInConfig, + path: "/v1/admin/activity/seven-day-checkin/config", + permission: "seven-day-checkin:view", + permissions: ["seven-day-checkin:view"] + }, + getTemporaryPaymentLink: { + method: "GET", + operationId: API_OPERATIONS.getTemporaryPaymentLink, + path: "/v1/admin/payment/temporary-links/{order_id}", + permission: "payment-temporary-link:view", + permissions: ["payment-temporary-link:view","money:view"] + }, + getUser: { + method: "GET", + operationId: API_OPERATIONS.getUser, + path: "/v1/users/{id}", + permission: "user:view", + permissions: ["user:view"] + }, + getWeeklyStarCycle: { + method: "GET", + operationId: API_OPERATIONS.getWeeklyStarCycle, + path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}", + permission: "weekly-star:view", + permissions: ["weekly-star:view"] + }, + getWheelConfig: { + method: "GET", + operationId: API_OPERATIONS.getWheelConfig, + path: "/v1/admin/activity/wheel/config", + permission: "wheel:view", + permissions: ["wheel:view"] + }, + getWheelDrawSummary: { + method: "GET", + operationId: API_OPERATIONS.getWheelDrawSummary, + path: "/v1/admin/activity/wheel/draw-summary", + permission: "wheel:view", + permissions: ["wheel:view"] + }, + grantPrettyId: { + method: "POST", + operationId: API_OPERATIONS.grantPrettyId, + path: "/v1/admin/users/pretty-ids/grant", + permission: "pretty-id:grant", + permissions: ["pretty-id:grant"] + }, + grantResource: { + method: "POST", + operationId: API_OPERATIONS.grantResource, + path: "/v1/admin/resource-grants/resource", + permission: "resource-grant:create", + permissions: ["resource-grant:create"] + }, + grantResourceGroup: { + method: "POST", + operationId: API_OPERATIONS.grantResourceGroup, + path: "/v1/admin/resource-grants/group", + permission: "resource-grant:create", + permissions: ["resource-grant:create"] + }, + listAchievementDefinitions: { + method: "GET", + operationId: API_OPERATIONS.listAchievementDefinitions, + path: "/v1/admin/activity/achievements", + permission: "achievement:view", + permissions: ["achievement:view"] + }, + listAgencies: { + method: "GET", + operationId: API_OPERATIONS.listAgencies, + path: "/v1/admin/agencies", + permission: "agency:view", + permissions: ["agency:view"] + }, + listApps: { + method: "GET", + operationId: API_OPERATIONS.listApps, + path: "/v1/admin/apps" + }, + listAppVersions: { + method: "GET", + operationId: API_OPERATIONS.listAppVersions, + path: "/v1/admin/app-config/versions", + permission: "app-version:view", + permissions: ["app-version:view"] + }, + listAvailableRoomRobots: { + method: "GET", + operationId: API_OPERATIONS.listAvailableRoomRobots, + path: "/v1/admin/rooms/robot-rooms/available-robots", + permission: "room-robot:view", + permissions: ["room-robot:view"] + }, + listBanners: { + method: "GET", + operationId: API_OPERATIONS.listBanners, + path: "/v1/admin/app-config/banners", + permission: "app-config:view", + permissions: ["app-config:view"] + }, + listBDLeaders: { + method: "GET", + operationId: API_OPERATIONS.listBDLeaders, + path: "/v1/admin/bd-leaders", + permission: "bd:view", + permissions: ["bd:view"] + }, + listBDs: { + method: "GET", + operationId: API_OPERATIONS.listBDs, + path: "/v1/admin/bds", + permission: "bd:view", + permissions: ["bd:view"] + }, + listCatalog: { + method: "GET", + operationId: API_OPERATIONS.listCatalog, + path: "/v1/admin/game/games", + permission: "game:view", + permissions: ["game:view"] + }, + listCoinAdjustments: { + method: "GET", + operationId: API_OPERATIONS.listCoinAdjustments, + path: "/v1/admin/operations/coin-adjustments", + permission: "coin-adjustment:view", + permissions: ["coin-adjustment:view"] + }, + listCoinLedger: { + method: "GET", + operationId: API_OPERATIONS.listCoinLedger, + path: "/v1/admin/operations/coin-ledger", + permission: "coin-ledger:view", + permissions: ["coin-ledger:view"] + }, + listCoinSellerLedger: { + method: "GET", + operationId: API_OPERATIONS.listCoinSellerLedger, + path: "/v1/admin/operations/coin-seller-ledger", + permission: "coin-seller-ledger:view", + permissions: ["coin-seller-ledger:view"] + }, + listCoinSellers: { + method: "GET", + operationId: API_OPERATIONS.listCoinSellers, + path: "/v1/admin/coin-sellers", + permission: "coin-seller:view", + permissions: ["coin-seller:view"] + }, + listCountries: { + method: "GET", + operationId: API_OPERATIONS.listCountries, + path: "/v1/admin/countries", + permission: "country:view", + permissions: ["country:view"] + }, + listCPApplications: { + method: "GET", + operationId: API_OPERATIONS.listCPApplications, + path: "/v1/admin/activity/cp/applications", + permission: "cp-config:view", + permissions: ["cp-config:view"] + }, + listCPRelationships: { + method: "GET", + operationId: API_OPERATIONS.listCPRelationships, + path: "/v1/admin/activity/cp/relationships", + permission: "cp-config:view", + permissions: ["cp-config:view"] + }, + listCPWeeklyRankSettlements: { + method: "GET", + operationId: API_OPERATIONS.listCPWeeklyRankSettlements, + path: "/v1/admin/activity/cp-weekly-rank/settlements", + permission: "cp-weekly-rank:view", + permissions: ["cp-weekly-rank:view"] + }, + listCumulativeRechargeRewardGrants: { + method: "GET", + operationId: API_OPERATIONS.listCumulativeRechargeRewardGrants, + path: "/v1/admin/activity/cumulative-recharge-reward/grants", + permission: "cumulative-recharge-reward:view", + permissions: ["cumulative-recharge-reward:view"] + }, + listDiceRobots: { + method: "GET", + operationId: API_OPERATIONS.listDiceRobots, + path: "/v1/admin/game/robots", + permission: "game:view", + permissions: ["game:view"] + }, + listEmojiPackCategories: { + method: "GET", + operationId: API_OPERATIONS.listEmojiPackCategories, + path: "/v1/admin/emoji-packs/categories", + permission: "emoji-pack:view", + permissions: ["emoji-pack:view"] + }, + listEmojiPacks: { + method: "GET", + operationId: API_OPERATIONS.listEmojiPacks, + path: "/v1/admin/emoji-packs", + permission: "emoji-pack:view", + permissions: ["emoji-pack:view"] + }, + listExploreTabs: { + method: "GET", + operationId: API_OPERATIONS.listExploreTabs, + path: "/v1/admin/app-config/explore-tabs", + permission: "app-config:view", + permissions: ["app-config:view"] + }, + listFirstRechargeRewardClaims: { + method: "GET", + operationId: API_OPERATIONS.listFirstRechargeRewardClaims, + path: "/v1/admin/activity/first-recharge-reward/claims", + permission: "first-recharge-reward:view", + permissions: ["first-recharge-reward:view"] + }, + listGifts: { + method: "GET", + operationId: API_OPERATIONS.listGifts, + path: "/v1/admin/gifts", + permission: "gift:view", + permissions: ["gift:view"] + }, + listGiftTypes: { + method: "GET", + operationId: API_OPERATIONS.listGiftTypes, + path: "/v1/admin/gift-types", + permission: "gift:view", + permissions: ["gift:view"] + }, + listH5Links: { + method: "GET", + operationId: API_OPERATIONS.listH5Links, + path: "/v1/admin/app-config/h5-links", + permission: "app-config:view", + permissions: ["app-config:view"] + }, + listHostAgencyPolicies: { + method: "GET", + operationId: API_OPERATIONS.listHostAgencyPolicies, + path: "/v1/admin/host-agency-policies", + permission: "host-agency-policy:view", + permissions: ["host-agency-policy:view"] + }, + listHosts: { + method: "GET", + operationId: API_OPERATIONS.listHosts, + path: "/v1/admin/hosts", + permission: "host:view", + permissions: ["host:view"] + }, + listHostSalarySettlements: { + method: "GET", + operationId: API_OPERATIONS.listHostSalarySettlements, + path: "/v1/admin/host-salary-settlements", + permission: "host-salary-settlement:view", + permissions: ["host-salary-settlement:view"] + }, + listInviteActivityRewardClaims: { + method: "GET", + operationId: API_OPERATIONS.listInviteActivityRewardClaims, + path: "/v1/admin/activity/invite-reward/claims", + permission: "invite-activity-reward:view", + permissions: ["invite-activity-reward:view"] + }, + listLevelConfig: { + method: "GET", + operationId: API_OPERATIONS.listLevelConfig, + path: "/v1/admin/users/level-config", + permission: "level-config:view", + permissions: ["level-config:view"] + }, + listLoginLogs: { + method: "GET", + operationId: API_OPERATIONS.listLoginLogs, + path: "/v1/logs/login", + permission: "log:view", + permissions: ["log:view"] + }, + listLuckyGiftConfigs: { + method: "GET", + operationId: API_OPERATIONS.listLuckyGiftConfigs, + path: "/v1/admin/activity/lucky-gifts/v2/configs", + permission: "lucky-gift:view", + permissions: ["lucky-gift:view"] + }, + listLuckyGiftDraws: { + method: "GET", + operationId: API_OPERATIONS.listLuckyGiftDraws, + path: "/v1/admin/activity/lucky-gifts/v2/draws", + permission: "lucky-gift:view", + permissions: ["lucky-gift:view"] + }, + listManagers: { + method: "GET", + operationId: API_OPERATIONS.listManagers, + path: "/v1/admin/managers", + permission: "bd:view", + permissions: ["bd:view"] + }, + listOperationLogs: { + method: "GET", + operationId: API_OPERATIONS.listOperationLogs, + path: "/v1/logs/operations", + permission: "log:view", + permissions: ["log:view"] + }, + listPermissions: { + method: "GET", + operationId: API_OPERATIONS.listPermissions, + path: "/v1/permissions", + permission: "permission:view", + permissions: ["permission:view","role:permission","role:manage"] + }, + listPlatforms: { + method: "GET", + operationId: API_OPERATIONS.listPlatforms, + path: "/v1/admin/game/platforms", + permission: "game:view", + permissions: ["game:view"] + }, + listPopups: { + method: "GET", + operationId: API_OPERATIONS.listPopups, + path: "/v1/admin/app-config/popups", + permission: "app-config:view", + permissions: ["app-config:view"] + }, + listPrettyIdPools: { + method: "GET", + operationId: API_OPERATIONS.listPrettyIdPools, + path: "/v1/admin/users/pretty-id-pools", + permission: "pretty-id:view", + permissions: ["pretty-id:view"] + }, + listPrettyIds: { + method: "GET", + operationId: API_OPERATIONS.listPrettyIds, + path: "/v1/admin/users/pretty-ids", + permission: "pretty-id:view", + permissions: ["pretty-id:view"] + }, + listRechargeBills: { + method: "GET", + operationId: API_OPERATIONS.listRechargeBills, + path: "/v1/admin/payment/recharge-bills", + permission: "payment-bill:view", + permissions: ["payment-bill:view"] + }, + listRechargeProducts: { + method: "GET", + operationId: API_OPERATIONS.listRechargeProducts, + path: "/v1/admin/payment/recharge-products", + permission: "payment-product:view", + permissions: ["payment-product:view"] + }, + listRedPackets: { + method: "GET", + operationId: API_OPERATIONS.listRedPackets, + path: "/v1/admin/activity/red-packets", + permission: "red-packet:view", + permissions: ["red-packet:view"] + }, + listRegionBlocks: { + method: "GET", + operationId: API_OPERATIONS.listRegionBlocks, + path: "/v1/admin/users/region-blocks", + permission: "region-block:view", + permissions: ["region-block:view"] + }, + listRegions: { + method: "GET", + operationId: API_OPERATIONS.listRegions, + path: "/v1/admin/regions", + permission: "region:view", + permissions: ["region:view"] + }, + listRegistrationRewardClaims: { + method: "GET", + operationId: API_OPERATIONS.listRegistrationRewardClaims, + path: "/v1/admin/activity/registration-reward/claims", + permission: "registration-reward:view", + permissions: ["registration-reward:view"] + }, + listReports: { + method: "GET", + operationId: API_OPERATIONS.listReports, + path: "/v1/admin/operations/reports", + permission: "report:view", + permissions: ["report:view"] + }, + listResourceGrants: { + method: "GET", + operationId: API_OPERATIONS.listResourceGrants, + path: "/v1/admin/resource-grants", + permission: "resource-grant:view", + permissions: ["resource-grant:view"] + }, + listResourceGroups: { + method: "GET", + operationId: API_OPERATIONS.listResourceGroups, + path: "/v1/admin/resource-groups", + permission: "resource-group:view", + permissions: ["resource-group:view"] + }, + listResources: { + method: "GET", + operationId: API_OPERATIONS.listResources, + path: "/v1/admin/resources", + permission: "resource:view", + permissions: ["resource:view"] + }, + listResourceShopItems: { + method: "GET", + operationId: API_OPERATIONS.listResourceShopItems, + path: "/v1/admin/resource-shop/items", + permission: "resource-shop:view", + permissions: ["resource-shop:view"] + }, + listResourceShopPurchaseOrders: { + method: "GET", + operationId: API_OPERATIONS.listResourceShopPurchaseOrders, + path: "/v1/admin/resource-shop/purchase-orders", + permission: "resource-shop:view", + permissions: ["resource-shop:view"] + }, + listRobotRooms: { + method: "GET", + operationId: API_OPERATIONS.listRobotRooms, + path: "/v1/admin/rooms/robot-rooms", + permission: "room-robot:view", + permissions: ["room-robot:view"] + }, + listRoles: { + method: "GET", + operationId: API_OPERATIONS.listRoles, + path: "/v1/roles", + permission: "role:view", + permissions: ["role:view"] + }, + listRoomPins: { + method: "GET", + operationId: API_OPERATIONS.listRoomPins, + path: "/v1/admin/rooms/pins", + permission: "room-pin:view", + permissions: ["room-pin:view"] + }, + listRoomRpsChallenges: { + method: "GET", + operationId: API_OPERATIONS.listRoomRpsChallenges, + path: "/v1/admin/game/room-rps/challenges", + permission: "game:view", + permissions: ["game:view"] + }, + listRooms: { + method: "GET", + operationId: API_OPERATIONS.listRooms, + path: "/v1/admin/rooms", + permission: "room:view", + permissions: ["room:view"] + }, + listRoomTurnoverRewardSettlements: { + method: "GET", + operationId: API_OPERATIONS.listRoomTurnoverRewardSettlements, + path: "/v1/admin/activity/room-turnover-reward/settlements", + permission: "room-turnover-reward:view", + permissions: ["room-turnover-reward:view"] + }, + listSelfGames: { + method: "GET", + operationId: API_OPERATIONS.listSelfGames, + path: "/v1/admin/game/self-games", + permission: "game:view", + permissions: ["game:view"] + }, + listSevenDayCheckInClaims: { + method: "GET", + operationId: API_OPERATIONS.listSevenDayCheckInClaims, + path: "/v1/admin/activity/seven-day-checkin/claims", + permission: "seven-day-checkin:view", + permissions: ["seven-day-checkin:view"] + }, + listSplashScreens: { + method: "GET", + operationId: API_OPERATIONS.listSplashScreens, + path: "/v1/admin/app-config/splash-screens", + permission: "app-config:view", + permissions: ["app-config:view"] + }, + listSystemMenus: { + method: "GET", + operationId: API_OPERATIONS.listSystemMenus, + path: "/v1/system/menus", + permission: "menu:view", + permissions: ["menu:view"] + }, + listTaskDefinitions: { + method: "GET", + operationId: API_OPERATIONS.listTaskDefinitions, + path: "/v1/admin/activity/daily-tasks", + permission: "daily-task:view", + permissions: ["daily-task:view"] + }, + listTeamSalaryPolicies: { + method: "GET", + operationId: API_OPERATIONS.listTeamSalaryPolicies, + path: "/v1/admin/team-salary-policies", + permission: "team-salary-policy:view", + permissions: ["team-salary-policy:view"] + }, + listTemporaryPaymentLinks: { + method: "GET", + operationId: API_OPERATIONS.listTemporaryPaymentLinks, + path: "/v1/admin/payment/temporary-links", + permission: "payment-temporary-link:view", + permissions: ["payment-temporary-link:view","money:view"] + }, + listThirdPartyPaymentChannels: { + method: "GET", + operationId: API_OPERATIONS.listThirdPartyPaymentChannels, + path: "/v1/admin/payment/third-party-channels", + permission: "payment-third-party:view", + permissions: ["payment-third-party:view","money:view"] + }, + listUserLeaderboards: { + method: "GET", + operationId: API_OPERATIONS.listUserLeaderboards, + path: "/v1/admin/activity/user-leaderboards", + permission: "user-leaderboard:view", + permissions: ["user-leaderboard:view"] + }, + listUserMoneyScopes: { + method: "GET", + operationId: API_OPERATIONS.listUserMoneyScopes, + path: "/v1/users/{id}/money-scopes", + permission: "user:view", + permissions: ["user:view"] + }, + listUsers: { + method: "GET", + operationId: API_OPERATIONS.listUsers, + path: "/v1/users", + permission: "user:view", + permissions: ["user:view"] + }, + listWeeklyStarCycles: { + method: "GET", + operationId: API_OPERATIONS.listWeeklyStarCycles, + path: "/v1/admin/activity/weekly-star/cycles", + permission: "weekly-star:view", + permissions: ["weekly-star:view"] + }, + listWeeklyStarLeaderboard: { + method: "GET", + operationId: API_OPERATIONS.listWeeklyStarLeaderboard, + path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/leaderboard", + permission: "weekly-star:view", + permissions: ["weekly-star:view"] + }, + listWeeklyStarSettlements: { + method: "GET", + operationId: API_OPERATIONS.listWeeklyStarSettlements, + path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/settlements", + permission: "weekly-star:settle", + permissions: ["weekly-star:settle"] + }, + listWheelDraws: { + method: "GET", + operationId: API_OPERATIONS.listWheelDraws, + path: "/v1/admin/activity/wheel/draws", + permission: "wheel:view", + permissions: ["wheel:view"] + }, + login: { + method: "POST", + operationId: API_OPERATIONS.login, + path: "/v1/auth/login" + }, + logout: { + method: "POST", + operationId: API_OPERATIONS.logout, + path: "/v1/auth/logout" + }, + lookupCoinAdjustmentTarget: { + method: "GET", + operationId: API_OPERATIONS.lookupCoinAdjustmentTarget, + path: "/v1/admin/operations/coin-adjustments/target", + permission: "coin-adjustment:create", + permissions: ["coin-adjustment:create"] + }, + lookupResourceGrantTarget: { + method: "GET", + operationId: API_OPERATIONS.lookupResourceGrantTarget, + path: "/v1/admin/resource-grants/target", + permission: "resource-grant:create", + permissions: ["resource-grant:create"] + }, + me: { + method: "GET", + operationId: API_OPERATIONS.me, + path: "/v1/auth/me" + }, + navigationMenus: { + method: "GET", + operationId: API_OPERATIONS.navigationMenus, + path: "/v1/navigation/menus" + }, + publishHostAgencyPolicy: { + method: "POST", + operationId: API_OPERATIONS.publishHostAgencyPolicy, + path: "/v1/admin/host-agency-policies/{policy_id}/publish", + permission: "host-agency-policy:publish", + permissions: ["host-agency-policy:publish"] + }, + refresh: { + method: "POST", + operationId: API_OPERATIONS.refresh, + path: "/v1/auth/refresh" + }, + replaceCoinSellerSalaryRates: { + method: "PUT", + operationId: API_OPERATIONS.replaceCoinSellerSalaryRates, + path: "/v1/admin/coin-seller-salary-rates/{region_id}", + permission: "coin-seller:exchange-rate", + permissions: ["coin-seller:exchange-rate"] + }, + replaceRegionBlocks: { + method: "PUT", + operationId: API_OPERATIONS.replaceRegionBlocks, + path: "/v1/admin/users/region-blocks", + permission: "region-block:update", + permissions: ["region-block:update"] + }, + replaceRegionCountries: { + method: "PUT", + operationId: API_OPERATIONS.replaceRegionCountries, + path: "/v1/admin/regions/{region_id}/countries", + permission: "region:update", + permissions: ["region:update"] + }, + replaceRoleDataScopes: { + method: "PUT", + operationId: API_OPERATIONS.replaceRoleDataScopes, + path: "/v1/roles/{id}/data-scopes", + permission: "role:data-scope", + permissions: ["role:data-scope"] + }, + replaceRolePermissions: { + method: "PUT", + operationId: API_OPERATIONS.replaceRolePermissions, + path: "/v1/roles/{id}/permissions", + permission: "role:permission", + permissions: ["role:permission","role:manage"] + }, + replaceUserMoneyScopes: { + method: "PUT", + operationId: API_OPERATIONS.replaceUserMoneyScopes, + path: "/v1/users/{id}/money-scopes", + permission: "user:update", + permissions: ["user:update"] + }, + resetUserPassword: { + method: "POST", + operationId: API_OPERATIONS.resetUserPassword, + path: "/v1/users/{id}/reset-password", + permission: "user:reset-password", + permissions: ["user:reset-password"] + }, + retryRedPacketRefund: { + method: "POST", + operationId: API_OPERATIONS.retryRedPacketRefund, + path: "/v1/admin/activity/red-packets/refund/retry", + permission: "red-packet:update", + permissions: ["red-packet:update"] + }, + retryRoomRpsSettlement: { + method: "POST", + operationId: API_OPERATIONS.retryRoomRpsSettlement, + path: "/v1/admin/game/room-rps/challenges/{challenge_id}/retry-settlement", + permission: "game:update", + permissions: ["game:update"] + }, + retryRoomTurnoverRewardSettlement: { + method: "POST", + operationId: API_OPERATIONS.retryRoomTurnoverRewardSettlement, + path: "/v1/admin/activity/room-turnover-reward/settlements/{settlement_id}/retry", + permission: "room-turnover-reward:retry", + permissions: ["room-turnover-reward:retry"] + }, + revokeResourceGrant: { + method: "POST", + operationId: API_OPERATIONS.revokeResourceGrant, + path: "/v1/admin/resource-grants/{grant_id}/revoke", + permission: "resource-grant:revoke", + permissions: ["resource-grant:revoke"] + }, + search: { + method: "GET", + operationId: API_OPERATIONS.search, + path: "/v1/search" + }, + setAgencyJoinEnabled: { + method: "POST", + operationId: API_OPERATIONS.setAgencyJoinEnabled, + path: "/v1/admin/agencies/{agency_id}/join-enabled", + permission: "agency:status", + permissions: ["agency:status"] + }, + setBDLeaderStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setBDLeaderStatus, + path: "/v1/admin/bd-leaders/{user_id}/status", + permission: "bd:update", + permissions: ["bd:update"] + }, + setBDStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setBDStatus, + path: "/v1/admin/bds/{user_id}/status", + permission: "bd:update", + permissions: ["bd:update"] + }, + setCoinSellerStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setCoinSellerStatus, + path: "/v1/admin/coin-sellers/{user_id}/status", + permission: "coin-seller:update", + permissions: ["coin-seller:update"] + }, + setDiceRobotStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setDiceRobotStatus, + path: "/v1/admin/game/robots/{user_id}/status", + permission: "game:update", + permissions: ["game:update"] + }, + setGameStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setGameStatus, + path: "/v1/admin/game/games/{game_id}/status", + permission: "game:status", + permissions: ["game:status"] + }, + setPrettyIdStatus: { + method: "POST", + operationId: API_OPERATIONS.setPrettyIdStatus, + path: "/v1/admin/users/pretty-ids/{pretty_id}/status", + permission: "pretty-id:update", + permissions: ["pretty-id:update"] + }, + setTaskDefinitionStatus: { + method: "POST", + operationId: API_OPERATIONS.setTaskDefinitionStatus, + path: "/v1/admin/activity/daily-tasks/{task_id}/status", + permission: "daily-task:status", + permissions: ["daily-task:status"] + }, + setThirdPartyPaymentMethodStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setThirdPartyPaymentMethodStatus, + path: "/v1/admin/payment/third-party-methods/{method_id}/status", + permission: "payment-third-party:update", + permissions: ["payment-third-party:update"] + }, + setWeeklyStarCycleStatus: { + method: "PATCH", + operationId: API_OPERATIONS.setWeeklyStarCycleStatus, + path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}/status", + permission: "weekly-star:update", + permissions: ["weekly-star:update"] + }, + sortMenus: { + method: "PUT", + operationId: API_OPERATIONS.sortMenus, + path: "/v1/system/menus/sort", + permission: "menu:sort", + permissions: ["menu:sort"] + }, + startRobotRoom: { + method: "POST", + operationId: API_OPERATIONS.startRobotRoom, + path: "/v1/admin/rooms/robot-rooms/{room_id}/start", + permission: "room-robot:update", + permissions: ["room-robot:update"] + }, + stopRobotRoom: { + method: "POST", + operationId: API_OPERATIONS.stopRobotRoom, + path: "/v1/admin/rooms/robot-rooms/{room_id}/stop", + permission: "room-robot:update", + permissions: ["room-robot:update"] + }, + syncPermissions: { + method: "POST", + operationId: API_OPERATIONS.syncPermissions, + path: "/v1/permissions/sync", + permission: "permission:sync", + permissions: ["permission:sync"] + }, + syncThirdPartyPaymentMethods: { + method: "POST", + operationId: API_OPERATIONS.syncThirdPartyPaymentMethods, + path: "/v1/admin/payment/third-party-methods/sync", + permission: "payment-third-party:update", + permissions: ["payment-third-party:update"] + }, + syncThirdPartyPaymentRates: { + method: "POST", + operationId: API_OPERATIONS.syncThirdPartyPaymentRates, + path: "/v1/admin/payment/third-party-rates/sync", + permission: "payment-third-party:update", + permissions: ["payment-third-party:update"] + }, + updateAchievementDefinition: { + method: "PUT", + operationId: API_OPERATIONS.updateAchievementDefinition, + path: "/v1/admin/activity/achievements/{achievement_id}", + permission: "achievement:update", + permissions: ["achievement:update"] + }, + updateAppVersion: { + method: "PUT", + operationId: API_OPERATIONS.updateAppVersion, + path: "/v1/admin/app-config/versions/{version_id}", + permission: "app-version:update", + permissions: ["app-version:update"] + }, + updateBanner: { + method: "PUT", + operationId: API_OPERATIONS.updateBanner, + path: "/v1/admin/app-config/banners/{banner_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updateCatalog: { + method: "PATCH", + operationId: API_OPERATIONS.updateCatalog, + path: "/v1/admin/game/games/{game_id}", + permission: "game:update", + permissions: ["game:update"] + }, + updateCountry: { + method: "PATCH", + operationId: API_OPERATIONS.updateCountry, + path: "/v1/admin/countries/{country_id}", + permission: "country:update", + permissions: ["country:update"] + }, + updateCPConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateCPConfig, + path: "/v1/admin/activity/cp/config", + permission: "cp-config:update", + permissions: ["cp-config:update"] + }, + updateCPWeeklyRankConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateCPWeeklyRankConfig, + path: "/v1/admin/activity/cp-weekly-rank/config", + permission: "cp-weekly-rank:update", + permissions: ["cp-weekly-rank:update"] + }, + updateCumulativeRechargeRewardConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateCumulativeRechargeRewardConfig, + path: "/v1/admin/activity/cumulative-recharge-reward/config", + permission: "cumulative-recharge-reward:update", + permissions: ["cumulative-recharge-reward:update"] + }, + updateDiceConfig: { + method: "PATCH", + operationId: API_OPERATIONS.updateDiceConfig, + path: "/v1/admin/game/self-games/{game_id}/config", + permission: "game:update", + permissions: ["game:update"] + }, + updateExploreTab: { + method: "PUT", + operationId: API_OPERATIONS.updateExploreTab, + path: "/v1/admin/app-config/explore-tabs/{tab_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updateFirstRechargeRewardConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateFirstRechargeRewardConfig, + path: "/v1/admin/activity/first-recharge-reward/config", + permission: "first-recharge-reward:update", + permissions: ["first-recharge-reward:update"] + }, + updateGift: { + method: "PUT", + operationId: API_OPERATIONS.updateGift, + path: "/v1/admin/gifts/{gift_id}", + permission: "gift:update", + permissions: ["gift:update"] + }, + updateGiftType: { + method: "PUT", + operationId: API_OPERATIONS.updateGiftType, + path: "/v1/admin/gift-types/{type_code}", + permission: "gift:update", + permissions: ["gift:update"] + }, + updateGiftTypes: { + method: "PUT", + operationId: API_OPERATIONS.updateGiftTypes, + path: "/v1/admin/gift-types", + permission: "gift:update", + permissions: ["gift:update"] + }, + updateH5Link: { + method: "PUT", + operationId: API_OPERATIONS.updateH5Link, + path: "/v1/admin/app-config/h5-links/{key}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updateH5Links: { + method: "PUT", + operationId: API_OPERATIONS.updateH5Links, + path: "/v1/admin/app-config/h5-links", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updateHostAgencyPolicy: { + method: "PUT", + operationId: API_OPERATIONS.updateHostAgencyPolicy, + path: "/v1/admin/host-agency-policies/{policy_id}", + permission: "host-agency-policy:update", + permissions: ["host-agency-policy:update"] + }, + updateHumanRoomRobotConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateHumanRoomRobotConfig, + path: "/v1/admin/rooms/robot-rooms/human-config", + permission: "room-robot:update", + permissions: ["room-robot:update"] + }, + updateInviteActivityRewardConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateInviteActivityRewardConfig, + path: "/v1/admin/activity/invite-reward/config", + permission: "invite-activity-reward:update", + permissions: ["invite-activity-reward:update"] + }, + updateMenu: { + method: "PATCH", + operationId: API_OPERATIONS.updateMenu, + path: "/v1/system/menus/{id}", + permission: "menu:update", + permissions: ["menu:update"] + }, + updateMenuVisible: { + method: "PATCH", + operationId: API_OPERATIONS.updateMenuVisible, + path: "/v1/system/menus/{id}/visible", + permission: "menu:visible", + permissions: ["menu:visible"] + }, + updatePermission: { + method: "PATCH", + operationId: API_OPERATIONS.updatePermission, + path: "/v1/permissions/{id}", + permission: "permission:update", + permissions: ["permission:update"] + }, + updatePlatform: { + method: "PATCH", + operationId: API_OPERATIONS.updatePlatform, + path: "/v1/admin/game/platforms/{platform_code}", + permission: "game:update", + permissions: ["game:update"] + }, + updatePopup: { + method: "PUT", + operationId: API_OPERATIONS.updatePopup, + path: "/v1/admin/app-config/popups/{popup_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updatePrettyIdPool: { + method: "PUT", + operationId: API_OPERATIONS.updatePrettyIdPool, + path: "/v1/admin/users/pretty-id-pools/{pool_id}", + permission: "pretty-id:update", + permissions: ["pretty-id:update"] + }, + updateRechargeProduct: { + method: "PUT", + operationId: API_OPERATIONS.updateRechargeProduct, + path: "/v1/admin/payment/recharge-products/{product_id}", + permission: "payment-product:update", + permissions: ["payment-product:update"] + }, + updateRedPacketConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRedPacketConfig, + path: "/v1/admin/activity/red-packets/config", + permission: "red-packet:update", + permissions: ["red-packet:update"] + }, + updateRegion: { + method: "PATCH", + operationId: API_OPERATIONS.updateRegion, + path: "/v1/admin/regions/{region_id}", + permission: "region:update", + permissions: ["region:update"] + }, + updateRegistrationRewardConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRegistrationRewardConfig, + path: "/v1/admin/activity/registration-reward/config", + permission: "registration-reward:update", + permissions: ["registration-reward:update"] + }, + updateResource: { + method: "PUT", + operationId: API_OPERATIONS.updateResource, + path: "/v1/admin/resources/{resource_id}", + permission: "resource:update", + permissions: ["resource:update"] + }, + updateResourceGroup: { + method: "PUT", + operationId: API_OPERATIONS.updateResourceGroup, + path: "/v1/admin/resource-groups/{group_id}", + permission: "resource-group:update", + permissions: ["resource-group:update"] + }, + updateResourceGroupItems: { + method: "PUT", + operationId: API_OPERATIONS.updateResourceGroupItems, + path: "/v1/admin/resource-groups/{group_id}/items", + permission: "resource-group:update", + permissions: ["resource-group:update"] + }, + updateResourceIdentityAutoGrantConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateResourceIdentityAutoGrantConfig, + path: "/v1/admin/resource-groups/identity-auto-grant-config", + permission: "resource-group:update", + permissions: ["resource-group:update"] + }, + updateRiskConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRiskConfig, + path: "/v1/admin/users/risk-config", + permission: "risk-config:update", + permissions: ["risk-config:update"] + }, + updateRole: { + method: "PATCH", + operationId: API_OPERATIONS.updateRole, + path: "/v1/roles/{id}", + permission: "role:update", + permissions: ["role:update","role:manage"] + }, + updateRoom: { + method: "PATCH", + operationId: API_OPERATIONS.updateRoom, + path: "/v1/admin/rooms/{room_id}", + permission: "room:update", + permissions: ["room:update"] + }, + updateRoomConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRoomConfig, + path: "/v1/admin/rooms/config", + permission: "room-config:update", + permissions: ["room-config:update"] + }, + updateRoomRocketConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRoomRocketConfig, + path: "/v1/admin/activity/room-rocket/config", + permission: "room-rocket:update", + permissions: ["room-rocket:update"] + }, + updateRoomRpsConfig: { + method: "PATCH", + operationId: API_OPERATIONS.updateRoomRpsConfig, + path: "/v1/admin/game/room-rps/config", + permission: "game:update", + permissions: ["game:update"] + }, + updateRoomTurnoverRewardConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRoomTurnoverRewardConfig, + path: "/v1/admin/activity/room-turnover-reward/config", + permission: "room-turnover-reward:update", + permissions: ["room-turnover-reward:update"] + }, + updateRoomWhitelistConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateRoomWhitelistConfig, + path: "/v1/admin/rooms/whitelist", + permission: "room-whitelist:update", + permissions: ["room-whitelist:update"] + }, + updateSevenDayCheckInConfig: { + method: "PUT", + operationId: API_OPERATIONS.updateSevenDayCheckInConfig, + path: "/v1/admin/activity/seven-day-checkin/config", + permission: "seven-day-checkin:update", + permissions: ["seven-day-checkin:update"] + }, + updateSplashScreen: { + method: "PUT", + operationId: API_OPERATIONS.updateSplashScreen, + path: "/v1/admin/app-config/splash-screens/{splash_id}", + permission: "app-config:update", + permissions: ["app-config:update"] + }, + updateTaskDefinition: { + method: "PUT", + operationId: API_OPERATIONS.updateTaskDefinition, + path: "/v1/admin/activity/daily-tasks/{task_id}", + permission: "daily-task:update", + permissions: ["daily-task:update"] + }, + updateTeamSalaryPolicy: { + method: "PUT", + operationId: API_OPERATIONS.updateTeamSalaryPolicy, + path: "/v1/admin/team-salary-policies/{policy_id}", + permission: "team-salary-policy:update", + permissions: ["team-salary-policy:update"] + }, + updateThirdPartyPaymentRate: { + method: "PATCH", + operationId: API_OPERATIONS.updateThirdPartyPaymentRate, + path: "/v1/admin/payment/third-party-rates/{method_id}", + permission: "payment-third-party:update", + permissions: ["payment-third-party:update"] + }, + updateTier: { + method: "PUT", + operationId: API_OPERATIONS.updateTier, + path: "/v1/admin/users/level-config/tiers/{tier_id}", + permission: "level-config:update", + permissions: ["level-config:update"] + }, + updateTrack: { + method: "PUT", + operationId: API_OPERATIONS.updateTrack, + path: "/v1/admin/users/level-config/tracks/{track}", + permission: "level-config:update", + permissions: ["level-config:update"] + }, + updateUser: { + method: "PATCH", + operationId: API_OPERATIONS.updateUser, + path: "/v1/users/{id}", + permission: "user:update", + permissions: ["user:update"] + }, + updateUserStatus: { + method: "PATCH", + operationId: API_OPERATIONS.updateUserStatus, + path: "/v1/users/{id}/status", + permission: "user:status", + permissions: ["user:status"] + }, + updateWeeklyStarCycle: { + method: "PUT", + operationId: API_OPERATIONS.updateWeeklyStarCycle, + path: "/v1/admin/activity/weekly-star/cycles/{cycle_id}", + permission: "weekly-star:update", + permissions: ["weekly-star:update"] + }, + uploadFile: { + method: "POST", + operationId: API_OPERATIONS.uploadFile, + path: "/v1/admin/files/upload", + permission: "upload:create", + permissions: ["upload:create"] + }, + uploadImage: { + method: "POST", + operationId: API_OPERATIONS.uploadImage, + path: "/v1/admin/files/image/upload", + permission: "upload:create", + permissions: ["upload:create"] + }, + upsertLuckyGiftConfig: { + method: "PUT", + operationId: API_OPERATIONS.upsertLuckyGiftConfig, + path: "/v1/admin/activity/lucky-gifts/v2/config", + permission: "lucky-gift:update", + permissions: ["lucky-gift:update"] + }, + upsertResourceShopItems: { + method: "POST", + operationId: API_OPERATIONS.upsertResourceShopItems, + path: "/v1/admin/resource-shop/items", + permission: "resource-shop:update", + permissions: ["resource-shop:update"] + }, + upsertRule: { + method: "PUT", + operationId: API_OPERATIONS.upsertRule, + path: "/v1/admin/users/level-config/rules/{track}/{level}", + permission: "level-config:update", + permissions: ["level-config:update"] + }, + upsertWheelConfig: { + method: "PUT", + operationId: API_OPERATIONS.upsertWheelConfig, + path: "/v1/admin/activity/wheel/config", + permission: "wheel:update", + permissions: ["wheel:update"] + } }; export const API_OPERATION_IDS = Object.values(API_OPERATIONS); export const API_PERMISSION_CODES = Array.from( - new Set( - Object.values(API_ENDPOINTS) - .flatMap((endpoint) => endpoint.permissions || (endpoint.permission ? [endpoint.permission] : [])) - .filter((permission): permission is PermissionCode => Boolean(permission)), - ), + new Set( + Object.values(API_ENDPOINTS) + .flatMap((endpoint) => endpoint.permissions || (endpoint.permission ? [endpoint.permission] : [])) + .filter((permission): permission is PermissionCode => Boolean(permission)) + ) ); export type ApiPathParams = Record; export function apiEndpointPath(operationId: ApiOperationId, params: ApiPathParams = {}) { - let endpointPath = API_ENDPOINTS[operationId].path; + let endpointPath = API_ENDPOINTS[operationId].path; - for (const [key, value] of Object.entries(params)) { - endpointPath = endpointPath.replace(`{${key}}`, encodeURIComponent(String(value))); - } + for (const [key, value] of Object.entries(params)) { + endpointPath = endpointPath.replace(`{${key}}`, encodeURIComponent(String(value))); + } - return endpointPath; + return endpointPath; } diff --git a/src/shared/api/generated/schema.d.ts b/src/shared/api/generated/schema.d.ts index adac00f..d525351 100644 --- a/src/shared/api/generated/schema.d.ts +++ b/src/shared/api/generated/schema.d.ts @@ -1860,6 +1860,38 @@ export interface paths { patch?: never; trace?: never; }; + "/admin/money/scope": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getMoneyScope"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/admin/money/performance": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["getMoneyPerformance"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/admin/payment/temporary-links": { parameters: { query?: never; @@ -1869,7 +1901,7 @@ export interface paths { }; get: operations["listTemporaryPaymentLinks"]; put?: never; - post?: never; + post: operations["createTemporaryPaymentLink"]; delete?: never; options?: never; head?: never; @@ -3156,6 +3188,22 @@ export interface paths { patch: operations["updateUser"]; trace?: never; }; + "/users/{id}/money-scopes": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: operations["listUserMoneyScopes"]; + put: operations["replaceUserMoneyScopes"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/users/{id}/reset-password": { parameters: { query?: never; @@ -3557,6 +3605,10 @@ export interface components { UserInput: { [key: string]: unknown; }; + UserMoneyScope: { + appCode: string; + regionId: number; + }; }; responses: { /** @description OK */ @@ -3785,6 +3837,13 @@ export interface components { }; }; }; + MoneyScopeRequest: { + content: { + "application/json": { + scopes: components["schemas"]["UserMoneyScope"][]; + }; + }; + }; MenuRequest: { content: { "application/json": components["schemas"]["MenuInput"]; @@ -3831,6 +3890,19 @@ export interface components { }; }; }; + TemporaryPaymentLinkRequest: { + content: { + "application/json": { + appCode: string; + language?: string; + paymentMethodId: number; + providerCode: string; + regionId: number; + returnUrl?: string; + usdMinorAmount: number; + }; + }; + }; UserRequest: { content: { "application/json": components["schemas"]["UserInput"]; @@ -6078,6 +6150,30 @@ export interface operations { 200: components["responses"]["EmptyResponse"]; }; }; + getMoneyScope: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: components["responses"]["EmptyResponse"]; + }; + }; + getMoneyPerformance: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: components["responses"]["EmptyResponse"]; + }; + }; listTemporaryPaymentLinks: { parameters: { query?: never; @@ -6090,6 +6186,18 @@ export interface operations { 200: components["responses"]["EmptyResponse"]; }; }; + createTemporaryPaymentLink: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: components["requestBodies"]["TemporaryPaymentLinkRequest"]; + responses: { + 200: components["responses"]["EmptyResponse"]; + }; + }; getTemporaryPaymentLink: { parameters: { query?: never; @@ -7526,6 +7634,34 @@ export interface operations { 200: components["responses"]["UserResponse"]; }; }; + listUserMoneyScopes: { + parameters: { + query?: never; + header?: never; + path: { + id: components["parameters"]["Id"]; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + 200: components["responses"]["EmptyResponse"]; + }; + }; + replaceUserMoneyScopes: { + parameters: { + query?: never; + header?: never; + path: { + id: components["parameters"]["Id"]; + }; + cookie?: never; + }; + requestBody?: components["requestBodies"]["MoneyScopeRequest"]; + responses: { + 200: components["responses"]["EmptyResponse"]; + }; + }; resetUserPassword: { parameters: { query?: never; diff --git a/src/shared/api/types.ts b/src/shared/api/types.ts index cea383c..f5e78f6 100644 --- a/src/shared/api/types.ts +++ b/src/shared/api/types.ts @@ -62,6 +62,12 @@ export interface AdminUserDto { team?: string; } +export interface UserMoneyScopeDto { + appCode: string; + regionId: number; + userId?: EntityId; +} + export interface UserFormPayload { mfaEnabled?: boolean; name: string; @@ -80,6 +86,7 @@ export interface ResetPasswordResultDto { export interface CreateUserResultDto { initialPassword?: string; + user?: AdminUserDto; } export interface RoleDto { diff --git a/src/styles/shared-ui.css b/src/styles/shared-ui.css index 82642ca..705b253 100644 --- a/src/styles/shared-ui.css +++ b/src/styles/shared-ui.css @@ -1322,6 +1322,24 @@ gap: var(--space-2); } +.permission-grid--money { + grid-template-columns: 1fr; +} + +.permission-scope-group { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--space-2); + padding-bottom: var(--space-2); + border-bottom: 1px solid var(--border); +} + +.permission-scope-group > strong { + grid-column: 1 / -1; + color: var(--text-primary); + font-size: var(--admin-font-size); +} + .permission-check { display: flex; align-items: center; diff --git a/vite.config.js b/vite.config.js index 8825c71..865a3ec 100644 --- a/vite.config.js +++ b/vite.config.js @@ -71,6 +71,16 @@ export default defineConfig({ "/api": { target: "http://localhost:13100", changeOrigin: true + }, + "/__api_test__": { + target: "https://api-test.global-interaction.com", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/__api_test__/, "") + }, + "/__api_local__": { + target: "http://127.0.0.1:13000", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/__api_local__/, "") } } },
负责模块负责区域 负责人模块类型区域类型 国家 / 地区 充值 App 流水