更新設備選擇組件,新增獲客場景選項,調整篩選邏輯以支持多種篩選條件,並修正路由以符合新結構。
This commit is contained in:
18
Cunkebao/dist/.vite/manifest.json
vendored
18
Cunkebao/dist/.vite/manifest.json
vendored
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"_charts-TuAbbBZ5.js": {
|
||||
"file": "assets/charts-TuAbbBZ5.js",
|
||||
"_charts-D0fT04H8.js": {
|
||||
"file": "assets/charts-D0fT04H8.js",
|
||||
"name": "charts",
|
||||
"imports": [
|
||||
"_ui-D1w-jetn.js",
|
||||
"_ui-qLeQLv1F.js",
|
||||
"_vendor-2vc8h_ct.js"
|
||||
]
|
||||
},
|
||||
@@ -11,8 +11,8 @@
|
||||
"file": "assets/ui-D0C0OGrH.css",
|
||||
"src": "_ui-D0C0OGrH.css"
|
||||
},
|
||||
"_ui-D1w-jetn.js": {
|
||||
"file": "assets/ui-D1w-jetn.js",
|
||||
"_ui-qLeQLv1F.js": {
|
||||
"file": "assets/ui-qLeQLv1F.js",
|
||||
"name": "ui",
|
||||
"imports": [
|
||||
"_vendor-2vc8h_ct.js"
|
||||
@@ -33,18 +33,18 @@
|
||||
"name": "vendor"
|
||||
},
|
||||
"index.html": {
|
||||
"file": "assets/index-DTZ_ow5W.js",
|
||||
"file": "assets/index-Cp05akVy.js",
|
||||
"name": "index",
|
||||
"src": "index.html",
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"_vendor-2vc8h_ct.js",
|
||||
"_ui-D1w-jetn.js",
|
||||
"_ui-qLeQLv1F.js",
|
||||
"_utils-6WF66_dS.js",
|
||||
"_charts-TuAbbBZ5.js"
|
||||
"_charts-D0fT04H8.js"
|
||||
],
|
||||
"css": [
|
||||
"assets/index-B0SB167P.css"
|
||||
"assets/index-Eg_DAu9e.css"
|
||||
]
|
||||
}
|
||||
}
|
||||
10
Cunkebao/dist/index.html
vendored
10
Cunkebao/dist/index.html
vendored
@@ -10,14 +10,14 @@
|
||||
}
|
||||
</style>
|
||||
<!-- 引入 uni-app web-view SDK(必须) -->
|
||||
<script type="text/javascript" src="./websdk.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-DTZ_ow5W.js"></script>
|
||||
<script type="text/javascript" src="/websdk.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-Cp05akVy.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-2vc8h_ct.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/ui-D1w-jetn.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/ui-qLeQLv1F.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/utils-6WF66_dS.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-TuAbbBZ5.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/charts-D0fT04H8.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/ui-D0C0OGrH.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B0SB167P.css">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Eg_DAu9e.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
}
|
||||
</style>
|
||||
<!-- 引入 uni-app web-view SDK(必须) -->
|
||||
<script type="text/javascript" src="./websdk.js"></script>
|
||||
<script type="text/javascript" src="/websdk.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -46,6 +46,12 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
onSelect(selectedOptions.filter(v => v.id !== id));
|
||||
};
|
||||
|
||||
// 清除所有已选设备
|
||||
const handleClearAll = () => {
|
||||
if (readonly) return;
|
||||
onSelect([]);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* mode=input 显示输入框,mode=dialog不显示 */}
|
||||
@@ -57,6 +63,7 @@ const DeviceSelection: React.FC<DeviceSelectionProps> = ({
|
||||
onClick={openPopup}
|
||||
prefix={<SearchOutlined />}
|
||||
allowClear={!readonly}
|
||||
onClear={handleClearAll}
|
||||
size="large"
|
||||
readOnly={readonly}
|
||||
disabled={readonly}
|
||||
|
||||
@@ -64,7 +64,7 @@ const Mine: React.FC = () => {
|
||||
description: "管理用户流量池和分组",
|
||||
icon: <DatabaseOutlined />,
|
||||
count: stats.traffic,
|
||||
path: "/traffic-pool",
|
||||
path: "/mine/traffic-pool",
|
||||
bgColor: "#f9f0ff",
|
||||
iconColor: "#722ed1",
|
||||
},
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Popup } from "antd-mobile";
|
||||
import { Select, Button } from "antd";
|
||||
import DeviceSelection from "@/components/DeviceSelection";
|
||||
import type {
|
||||
DeviceOption,
|
||||
PackageOption,
|
||||
ValueLevel,
|
||||
UserStatus,
|
||||
ScenarioOption,
|
||||
} from "./data";
|
||||
|
||||
import { DeviceSelectionItem } from "@/components/DeviceSelection/data";
|
||||
|
||||
interface FilterModalProps {
|
||||
visible: boolean;
|
||||
onClose: () => void;
|
||||
deviceOptions: DeviceOption[];
|
||||
onConfirm: (filters: {
|
||||
deviceIds: string[];
|
||||
packageId: string;
|
||||
scenarioId: string;
|
||||
valueLevel: ValueLevel;
|
||||
userStatus: UserStatus;
|
||||
}) => void;
|
||||
packageOptions: PackageOption[];
|
||||
deviceId: string;
|
||||
setDeviceId: (v: string) => void;
|
||||
packageId: string;
|
||||
setPackageId: (v: string) => void;
|
||||
valueLevel: ValueLevel;
|
||||
setValueLevel: (v: ValueLevel) => void;
|
||||
userStatus: UserStatus;
|
||||
setUserStatus: (v: UserStatus) => void;
|
||||
onReset: () => void;
|
||||
scenarioOptions: ScenarioOption[];
|
||||
}
|
||||
|
||||
const valueLevelOptions = [
|
||||
@@ -41,78 +42,109 @@ const statusOptions = [
|
||||
const FilterModal: React.FC<FilterModalProps> = ({
|
||||
visible,
|
||||
onClose,
|
||||
deviceOptions,
|
||||
packageOptions,
|
||||
deviceId,
|
||||
setDeviceId,
|
||||
packageId,
|
||||
setPackageId,
|
||||
valueLevel,
|
||||
setValueLevel,
|
||||
userStatus,
|
||||
setUserStatus,
|
||||
onReset,
|
||||
}) => (
|
||||
<Popup
|
||||
visible={visible}
|
||||
onMaskClick={onClose}
|
||||
position="right"
|
||||
bodyStyle={{ width: "80vw", maxWidth: 360, padding: 24 }}
|
||||
>
|
||||
<div style={{ fontWeight: 600, fontSize: 18, marginBottom: 20 }}>
|
||||
筛选选项
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>设备</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={deviceId}
|
||||
onChange={setDeviceId}
|
||||
options={[
|
||||
{ label: "全部设备", value: "all" },
|
||||
...deviceOptions.map(d => ({ label: d.name, value: d.id })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>流量池</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={packageId}
|
||||
onChange={setPackageId}
|
||||
options={[
|
||||
{ label: "全部流量池", value: "all" },
|
||||
...packageOptions.map(p => ({ label: p.name, value: p.id })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>用户价值</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={valueLevel}
|
||||
onChange={v => setValueLevel(v as ValueLevel)}
|
||||
options={valueLevelOptions}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>添加状态</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={userStatus}
|
||||
onChange={v => setUserStatus(v as UserStatus)}
|
||||
options={statusOptions}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 12, marginTop: 32 }}>
|
||||
<Button onClick={onReset} style={{ flex: 1 }}>
|
||||
重置筛选
|
||||
</Button>
|
||||
<Button type="primary" onClick={onClose} style={{ flex: 1 }}>
|
||||
应用筛选
|
||||
</Button>
|
||||
</div>
|
||||
</Popup>
|
||||
);
|
||||
scenarioOptions,
|
||||
onConfirm,
|
||||
}) => {
|
||||
const [selectedDevices, setSelectedDevices] = useState<DeviceSelectionItem[]>(
|
||||
[],
|
||||
);
|
||||
const [packageId, setPackageId] = useState<string>("all");
|
||||
const [scenarioId, setScenarioId] = useState<string>("all");
|
||||
const [valueLevel, setValueLevel] = useState<ValueLevel>("all");
|
||||
const [userStatus, setUserStatus] = useState<UserStatus>("all");
|
||||
|
||||
const handleApply = () => {
|
||||
onConfirm({
|
||||
deviceIds: selectedDevices.map(d => d.id.toString()),
|
||||
packageId,
|
||||
scenarioId,
|
||||
valueLevel,
|
||||
userStatus,
|
||||
});
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setSelectedDevices([]);
|
||||
setPackageId("all");
|
||||
setScenarioId("all");
|
||||
setValueLevel("all");
|
||||
setUserStatus("all");
|
||||
};
|
||||
|
||||
return (
|
||||
<Popup
|
||||
visible={visible}
|
||||
onMaskClick={onClose}
|
||||
position="right"
|
||||
bodyStyle={{ width: "80vw", maxWidth: 360, padding: 24 }}
|
||||
>
|
||||
<div style={{ fontWeight: 600, fontSize: 18, marginBottom: 20 }}>
|
||||
筛选选项
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>设备</div>
|
||||
<DeviceSelection
|
||||
selectedOptions={selectedDevices}
|
||||
onSelect={setSelectedDevices}
|
||||
placeholder="选择设备"
|
||||
showSelectedList={false}
|
||||
selectedListMaxHeight={120}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>流量池</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={packageId}
|
||||
onChange={setPackageId}
|
||||
options={[
|
||||
{ label: "全部流量池", value: "all" },
|
||||
...packageOptions.map(p => ({ label: p.name, value: p.id })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>获客场景</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={scenarioId}
|
||||
onChange={setScenarioId}
|
||||
options={[
|
||||
{ label: "全部场景", value: "all" },
|
||||
...scenarioOptions.map(s => ({ label: s.name, value: s.id })),
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>用户价值</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={valueLevel}
|
||||
onChange={v => setValueLevel(v as ValueLevel)}
|
||||
options={valueLevelOptions}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<div style={{ marginBottom: 6 }}>添加状态</div>
|
||||
<Select
|
||||
style={{ width: "100%" }}
|
||||
value={userStatus}
|
||||
onChange={v => setUserStatus(v as UserStatus)}
|
||||
options={statusOptions}
|
||||
/>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 12, marginTop: 32 }}>
|
||||
<Button onClick={handleReset} style={{ flex: 1 }}>
|
||||
重置筛选
|
||||
</Button>
|
||||
<Button type="primary" onClick={handleApply} style={{ flex: 1 }}>
|
||||
应用筛选
|
||||
</Button>
|
||||
</div>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
|
||||
export default FilterModal;
|
||||
|
||||
@@ -17,3 +17,14 @@ export async function fetchPackageOptions(): Promise<any[]> {
|
||||
{ id: "pkg-2", name: "测试流量池" },
|
||||
];
|
||||
}
|
||||
|
||||
// 获取获客场景列表
|
||||
export async function fetchScenarioOptions(): Promise<any[]> {
|
||||
// TODO: 替换为真实接口
|
||||
return [
|
||||
{ id: "scenario-1", name: "朋友圈推广" },
|
||||
{ id: "scenario-2", name: "群聊引流" },
|
||||
{ id: "scenario-3", name: "公众号推广" },
|
||||
{ id: "scenario-4", name: "线下活动" },
|
||||
];
|
||||
}
|
||||
|
||||
@@ -43,3 +43,9 @@ export type ValueLevel = "all" | "high" | "medium" | "low";
|
||||
|
||||
// 状态类型
|
||||
export type UserStatus = "all" | "added" | "pending" | "failed" | "duplicate";
|
||||
|
||||
// 获客场景类型
|
||||
export interface ScenarioOption {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
import { fetchTrafficPoolList, fetchPackageOptions } from "./api";
|
||||
import {
|
||||
fetchTrafficPoolList,
|
||||
fetchPackageOptions,
|
||||
fetchScenarioOptions,
|
||||
} from "./api";
|
||||
import type {
|
||||
TrafficPoolUser,
|
||||
DeviceOption,
|
||||
PackageOption,
|
||||
ValueLevel,
|
||||
UserStatus,
|
||||
ScenarioOption,
|
||||
} from "./data";
|
||||
import { Toast } from "antd-mobile";
|
||||
|
||||
@@ -19,10 +24,11 @@ export function useTrafficPoolListLogic() {
|
||||
|
||||
// 筛选相关
|
||||
const [showFilter, setShowFilter] = useState(false);
|
||||
const [deviceOptions, setDeviceOptions] = useState<DeviceOption[]>([]);
|
||||
const [packageOptions, setPackageOptions] = useState<PackageOption[]>([]);
|
||||
const [deviceId, setDeviceId] = useState<string>("all");
|
||||
const [scenarioOptions, setScenarioOptions] = useState<ScenarioOption[]>([]);
|
||||
const [selectedDevices, setSelectedDevices] = useState<any[]>([]);
|
||||
const [packageId, setPackageId] = useState<string>("all");
|
||||
const [scenarioId, setScenarioId] = useState<string>("all");
|
||||
const [valueLevel, setValueLevel] = useState<ValueLevel>("all");
|
||||
const [userStatus, setUserStatus] = useState<UserStatus>("all");
|
||||
|
||||
@@ -47,15 +53,38 @@ export function useTrafficPoolListLogic() {
|
||||
const getList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await fetchTrafficPoolList({
|
||||
const params: any = {
|
||||
page,
|
||||
pageSize,
|
||||
keyword: search,
|
||||
// deviceId,
|
||||
// packageId,
|
||||
// valueLevel,
|
||||
// userStatus,
|
||||
});
|
||||
};
|
||||
|
||||
// 添加筛选参数
|
||||
if (selectedDevices.length > 0) {
|
||||
params.deviceId = selectedDevices.map(d => d.id).join(",");
|
||||
}
|
||||
if (packageId !== "all") {
|
||||
params.packageId = packageId;
|
||||
}
|
||||
if (scenarioId !== "all") {
|
||||
params.taskId = scenarioId;
|
||||
}
|
||||
if (valueLevel !== "all") {
|
||||
params.userValue =
|
||||
valueLevel === "high" ? 3 : valueLevel === "medium" ? 2 : 1;
|
||||
}
|
||||
if (userStatus !== "all") {
|
||||
params.addStatus =
|
||||
userStatus === "added"
|
||||
? 1
|
||||
: userStatus === "pending"
|
||||
? 0
|
||||
: userStatus === "failed"
|
||||
? -1
|
||||
: -2;
|
||||
}
|
||||
|
||||
const res = await fetchTrafficPoolList(params);
|
||||
setList(res.list || []);
|
||||
setTotal(res.total || 0);
|
||||
} finally {
|
||||
@@ -66,13 +95,22 @@ export function useTrafficPoolListLogic() {
|
||||
// 获取筛选项
|
||||
useEffect(() => {
|
||||
fetchPackageOptions().then(setPackageOptions);
|
||||
fetchScenarioOptions().then(setScenarioOptions);
|
||||
}, []);
|
||||
|
||||
// 筛选条件变化时刷新列表
|
||||
useEffect(() => {
|
||||
getList();
|
||||
// eslint-disable-next-line
|
||||
}, [page, search /*, deviceId, packageId, valueLevel, userStatus*/]);
|
||||
}, [
|
||||
page,
|
||||
search,
|
||||
selectedDevices,
|
||||
packageId,
|
||||
scenarioId,
|
||||
valueLevel,
|
||||
userStatus,
|
||||
]);
|
||||
|
||||
// 全选/反选
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
@@ -108,8 +146,9 @@ export function useTrafficPoolListLogic() {
|
||||
|
||||
// 筛选重置
|
||||
const resetFilter = () => {
|
||||
setDeviceId("all");
|
||||
setSelectedDevices([]);
|
||||
setPackageId("all");
|
||||
setScenarioId("all");
|
||||
setValueLevel("all");
|
||||
setUserStatus("all");
|
||||
};
|
||||
@@ -125,12 +164,14 @@ export function useTrafficPoolListLogic() {
|
||||
setSearch,
|
||||
showFilter,
|
||||
setShowFilter,
|
||||
deviceOptions,
|
||||
packageOptions,
|
||||
deviceId,
|
||||
setDeviceId,
|
||||
scenarioOptions,
|
||||
selectedDevices,
|
||||
setSelectedDevices,
|
||||
packageId,
|
||||
setPackageId,
|
||||
scenarioId,
|
||||
setScenarioId,
|
||||
valueLevel,
|
||||
setValueLevel,
|
||||
userStatus,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from "@ant-design/icons";
|
||||
import { Input, Button, Checkbox } from "antd";
|
||||
import styles from "./index.module.scss";
|
||||
import { List, Empty, Avatar, Modal, Selector, Toast, Card } from "antd-mobile";
|
||||
import { Empty, Avatar } from "antd-mobile";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import NavCommon from "@/components/NavCommon";
|
||||
import { useTrafficPoolListLogic } from "./dataAnyx";
|
||||
@@ -18,20 +18,6 @@ import BatchAddModal from "./BatchAddModal";
|
||||
const defaultAvatar =
|
||||
"https://cdn.jsdelivr.net/gh/maokaka/static/avatar-default.png";
|
||||
|
||||
const valueLevelOptions = [
|
||||
{ label: "全部", value: "all" },
|
||||
{ label: "高价值", value: "high" },
|
||||
{ label: "中价值", value: "medium" },
|
||||
{ label: "低价值", value: "low" },
|
||||
];
|
||||
const statusOptions = [
|
||||
{ label: "全部", value: "all" },
|
||||
{ label: "已添加", value: "added" },
|
||||
{ label: "待添加", value: "pending" },
|
||||
{ label: "添加失败", value: "failed" },
|
||||
{ label: "重复", value: "duplicate" },
|
||||
];
|
||||
|
||||
const TrafficPoolList: React.FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
@@ -45,12 +31,14 @@ const TrafficPoolList: React.FC = () => {
|
||||
setSearch,
|
||||
showFilter,
|
||||
setShowFilter,
|
||||
deviceOptions,
|
||||
packageOptions,
|
||||
deviceId,
|
||||
setDeviceId,
|
||||
scenarioOptions,
|
||||
selectedDevices,
|
||||
setSelectedDevices,
|
||||
packageId,
|
||||
setPackageId,
|
||||
scenarioId,
|
||||
setScenarioId,
|
||||
valueLevel,
|
||||
setValueLevel,
|
||||
userStatus,
|
||||
@@ -169,17 +157,26 @@ const TrafficPoolList: React.FC = () => {
|
||||
<FilterModal
|
||||
visible={showFilter}
|
||||
onClose={() => setShowFilter(false)}
|
||||
deviceOptions={deviceOptions}
|
||||
onConfirm={filters => {
|
||||
// 更新筛选条件
|
||||
setSelectedDevices(
|
||||
filters.deviceIds.map(id => ({
|
||||
id: parseInt(id),
|
||||
memo: "",
|
||||
imei: "",
|
||||
wechatId: "",
|
||||
status: "offline" as const,
|
||||
})),
|
||||
);
|
||||
setPackageId(filters.packageId);
|
||||
setScenarioId(filters.scenarioId);
|
||||
setValueLevel(filters.valueLevel);
|
||||
setUserStatus(filters.userStatus);
|
||||
// 重新获取列表
|
||||
getList();
|
||||
}}
|
||||
packageOptions={packageOptions}
|
||||
deviceId={deviceId}
|
||||
setDeviceId={setDeviceId}
|
||||
packageId={packageId}
|
||||
setPackageId={setPackageId}
|
||||
valueLevel={valueLevel}
|
||||
setValueLevel={setValueLevel}
|
||||
userStatus={userStatus}
|
||||
setUserStatus={setUserStatus}
|
||||
onReset={resetFilter}
|
||||
scenarioOptions={scenarioOptions}
|
||||
/>
|
||||
<div className={styles.listWrap}>
|
||||
{list.length === 0 && !loading ? (
|
||||
@@ -192,7 +189,9 @@ const TrafficPoolList: React.FC = () => {
|
||||
className={styles.card}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() =>
|
||||
navigate(`/traffic-pool/detail/${item.sourceId}/${item.id}`)
|
||||
navigate(
|
||||
`/mine/traffic-pool/detail/${item.sourceId}/${item.id}`,
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className={styles.cardContent}>
|
||||
|
||||
@@ -36,12 +36,12 @@ const routes = [
|
||||
auth: true,
|
||||
},
|
||||
{
|
||||
path: "/traffic-pool",
|
||||
path: "/mine/traffic-pool",
|
||||
element: <TrafficPool />,
|
||||
auth: true,
|
||||
},
|
||||
{
|
||||
path: "/traffic-pool/detail/:wxid/:userId",
|
||||
path: "/mine/traffic-pool/detail/:wxid/:userId",
|
||||
element: <TrafficPoolDetail />,
|
||||
auth: true,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user