app区域限制
This commit is contained in:
parent
1b9982e52c
commit
01989ee16e
@ -1130,6 +1130,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/banners": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"operationId": "listBanners",
|
||||
"responses": {
|
||||
@ -1152,6 +1157,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/banners/{banner_id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"put": {
|
||||
"operationId": "updateBanner",
|
||||
"responses": {
|
||||
@ -1194,6 +1204,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/splash-screens": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"operationId": "listSplashScreens",
|
||||
"responses": {
|
||||
@ -1216,6 +1231,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/splash-screens/{splash_id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"put": {
|
||||
"operationId": "updateSplashScreen",
|
||||
"responses": {
|
||||
@ -1258,6 +1278,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/popups": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"operationId": "listPopups",
|
||||
"responses": {
|
||||
@ -1280,6 +1305,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/popups/{popup_id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"put": {
|
||||
"operationId": "updatePopup",
|
||||
"responses": {
|
||||
@ -1436,6 +1466,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/explore-tabs": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"operationId": "listExploreTabs",
|
||||
"responses": {
|
||||
@ -1458,6 +1493,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/explore-tabs/{tab_id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"put": {
|
||||
"operationId": "updateExploreTab",
|
||||
"responses": {
|
||||
@ -1500,6 +1540,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/versions": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"operationId": "listAppVersions",
|
||||
"responses": {
|
||||
@ -1522,6 +1567,11 @@
|
||||
}
|
||||
},
|
||||
"/admin/app-config/versions/{version_id}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/AppCodeHeader"
|
||||
}
|
||||
],
|
||||
"put": {
|
||||
"operationId": "updateAppVersion",
|
||||
"responses": {
|
||||
|
||||
@ -1,12 +1,32 @@
|
||||
import { afterEach, expect, test, vi } from "vitest";
|
||||
import { setAccessToken, setSelectedAppCode } from "@/shared/api/request";
|
||||
import {
|
||||
createAppVersion,
|
||||
createBanner,
|
||||
createExploreTab,
|
||||
createH5Link,
|
||||
createPopup,
|
||||
createSplashScreen,
|
||||
createSystemMessagePushFanout,
|
||||
deleteAppVersion,
|
||||
deleteBanner,
|
||||
deleteExploreTab,
|
||||
deleteH5Link,
|
||||
deletePopup,
|
||||
deleteSplashScreen,
|
||||
listAppVersions,
|
||||
listBanners,
|
||||
listExploreTabs,
|
||||
listH5Links,
|
||||
listPopups,
|
||||
listSplashScreens,
|
||||
updateAppVersion,
|
||||
updateBanner,
|
||||
updateExploreTab,
|
||||
updateH5Link,
|
||||
updateH5Links,
|
||||
updatePopup,
|
||||
updateSplashScreen,
|
||||
} from "./api";
|
||||
|
||||
afterEach(() => {
|
||||
@ -56,6 +76,52 @@ test("H5 config API pins every request to its explicit app scope", async () => {
|
||||
expect(JSON.parse(String(calls[3][1]?.body))).toEqual(payload);
|
||||
});
|
||||
|
||||
test("every APP config API pins reads and writes to the explicit app scope", async () => {
|
||||
setSelectedAppCode("lalu");
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
vi.fn(async (_url, init) => {
|
||||
const method = String(init?.method || "GET");
|
||||
const data = method === "GET" ? { items: [], total: 0 } : method === "DELETE" ? { deleted: true } : {};
|
||||
return new Response(JSON.stringify({ code: 0, data }), { status: method === "POST" ? 201 : 200 });
|
||||
}),
|
||||
);
|
||||
|
||||
const appCode = " Huwaa ";
|
||||
const banner = { bannerType: "h5", coverUrl: "https://cdn.example.com/banner.png", platform: "android", status: "active" } as const;
|
||||
const splash = { coverUrl: "https://cdn.example.com/splash.png", platform: "android", splashType: "h5", status: "active" } as const;
|
||||
const popup = { code: "welcome", jumpType: "h5", jumpUrl: "https://h5.example.com/welcome", name: "Welcome", status: "active" } as const;
|
||||
const explore = { enabled: true, h5Url: "https://h5.example.com/explore", tab: "Explore" };
|
||||
const version = { buildNumber: 10, downloadUrl: "https://cdn.example.com/app.apk", forceUpdate: false, platform: "android", version: "1.0.0" } as const;
|
||||
|
||||
await listBanners(appCode);
|
||||
await createBanner(appCode, banner);
|
||||
await updateBanner(appCode, 1, banner);
|
||||
await deleteBanner(appCode, 1);
|
||||
await listSplashScreens(appCode);
|
||||
await createSplashScreen(appCode, splash);
|
||||
await updateSplashScreen(appCode, 2, splash);
|
||||
await deleteSplashScreen(appCode, 2);
|
||||
await listPopups(appCode);
|
||||
await createPopup(appCode, popup);
|
||||
await updatePopup(appCode, 3, popup);
|
||||
await deletePopup(appCode, 3);
|
||||
await listExploreTabs(appCode);
|
||||
await createExploreTab(appCode, explore);
|
||||
await updateExploreTab(appCode, 4, explore);
|
||||
await deleteExploreTab(appCode, 4);
|
||||
await listAppVersions(appCode);
|
||||
await createAppVersion(appCode, version);
|
||||
await updateAppVersion(appCode, 5, version);
|
||||
await deleteAppVersion(appCode, 5);
|
||||
|
||||
const calls = vi.mocked(fetch).mock.calls;
|
||||
expect(calls).toHaveLength(20);
|
||||
calls.forEach(([, init]) => {
|
||||
expect(init?.headers).toMatchObject({ "X-App-Code": "huwaa" });
|
||||
});
|
||||
});
|
||||
|
||||
test("system message push fanout API keeps existing operations path", async () => {
|
||||
vi.stubGlobal(
|
||||
"fetch",
|
||||
|
||||
@ -100,181 +100,201 @@ export function deleteH5Link(appCode: string, key: EntityId): Promise<{ deleted:
|
||||
}
|
||||
|
||||
function appScopeHeaders(appCode: string) {
|
||||
// H5 配置是强 App 隔离数据;显式固定请求头可避免用户切换 App 时全局请求上下文变化导致写入错误租户。
|
||||
// APP 配置全部是强 App 隔离数据;显式固定请求头可避免切换 App 时全局请求上下文变化导致写入错误租户。
|
||||
return { "X-App-Code": String(appCode || "").trim().toLowerCase() };
|
||||
}
|
||||
|
||||
export function listExploreTabs(query: PageQuery = {}): Promise<ApiList<ExploreTabDto>> {
|
||||
export function listExploreTabs(appCode: string, query: PageQuery = {}): Promise<ApiList<ExploreTabDto>> {
|
||||
const endpoint = API_ENDPOINTS.listExploreTabs;
|
||||
return apiRequest<ApiList<ExploreTabDto>>(apiEndpointPath(API_OPERATIONS.listExploreTabs), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
export function createExploreTab(payload: ExploreTabPayload): Promise<ExploreTabDto> {
|
||||
export function createExploreTab(appCode: string, payload: ExploreTabPayload): Promise<ExploreTabDto> {
|
||||
const endpoint = API_ENDPOINTS.createExploreTab;
|
||||
return apiRequest<ExploreTabDto, ExploreTabPayload>(apiEndpointPath(API_OPERATIONS.createExploreTab), {
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateExploreTab(tabId: EntityId, payload: ExploreTabPayload): Promise<ExploreTabDto> {
|
||||
export function updateExploreTab(appCode: string, tabId: EntityId, payload: ExploreTabPayload): Promise<ExploreTabDto> {
|
||||
const endpoint = API_ENDPOINTS.updateExploreTab;
|
||||
return apiRequest<ExploreTabDto, ExploreTabPayload>(
|
||||
apiEndpointPath(API_OPERATIONS.updateExploreTab, { tab_id: tabId }),
|
||||
{
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function deleteExploreTab(tabId: EntityId): Promise<{ deleted: boolean }> {
|
||||
export function deleteExploreTab(appCode: string, tabId: EntityId): Promise<{ deleted: boolean }> {
|
||||
const endpoint = API_ENDPOINTS.deleteExploreTab;
|
||||
return apiRequest<{ deleted: boolean }>(apiEndpointPath(API_OPERATIONS.deleteExploreTab, { tab_id: tabId }), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function listBanners(query: PageQuery = {}): Promise<ApiList<AppBannerDto>> {
|
||||
export function listBanners(appCode: string, query: PageQuery = {}): Promise<ApiList<AppBannerDto>> {
|
||||
const endpoint = API_ENDPOINTS.listBanners;
|
||||
return apiRequest<ApiList<AppBannerDto>>(apiEndpointPath(API_OPERATIONS.listBanners), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
export function createBanner(payload: AppBannerPayload): Promise<AppBannerDto> {
|
||||
export function createBanner(appCode: string, payload: AppBannerPayload): Promise<AppBannerDto> {
|
||||
const endpoint = API_ENDPOINTS.createBanner;
|
||||
return apiRequest<AppBannerDto, AppBannerPayload>(apiEndpointPath(API_OPERATIONS.createBanner), {
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateBanner(bannerId: EntityId, payload: AppBannerPayload): Promise<AppBannerDto> {
|
||||
export function updateBanner(appCode: string, bannerId: EntityId, payload: AppBannerPayload): Promise<AppBannerDto> {
|
||||
const endpoint = API_ENDPOINTS.updateBanner;
|
||||
return apiRequest<AppBannerDto, AppBannerPayload>(
|
||||
apiEndpointPath(API_OPERATIONS.updateBanner, { banner_id: bannerId }),
|
||||
{
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function deleteBanner(bannerId: EntityId): Promise<{ deleted: boolean }> {
|
||||
export function deleteBanner(appCode: string, bannerId: EntityId): Promise<{ deleted: boolean }> {
|
||||
const endpoint = API_ENDPOINTS.deleteBanner;
|
||||
return apiRequest<{ deleted: boolean }>(apiEndpointPath(API_OPERATIONS.deleteBanner, { banner_id: bannerId }), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function listSplashScreens(query: PageQuery = {}): Promise<ApiList<AppSplashScreenDto>> {
|
||||
export function listSplashScreens(appCode: string, query: PageQuery = {}): Promise<ApiList<AppSplashScreenDto>> {
|
||||
const endpoint = API_ENDPOINTS.listSplashScreens;
|
||||
return apiRequest<ApiList<AppSplashScreenDto>>(apiEndpointPath(API_OPERATIONS.listSplashScreens), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
export function createSplashScreen(payload: AppSplashScreenPayload): Promise<AppSplashScreenDto> {
|
||||
export function createSplashScreen(appCode: string, payload: AppSplashScreenPayload): Promise<AppSplashScreenDto> {
|
||||
const endpoint = API_ENDPOINTS.createSplashScreen;
|
||||
return apiRequest<AppSplashScreenDto, AppSplashScreenPayload>(apiEndpointPath(API_OPERATIONS.createSplashScreen), {
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateSplashScreen(splashId: EntityId, payload: AppSplashScreenPayload): Promise<AppSplashScreenDto> {
|
||||
export function updateSplashScreen(appCode: string, splashId: EntityId, payload: AppSplashScreenPayload): Promise<AppSplashScreenDto> {
|
||||
const endpoint = API_ENDPOINTS.updateSplashScreen;
|
||||
return apiRequest<AppSplashScreenDto, AppSplashScreenPayload>(
|
||||
apiEndpointPath(API_OPERATIONS.updateSplashScreen, { splash_id: splashId }),
|
||||
{
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function deleteSplashScreen(splashId: EntityId): Promise<{ deleted: boolean }> {
|
||||
export function deleteSplashScreen(appCode: string, splashId: EntityId): Promise<{ deleted: boolean }> {
|
||||
const endpoint = API_ENDPOINTS.deleteSplashScreen;
|
||||
return apiRequest<{ deleted: boolean }>(
|
||||
apiEndpointPath(API_OPERATIONS.deleteSplashScreen, { splash_id: splashId }),
|
||||
{
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function listPopups(query: PageQuery = {}): Promise<ApiList<AppPopupDto>> {
|
||||
export function listPopups(appCode: string, query: PageQuery = {}): Promise<ApiList<AppPopupDto>> {
|
||||
const endpoint = API_ENDPOINTS.listPopups;
|
||||
return apiRequest<ApiList<AppPopupDto>>(apiEndpointPath(API_OPERATIONS.listPopups), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
export function createPopup(payload: AppPopupPayload): Promise<AppPopupDto> {
|
||||
export function createPopup(appCode: string, payload: AppPopupPayload): Promise<AppPopupDto> {
|
||||
const endpoint = API_ENDPOINTS.createPopup;
|
||||
return apiRequest<AppPopupDto, AppPopupPayload>(apiEndpointPath(API_OPERATIONS.createPopup), {
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function updatePopup(popupId: EntityId, payload: AppPopupPayload): Promise<AppPopupDto> {
|
||||
export function updatePopup(appCode: string, popupId: EntityId, payload: AppPopupPayload): Promise<AppPopupDto> {
|
||||
const endpoint = API_ENDPOINTS.updatePopup;
|
||||
return apiRequest<AppPopupDto, AppPopupPayload>(
|
||||
apiEndpointPath(API_OPERATIONS.updatePopup, { popup_id: popupId }),
|
||||
{
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function deletePopup(popupId: EntityId): Promise<{ deleted: boolean }> {
|
||||
export function deletePopup(appCode: string, popupId: EntityId): Promise<{ deleted: boolean }> {
|
||||
const endpoint = API_ENDPOINTS.deletePopup;
|
||||
return apiRequest<{ deleted: boolean }>(apiEndpointPath(API_OPERATIONS.deletePopup, { popup_id: popupId }), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function listAppVersions(query: PageQuery = {}): Promise<ApiList<AppVersionDto>> {
|
||||
export function listAppVersions(appCode: string, query: PageQuery = {}): Promise<ApiList<AppVersionDto>> {
|
||||
const endpoint = API_ENDPOINTS.listAppVersions;
|
||||
return apiRequest<ApiList<AppVersionDto>>(apiEndpointPath(API_OPERATIONS.listAppVersions), {
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
export function createAppVersion(payload: AppVersionPayload): Promise<AppVersionDto> {
|
||||
export function createAppVersion(appCode: string, payload: AppVersionPayload): Promise<AppVersionDto> {
|
||||
const endpoint = API_ENDPOINTS.createAppVersion;
|
||||
return apiRequest<AppVersionDto, AppVersionPayload>(apiEndpointPath(API_OPERATIONS.createAppVersion), {
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
});
|
||||
}
|
||||
|
||||
export function updateAppVersion(versionId: EntityId, payload: AppVersionPayload): Promise<AppVersionDto> {
|
||||
export function updateAppVersion(appCode: string, versionId: EntityId, payload: AppVersionPayload): Promise<AppVersionDto> {
|
||||
const endpoint = API_ENDPOINTS.updateAppVersion;
|
||||
return apiRequest<AppVersionDto, AppVersionPayload>(
|
||||
apiEndpointPath(API_OPERATIONS.updateAppVersion, { version_id: versionId }),
|
||||
{
|
||||
body: payload,
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function deleteAppVersion(versionId: EntityId): Promise<{ deleted: boolean }> {
|
||||
export function deleteAppVersion(appCode: string, versionId: EntityId): Promise<{ deleted: boolean }> {
|
||||
const endpoint = API_ENDPOINTS.deleteAppVersion;
|
||||
return apiRequest<{ deleted: boolean }>(
|
||||
apiEndpointPath(API_OPERATIONS.deleteAppVersion, { version_id: versionId }),
|
||||
{
|
||||
headers: appScopeHeaders(appCode),
|
||||
method: endpoint.method,
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
|
||||
import { createAppVersion, deleteAppVersion, listAppVersions, updateAppVersion } from "@/features/app-config/api";
|
||||
import { useAppConfigAbilities } from "@/features/app-config/permissions.js";
|
||||
import { appVersionSchema } from "@/features/app-config/schema";
|
||||
@ -19,6 +20,7 @@ const emptyForm = () => ({
|
||||
});
|
||||
|
||||
export function useAppVersionsPage() {
|
||||
const { appCode } = useAppScope();
|
||||
const abilities = useAppConfigAbilities();
|
||||
const confirm = useConfirm();
|
||||
const { showToast } = useToast();
|
||||
@ -30,18 +32,26 @@ export function useAppVersionsPage() {
|
||||
const [loadingAction, setLoadingAction] = useState("");
|
||||
|
||||
const filters = useMemo(() => ({ keyword, platform }), [keyword, platform]);
|
||||
const queryFn = useCallback(() => listAppVersions(filters), [filters]);
|
||||
const queryFn = useCallback(() => listAppVersions(appCode, filters), [appCode, filters]);
|
||||
const {
|
||||
data = emptyData,
|
||||
error,
|
||||
loading,
|
||||
reload
|
||||
} = useAdminQuery(queryFn, {
|
||||
enabled: Boolean(appCode),
|
||||
errorMessage: "加载版本配置失败",
|
||||
initialData: emptyData,
|
||||
queryKey: ["app-config", "versions", filters]
|
||||
queryKey: ["app-config", "versions", appCode, filters]
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 安装包和强更策略必须按 App 隔离;切换 App 后清除旧版本编辑态,避免发布到错误租户。
|
||||
setActiveAction("");
|
||||
setEditingItem(null);
|
||||
setFormState(emptyForm());
|
||||
}, [appCode]);
|
||||
|
||||
const setForm = (patch) => {
|
||||
setFormState((current) => ({ ...current, ...patch }));
|
||||
};
|
||||
@ -76,10 +86,10 @@ export function useAppVersionsPage() {
|
||||
setLoadingAction(action);
|
||||
try {
|
||||
if (editingItem) {
|
||||
await updateAppVersion(editingItem.id, payload);
|
||||
await updateAppVersion(appCode, editingItem.id, payload);
|
||||
showToast("版本配置已更新", "success");
|
||||
} else {
|
||||
await createAppVersion(payload);
|
||||
await createAppVersion(appCode, payload);
|
||||
showToast("版本配置已新增", "success");
|
||||
}
|
||||
closeDialog();
|
||||
@ -103,7 +113,7 @@ export function useAppVersionsPage() {
|
||||
}
|
||||
setLoadingAction(`delete:${item.id}`);
|
||||
try {
|
||||
await deleteAppVersion(item.id);
|
||||
await deleteAppVersion(appCode, item.id);
|
||||
await reload();
|
||||
showToast("版本配置已删除", "success");
|
||||
} catch (err) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
|
||||
import { createBanner, deleteBanner, listBanners, updateBanner } from "@/features/app-config/api";
|
||||
import { useAppConfigAbilities } from "@/features/app-config/permissions.js";
|
||||
import { appBannerSchema } from "@/features/app-config/schema";
|
||||
@ -28,6 +29,7 @@ const emptyForm = () => ({
|
||||
});
|
||||
|
||||
export function useBannerConfigPage() {
|
||||
const { appCode } = useAppScope();
|
||||
const abilities = useAppConfigAbilities();
|
||||
const confirm = useConfirm();
|
||||
const { showToast } = useToast();
|
||||
@ -55,18 +57,26 @@ export function useBannerConfigPage() {
|
||||
}),
|
||||
[countryCode, displayScope, keyword, platform, regionId, status],
|
||||
);
|
||||
const queryFn = useCallback(() => listBanners(filters), [filters]);
|
||||
const queryFn = useCallback(() => listBanners(appCode, filters), [appCode, filters]);
|
||||
const {
|
||||
data = emptyData,
|
||||
error,
|
||||
loading,
|
||||
reload,
|
||||
} = useAdminQuery(queryFn, {
|
||||
enabled: Boolean(appCode),
|
||||
errorMessage: "加载 BANNER 配置失败",
|
||||
initialData: emptyData,
|
||||
queryKey: ["app-config", "banners", filters],
|
||||
queryKey: ["app-config", "banners", appCode, filters],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 切换 App 后丢弃旧租户表单;已发出的请求仍携带旧 appCode,只会回写旧租户缓存键。
|
||||
setActiveAction("");
|
||||
setEditingItem(null);
|
||||
setFormState(emptyForm());
|
||||
}, [appCode]);
|
||||
|
||||
const setForm = (patch) => {
|
||||
setFormState((current) => ({ ...current, ...patch }));
|
||||
};
|
||||
@ -105,10 +115,10 @@ export function useBannerConfigPage() {
|
||||
setLoadingAction(action);
|
||||
try {
|
||||
if (editingItem) {
|
||||
await updateBanner(editingItem.id, payload);
|
||||
await updateBanner(appCode, editingItem.id, payload);
|
||||
showToast("BANNER 已更新", "success");
|
||||
} else {
|
||||
await createBanner(payload);
|
||||
await createBanner(appCode, payload);
|
||||
showToast("BANNER 已新增", "success");
|
||||
}
|
||||
closeDialog();
|
||||
@ -132,7 +142,7 @@ export function useBannerConfigPage() {
|
||||
}
|
||||
setLoadingAction(`delete:${item.id}`);
|
||||
try {
|
||||
await deleteBanner(item.id);
|
||||
await deleteBanner(appCode, item.id);
|
||||
await reload();
|
||||
showToast("BANNER 已删除", "success");
|
||||
} catch (err) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
|
||||
import { createExploreTab, deleteExploreTab, listExploreTabs, updateExploreTab } from "@/features/app-config/api";
|
||||
import { useAppConfigAbilities } from "@/features/app-config/permissions.js";
|
||||
import { exploreTabSchema } from "@/features/app-config/schema";
|
||||
@ -17,6 +18,7 @@ const emptyForm = () => ({
|
||||
});
|
||||
|
||||
export function useExploreConfigPage() {
|
||||
const { appCode } = useAppScope();
|
||||
const abilities = useAppConfigAbilities();
|
||||
const confirm = useConfirm();
|
||||
const { showToast } = useToast();
|
||||
@ -28,18 +30,26 @@ export function useExploreConfigPage() {
|
||||
const [loadingAction, setLoadingAction] = useState("");
|
||||
|
||||
const filters = useMemo(() => ({ enabled, keyword }), [enabled, keyword]);
|
||||
const queryFn = useCallback(() => listExploreTabs(filters), [filters]);
|
||||
const queryFn = useCallback(() => listExploreTabs(appCode, filters), [appCode, filters]);
|
||||
const {
|
||||
data = emptyData,
|
||||
error,
|
||||
loading,
|
||||
reload,
|
||||
} = useAdminQuery(queryFn, {
|
||||
enabled: Boolean(appCode),
|
||||
errorMessage: "加载 Explore 配置失败",
|
||||
initialData: emptyData,
|
||||
queryKey: ["app-config", "explore-tabs", filters],
|
||||
queryKey: ["app-config", "explore-tabs", appCode, filters],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Explore tab 的文案和 H5 地址属于 App 品牌内容,切换 App 后不能保留旧租户编辑态。
|
||||
setActiveAction("");
|
||||
setEditingItem(null);
|
||||
setFormState(emptyForm());
|
||||
}, [appCode]);
|
||||
|
||||
const setForm = (patch) => {
|
||||
setFormState((current) => ({ ...current, ...patch }));
|
||||
};
|
||||
@ -74,10 +84,10 @@ export function useExploreConfigPage() {
|
||||
setLoadingAction(action);
|
||||
try {
|
||||
if (editingItem) {
|
||||
await updateExploreTab(editingItem.id, payload);
|
||||
await updateExploreTab(appCode, editingItem.id, payload);
|
||||
showToast("Explore 配置已更新", "success");
|
||||
} else {
|
||||
await createExploreTab(payload);
|
||||
await createExploreTab(appCode, payload);
|
||||
showToast("Explore 配置已新增", "success");
|
||||
}
|
||||
closeDialog();
|
||||
@ -92,7 +102,7 @@ export function useExploreConfigPage() {
|
||||
const toggleExploreTab = async (item, nextEnabled) => {
|
||||
setLoadingAction(`toggle:${item.id}`);
|
||||
try {
|
||||
await updateExploreTab(item.id, {
|
||||
await updateExploreTab(appCode, item.id, {
|
||||
enabled: nextEnabled,
|
||||
h5Url: item.h5Url || "",
|
||||
sortOrder: item.sortOrder || 0,
|
||||
@ -119,7 +129,7 @@ export function useExploreConfigPage() {
|
||||
}
|
||||
setLoadingAction(`delete:${item.id}`);
|
||||
try {
|
||||
await deleteExploreTab(item.id);
|
||||
await deleteExploreTab(appCode, item.id);
|
||||
await reload();
|
||||
showToast("Explore 配置已删除", "success");
|
||||
} catch (err) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
|
||||
import { createPopup, deletePopup, listPopups, updatePopup } from "@/features/app-config/api";
|
||||
import { useAppConfigAbilities } from "@/features/app-config/permissions.js";
|
||||
import { appPopupSchema } from "@/features/app-config/schema";
|
||||
@ -23,6 +24,7 @@ const emptyForm = () => ({
|
||||
});
|
||||
|
||||
export function usePopupConfigPage() {
|
||||
const { appCode } = useAppScope();
|
||||
const abilities = useAppConfigAbilities();
|
||||
const confirm = useConfirm();
|
||||
const { showToast } = useToast();
|
||||
@ -40,18 +42,26 @@ export function usePopupConfigPage() {
|
||||
}),
|
||||
[keyword, status],
|
||||
);
|
||||
const queryFn = useCallback(() => listPopups(filters), [filters]);
|
||||
const queryFn = useCallback(() => listPopups(appCode, filters), [appCode, filters]);
|
||||
const {
|
||||
data = emptyData,
|
||||
error,
|
||||
loading,
|
||||
reload,
|
||||
} = useAdminQuery(queryFn, {
|
||||
enabled: Boolean(appCode),
|
||||
errorMessage: "加载弹窗配置失败",
|
||||
initialData: emptyData,
|
||||
queryKey: ["app-config", "popups", filters],
|
||||
queryKey: ["app-config", "popups", appCode, filters],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 弹窗 code 只在单个 App 内唯一;切换时必须丢弃旧编辑态,不能把旧租户内容复制到新租户。
|
||||
setActiveAction("");
|
||||
setEditingItem(null);
|
||||
setFormState(emptyForm());
|
||||
}, [appCode]);
|
||||
|
||||
const setForm = (patch) => {
|
||||
setFormState((current) => ({ ...current, ...patch }));
|
||||
};
|
||||
@ -86,10 +96,10 @@ export function usePopupConfigPage() {
|
||||
setLoadingAction(action);
|
||||
try {
|
||||
if (editingItem) {
|
||||
await updatePopup(editingItem.id, payload);
|
||||
await updatePopup(appCode, editingItem.id, payload);
|
||||
showToast("弹窗配置已更新", "success");
|
||||
} else {
|
||||
await createPopup(payload);
|
||||
await createPopup(appCode, payload);
|
||||
showToast("弹窗配置已新增", "success");
|
||||
}
|
||||
closeDialog();
|
||||
@ -113,7 +123,7 @@ export function usePopupConfigPage() {
|
||||
}
|
||||
setLoadingAction(`delete:${item.id}`);
|
||||
try {
|
||||
await deletePopup(item.id);
|
||||
await deletePopup(appCode, item.id);
|
||||
await reload();
|
||||
showToast("弹窗配置已删除", "success");
|
||||
} catch (err) {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAppScope } from "@/app/app-scope/AppScopeProvider.jsx";
|
||||
import {
|
||||
createSplashScreen,
|
||||
deleteSplashScreen,
|
||||
@ -32,6 +33,7 @@ const emptyForm = () => ({
|
||||
});
|
||||
|
||||
export function useSplashScreenConfigPage() {
|
||||
const { appCode } = useAppScope();
|
||||
const abilities = useAppConfigAbilities();
|
||||
const confirm = useConfirm();
|
||||
const { showToast } = useToast();
|
||||
@ -57,18 +59,26 @@ export function useSplashScreenConfigPage() {
|
||||
}),
|
||||
[countryCode, keyword, platform, regionId, status],
|
||||
);
|
||||
const queryFn = useCallback(() => listSplashScreens(filters), [filters]);
|
||||
const queryFn = useCallback(() => listSplashScreens(appCode, filters), [appCode, filters]);
|
||||
const {
|
||||
data = emptyData,
|
||||
error,
|
||||
loading,
|
||||
reload,
|
||||
} = useAdminQuery(queryFn, {
|
||||
enabled: Boolean(appCode),
|
||||
errorMessage: "加载开屏配置失败",
|
||||
initialData: emptyData,
|
||||
queryKey: ["app-config", "splash-screens", filters],
|
||||
queryKey: ["app-config", "splash-screens", appCode, filters],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// 开屏配置按 App 独立;切换时关闭旧表单,避免旧图片和投放条件被带到新 App。
|
||||
setActiveAction("");
|
||||
setEditingItem(null);
|
||||
setFormState(emptyForm());
|
||||
}, [appCode]);
|
||||
|
||||
const setForm = (patch) => {
|
||||
setFormState((current) => ({ ...current, ...patch }));
|
||||
};
|
||||
@ -106,10 +116,10 @@ export function useSplashScreenConfigPage() {
|
||||
setLoadingAction(action);
|
||||
try {
|
||||
if (editingItem) {
|
||||
await updateSplashScreen(editingItem.id, payload);
|
||||
await updateSplashScreen(appCode, editingItem.id, payload);
|
||||
showToast("开屏配置已更新", "success");
|
||||
} else {
|
||||
await createSplashScreen(payload);
|
||||
await createSplashScreen(appCode, payload);
|
||||
showToast("开屏配置已新增", "success");
|
||||
}
|
||||
closeDialog();
|
||||
@ -133,7 +143,7 @@ export function useSplashScreenConfigPage() {
|
||||
}
|
||||
setLoadingAction(`delete:${item.id}`);
|
||||
try {
|
||||
await deleteSplashScreen(item.id);
|
||||
await deleteSplashScreen(appCode, item.id);
|
||||
await reload();
|
||||
showToast("开屏配置已删除", "success");
|
||||
} catch (err) {
|
||||
|
||||
136
src/shared/api/generated/schema.d.ts
vendored
136
src/shared/api/generated/schema.d.ts
vendored
@ -855,7 +855,9 @@ export interface paths {
|
||||
"/admin/app-config/banners": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -871,7 +873,9 @@ export interface paths {
|
||||
"/admin/app-config/banners/{banner_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -887,7 +891,9 @@ export interface paths {
|
||||
"/admin/app-config/splash-screens": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -903,7 +909,9 @@ export interface paths {
|
||||
"/admin/app-config/splash-screens/{splash_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -919,7 +927,9 @@ export interface paths {
|
||||
"/admin/app-config/popups": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -935,7 +945,9 @@ export interface paths {
|
||||
"/admin/app-config/popups/{popup_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -987,7 +999,9 @@ export interface paths {
|
||||
"/admin/app-config/explore-tabs": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -1003,7 +1017,9 @@ export interface paths {
|
||||
"/admin/app-config/explore-tabs/{tab_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -1019,7 +1035,9 @@ export interface paths {
|
||||
"/admin/app-config/versions": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -1035,7 +1053,9 @@ export interface paths {
|
||||
"/admin/app-config/versions/{version_id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -5725,7 +5745,11 @@ export interface components {
|
||||
providerStatus?: string;
|
||||
providerPayType?: string;
|
||||
receiveAddress?: string;
|
||||
orderDate?: string;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description 订单业务时间;历史订单为 0 时回退到 createdAtMs
|
||||
*/
|
||||
orderDateMs?: number;
|
||||
status: string;
|
||||
verifyStatus: string;
|
||||
grantStatus: string;
|
||||
@ -5783,6 +5807,11 @@ export interface components {
|
||||
usdAmount: number;
|
||||
/** @description 补单时为 true;订单正常计入充值,但服务端强制金币数为 0 */
|
||||
isMakeup?: boolean;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description 订单业务时间;未传时服务端默认为当前时间
|
||||
*/
|
||||
orderDateMs?: number;
|
||||
/** @enum {string} */
|
||||
providerCode: "mifapay" | "v5pay" | "usdt";
|
||||
externalOrderNo: string;
|
||||
@ -5860,6 +5889,11 @@ export interface components {
|
||||
chain?: "TRON" | "BSC";
|
||||
usdAmount?: number;
|
||||
usdMinorAmount?: number;
|
||||
/**
|
||||
* Format: int64
|
||||
* @description 订单业务时间,用于三方凭证按日期查询
|
||||
*/
|
||||
orderDateMs?: number;
|
||||
providerCurrencyCode?: string;
|
||||
providerAmountMinor?: number;
|
||||
};
|
||||
@ -7570,7 +7604,9 @@ export interface operations {
|
||||
listBanners: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7582,7 +7618,9 @@ export interface operations {
|
||||
createBanner: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7594,7 +7632,9 @@ export interface operations {
|
||||
updateBanner: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
banner_id: number;
|
||||
};
|
||||
@ -7608,7 +7648,9 @@ export interface operations {
|
||||
deleteBanner: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
banner_id: number;
|
||||
};
|
||||
@ -7622,7 +7664,9 @@ export interface operations {
|
||||
listSplashScreens: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7634,7 +7678,9 @@ export interface operations {
|
||||
createSplashScreen: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7646,7 +7692,9 @@ export interface operations {
|
||||
updateSplashScreen: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
splash_id: number;
|
||||
};
|
||||
@ -7660,7 +7708,9 @@ export interface operations {
|
||||
deleteSplashScreen: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
splash_id: number;
|
||||
};
|
||||
@ -7674,7 +7724,9 @@ export interface operations {
|
||||
listPopups: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7686,7 +7738,9 @@ export interface operations {
|
||||
createPopup: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7698,7 +7752,9 @@ export interface operations {
|
||||
updatePopup: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
popup_id: number;
|
||||
};
|
||||
@ -7712,7 +7768,9 @@ export interface operations {
|
||||
deletePopup: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
popup_id: number;
|
||||
};
|
||||
@ -7812,7 +7870,9 @@ export interface operations {
|
||||
listExploreTabs: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7824,7 +7884,9 @@ export interface operations {
|
||||
createExploreTab: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7836,7 +7898,9 @@ export interface operations {
|
||||
updateExploreTab: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
tab_id: number;
|
||||
};
|
||||
@ -7850,7 +7914,9 @@ export interface operations {
|
||||
deleteExploreTab: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
tab_id: number;
|
||||
};
|
||||
@ -7864,7 +7930,9 @@ export interface operations {
|
||||
listAppVersions: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7876,7 +7944,9 @@ export interface operations {
|
||||
createAppVersion: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
@ -7888,7 +7958,9 @@ export interface operations {
|
||||
updateAppVersion: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
version_id: number;
|
||||
};
|
||||
@ -7902,7 +7974,9 @@ export interface operations {
|
||||
deleteAppVersion: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
header: {
|
||||
"X-App-Code": components["parameters"]["AppCodeHeader"];
|
||||
};
|
||||
path: {
|
||||
version_id: number;
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user