diff --git a/src/features/host-org/api.test.ts b/src/features/host-org/api.test.ts
index b6a51ad..db07449 100644
--- a/src/features/host-org/api.test.ts
+++ b/src/features/host-org/api.test.ts
@@ -67,6 +67,7 @@ test("host org list APIs use generated admin paths and filters", async () => {
canGrantVehicle: true,
canTransferUserCountry: false,
contact: "+63",
+ status: "disabled",
});
await listHosts({ agency_id: 41, page: 1, page_size: 10, sort_by: "diamond", sort_direction: "desc" });
await listCoinSellers({
@@ -149,6 +150,7 @@ test("host org list APIs use generated admin paths and filters", async () => {
canGrantVehicle: true,
canTransferUserCountry: false,
contact: "+63",
+ status: "disabled",
});
expect(String(hostUrl)).toContain("/api/v1/admin/hosts?");
expect(String(hostUrl)).toContain("agency_id=41");
diff --git a/src/features/host-org/hooks/useHostManagersPage.js b/src/features/host-org/hooks/useHostManagersPage.js
index 991a0db..3f4b6c5 100644
--- a/src/features/host-org/hooks/useHostManagersPage.js
+++ b/src/features/host-org/hooks/useHostManagersPage.js
@@ -28,6 +28,12 @@ const emptyManagerForm = () => ({ contact: "", targetUserId: "", ...emptyPermiss
const managerPermissionPayload = (form) =>
Object.fromEntries(managerPermissionFields.map((field) => [field, form[field] !== false]));
+const managerStatusPayload = (item, status) => ({
+ contact: item?.contact || "",
+ status,
+ ...Object.fromEntries(managerPermissionFields.map((field) => [field, item?.[field] !== false])),
+});
+
const managerFormFromItem = (item) => ({
contact: item?.contact || "",
targetUserId: String(item?.userId || ""),
@@ -139,6 +145,21 @@ export function useHostManagersPage() {
setActiveAction("manager-edit");
};
+ const toggleManager = async (item, enabled) => {
+ const nextStatus = enabled ? "active" : "disabled";
+ setLoadingAction(`manager-status-${item.userId}`);
+ try {
+ // 状态接口复用经理更新入口;提交当前行的权限快照,避免只改状态时把已有权限开关覆盖成后端默认值。
+ await updateManager(item.userId, managerStatusPayload(item, nextStatus));
+ showToast(enabled ? "经理已启用" : "经理已停用", "success");
+ await reload();
+ } catch (err) {
+ showToast(err.message || (enabled ? "启用经理失败" : "停用经理失败"), "error");
+ } finally {
+ setLoadingAction("");
+ }
+ };
+
return {
abilities,
activeAction,
@@ -165,5 +186,6 @@ export function useHostManagersPage() {
setPage,
status,
submitManager,
+ toggleManager,
};
}
diff --git a/src/features/host-org/pages/HostManagersPage.jsx b/src/features/host-org/pages/HostManagersPage.jsx
index 738fa2c..d428c4a 100644
--- a/src/features/host-org/pages/HostManagersPage.jsx
+++ b/src/features/host-org/pages/HostManagersPage.jsx
@@ -6,7 +6,7 @@ import { formatMillis } from "@/shared/utils/time.js";
import { AdminSwitch } from "@/shared/ui/AdminSwitch.jsx";
import { DataState } from "@/shared/ui/DataState.jsx";
import { IconButton } from "@/shared/ui/IconButton.jsx";
-import { managerStatusFilters, statusLabels } from "@/features/host-org/constants.js";
+import { managerStatusFilters } from "@/features/host-org/constants.js";
import { HostOrgActionModal } from "@/features/host-org/components/HostOrgActionModal.jsx";
import { HostOrgPerson, hostOrgRegionName } from "@/features/host-org/components/HostOrgIdentity.jsx";
import { HostOrgTable } from "@/features/host-org/components/HostOrgTable.jsx";
@@ -55,7 +55,7 @@ const managerColumns = [
{
key: "status",
label: "状态",
- render: (item) => ,
+ render: (item, _index, context) => ,
width: "minmax(90px, 0.7fr)",
},
{
@@ -187,12 +187,14 @@ function ManagerUser({ item }) {
);
}
-function ManagerStatus({ item }) {
- const active = item.status === "active";
+function ManagerStatusSwitch({ item, page }) {
return (
-
- {statusLabels[item.status] || item.status || "-"}
-
+ page.toggleManager(item, event.target.checked)}
+ />
);
}
diff --git a/src/features/host-org/pages/HostManagersPage.test.jsx b/src/features/host-org/pages/HostManagersPage.test.jsx
new file mode 100644
index 0000000..52d0a56
--- /dev/null
+++ b/src/features/host-org/pages/HostManagersPage.test.jsx
@@ -0,0 +1,103 @@
+import { fireEvent, render, screen } from "@testing-library/react";
+import { afterEach, expect, test, vi } from "vitest";
+import { HostManagersPage } from "./HostManagersPage.jsx";
+import { useHostManagersPage } from "@/features/host-org/hooks/useHostManagersPage.js";
+
+const mocks = vi.hoisted(() => ({
+ toggleManager: vi.fn(),
+}));
+
+vi.mock("@/features/host-org/hooks/useHostManagersPage.js", () => ({
+ useHostManagersPage: vi.fn(),
+}));
+
+afterEach(() => {
+ vi.clearAllMocks();
+});
+
+test("manager status column uses a switch and toggles through the page hook", () => {
+ const manager = managerFixture();
+ vi.mocked(useHostManagersPage).mockReturnValue(pageFixture({ data: { items: [manager], page: 1, pageSize: 50, total: 1 } }));
+
+ render();
+
+ const statusSwitch = screen.getByRole("switch", { name: "停用经理" });
+ expect(statusSwitch).toBeChecked();
+
+ fireEvent.click(statusSwitch);
+
+ expect(mocks.toggleManager).toHaveBeenCalledWith(manager, false);
+});
+
+function pageFixture(patch = {}) {
+ return {
+ abilities: {
+ canCreate: true,
+ canUpdate: true,
+ canView: true,
+ },
+ activeAction: "",
+ changeQuery: vi.fn(),
+ changeRegionId: vi.fn(),
+ changeStatus: vi.fn(),
+ closeAction: vi.fn(),
+ data: { items: [], page: 1, pageSize: 50, total: 0 },
+ editingManager: null,
+ error: null,
+ loading: false,
+ loadingAction: "",
+ loadingRegions: false,
+ managerForm: {
+ canAddAdmin: true,
+ canAddBdLeader: true,
+ canAddSuperadmin: true,
+ canBlockUser: true,
+ canGrantAvatarFrame: true,
+ canGrantBadge: true,
+ canGrantVehicle: true,
+ canTransferUserCountry: true,
+ canUpdateUserLevel: true,
+ contact: "",
+ targetUserId: "",
+ },
+ openManagerEdit: vi.fn(),
+ openManagerForm: vi.fn(),
+ page: 1,
+ query: "",
+ regionId: "",
+ regionOptions: [],
+ reload: vi.fn(),
+ resetFilters: vi.fn(),
+ setManagerForm: vi.fn(),
+ setPage: vi.fn(),
+ status: "",
+ submitManager: vi.fn(),
+ toggleManager: mocks.toggleManager,
+ ...patch,
+ };
+}
+
+function managerFixture() {
+ return {
+ avatar: "",
+ bdLeaderCount: 3,
+ canAddAdmin: true,
+ canAddBdLeader: false,
+ canAddSuperadmin: true,
+ canBlockUser: true,
+ canGrantAvatarFrame: true,
+ canGrantBadge: true,
+ canGrantVehicle: true,
+ canTransferUserCountry: true,
+ canUpdateUserLevel: true,
+ contact: "+63 910 323 3670",
+ displayUserId: "167579",
+ lastInvitedAtMs: 1782198308000,
+ regionId: 1,
+ regionName: "欧亚美区",
+ status: "active",
+ updatedAtMs: 1782284840000,
+ userId: "10001",
+ username: "PH-MANAGER",
+ };
+}
diff --git a/src/shared/api/types.ts b/src/shared/api/types.ts
index 793f9c2..fac3286 100644
--- a/src/shared/api/types.ts
+++ b/src/shared/api/types.ts
@@ -607,6 +607,7 @@ export interface UpdateManagerPayload {
canTransferUserCountry?: boolean;
canUpdateUserLevel?: boolean;
contact?: string;
+ status?: "active" | "disabled";
}
export interface HostProfileDto {