Fix KOC resource fuzzy filters

This commit is contained in:
巫凤萍
2026-08-06 11:48:10 +08:00
parent 72f8862f8a
commit 1f910c975d
3 changed files with 69 additions and 39 deletions

View File

@@ -1377,8 +1377,8 @@ function ResourcesPage({
}) { }) {
const [query, setQuery] = useState(""); const [query, setQuery] = useState("");
const [platformFilter, setPlatformFilter] = useState("全部平台"); const [platformFilter, setPlatformFilter] = useState("全部平台");
const [ipFilter, setIpFilter] = useState("全部IP地区"); const [ipFilter, setIpFilter] = useState("");
const [sourceFilter, setSourceFilter] = useState("全部合作来源"); const [sourceFilter, setSourceFilter] = useState("");
const resourceAccounts = useMemo(() => { const resourceAccounts = useMemo(() => {
const deliveriesByAccount = new Map<string, Distribution[]>(); const deliveriesByAccount = new Map<string, Distribution[]>();
distributions.forEach((distribution) => { distributions.forEach((distribution) => {
@@ -1430,31 +1430,37 @@ function ResourcesPage({
); );
const filteredAccounts = useMemo(() => { const filteredAccounts = useMemo(() => {
const keyword = query.trim().toLocaleLowerCase("zh-CN"); const keyword = query.trim().toLocaleLowerCase("zh-CN");
const ipKeyword = ipFilter.trim().toLocaleLowerCase("zh-CN");
const sourceKeyword = sourceFilter.trim().toLocaleLowerCase("zh-CN");
return resourceAccounts.filter(({ account, sources }) => { return resourceAccounts.filter(({ account, sources }) => {
const searchable = `${account.nickname} ${account.public_account_id}`.toLocaleLowerCase( const searchable = `${account.nickname} ${account.public_account_id}`.toLocaleLowerCase(
"zh-CN", "zh-CN",
); );
const ipLocation = (account.ip_location || "待识别").toLocaleLowerCase(
"zh-CN",
);
return ( return (
(!keyword || searchable.includes(keyword)) && (!keyword || searchable.includes(keyword)) &&
(platformFilter === "全部平台" || (platformFilter === "全部平台" ||
account.platform === platformFilter) && account.platform === platformFilter) &&
(ipFilter === "全部IP地区" || (!ipKeyword || ipLocation.includes(ipKeyword)) &&
(account.ip_location || "待识别") === ipFilter) && (!sourceKeyword ||
(sourceFilter === "全部合作来源" || sources.some((source) =>
sources.includes(sourceFilter)) source.toLocaleLowerCase("zh-CN").includes(sourceKeyword),
))
); );
}); });
}, [ipFilter, platformFilter, query, resourceAccounts, sourceFilter]); }, [ipFilter, platformFilter, query, resourceAccounts, sourceFilter]);
const hasActiveFilters = const hasActiveFilters =
Boolean(query.trim()) || Boolean(query.trim()) ||
platformFilter !== "全部平台" || platformFilter !== "全部平台" ||
ipFilter !== "全部IP地区" || Boolean(ipFilter.trim()) ||
sourceFilter !== "全部合作来源"; Boolean(sourceFilter.trim());
const clearFilters = () => { const clearFilters = () => {
setQuery(""); setQuery("");
setPlatformFilter("全部平台"); setPlatformFilter("全部平台");
setIpFilter("全部IP地区"); setIpFilter("");
setSourceFilter("全部合作来源"); setSourceFilter("");
}; };
return ( return (
<div className="stack"> <div className="stack">
@@ -1494,7 +1500,7 @@ function ResourcesPage({
</div> </div>
</div> </div>
<div className="resource-toolbar"> <div className="resource-toolbar">
<label className="resource-search"> <div className="resource-search">
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<input <input
aria-label="搜索账号名称或账号ID" aria-label="搜索账号名称或账号ID"
@@ -1503,23 +1509,37 @@ function ResourcesPage({
type="search" type="search"
value={query} value={query}
/> />
</label> </div>
<select <div className="resource-filter-search">
aria-label="按IP地区筛选" <span aria-hidden="true"></span>
<input
aria-label="模糊搜索IP地区"
list="resource-ip-options"
onChange={(event) => setIpFilter(event.target.value)} onChange={(event) => setIpFilter(event.target.value)}
placeholder="搜索IP地区"
type="search"
value={ipFilter} value={ipFilter}
> />
<option>IP地区</option> <datalist id="resource-ip-options">
{ipOptions.map((ip) => <option key={ip}>{ip}</option>)} {ipOptions.map((ip) => <option key={ip} value={ip} />)}
</select> </datalist>
<select </div>
aria-label="按合作来源筛选" <div className="resource-filter-search">
<span aria-hidden="true"></span>
<input
aria-label="模糊搜索合作来源"
list="resource-source-options"
onChange={(event) => setSourceFilter(event.target.value)} onChange={(event) => setSourceFilter(event.target.value)}
placeholder="搜索合作来源"
type="search"
value={sourceFilter} value={sourceFilter}
> />
<option></option> <datalist id="resource-source-options">
{sourceOptions.map((source) => <option key={source}>{source}</option>)} {sourceOptions.map((source) => (
</select> <option key={source} value={source} />
))}
</datalist>
</div>
<button <button
className="resource-clear-button" className="resource-clear-button"
disabled={!hasActiveFilters} disabled={!hasActiveFilters}

View File

@@ -1440,10 +1440,12 @@ a {
.resource-search { .resource-search {
display: flex; display: flex;
flex-direction: row;
min-width: 230px; min-width: 230px;
flex: 1 1 280px; flex: 1 1 280px;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
margin: 0;
height: 38px; height: 38px;
padding: 0 12px; padding: 0 12px;
border: 1px solid #dfe6e2; border: 1px solid #dfe6e2;
@@ -1451,17 +1453,21 @@ a {
background: white; background: white;
} }
.resource-search:focus-within { .resource-search:focus-within,
.resource-filter-search:focus-within {
border-color: #74b79f; border-color: #74b79f;
box-shadow: 0 0 0 3px rgb(31 143 107 / 0.08); box-shadow: 0 0 0 3px rgb(31 143 107 / 0.08);
} }
.resource-search > span { .resource-search > span,
.resource-filter-search > span {
color: #83918c; color: #83918c;
font-size: 17px; font-size: 17px;
font-weight: 400;
} }
.resource-search input { .resource-search input,
.resource-filter-search input {
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 0; padding: 0;
@@ -1471,14 +1477,16 @@ a {
font-size: 10px; font-size: 10px;
} }
.resource-toolbar > select { .resource-filter-search {
width: 160px; display: flex;
flex: 0 1 180px;
align-items: center;
gap: 7px;
height: 38px; height: 38px;
padding: 0 31px 0 11px; padding: 0 11px;
border: 1px solid #dfe6e2; border: 1px solid #dfe6e2;
border-radius: 9px; border-radius: 9px;
background-color: white; background: white;
font-size: 10px;
} }
.resource-clear-button { .resource-clear-button {
@@ -2991,7 +2999,7 @@ label small {
} }
.resource-search, .resource-search,
.resource-toolbar > select { .resource-filter-search {
width: 100%; width: 100%;
flex-basis: 100%; flex-basis: 100%;
} }

View File

@@ -258,8 +258,10 @@ test("filters and exports the current KOC resource result set", async () => {
]); ]);
assert.match(adminApp, /搜索账号名称 \/ 账号ID/); assert.match(adminApp, /搜索账号名称 \/ 账号ID/);
assert.match(adminApp, /全部IP地区/); assert.match(adminApp, /搜索IP地区/);
assert.match(adminApp, /全部合作来源/); assert.match(adminApp, /搜索合作来源/);
assert.match(adminApp, /ipLocation\.includes\(ipKeyword\)/);
assert.match(adminApp, /includes\(sourceKeyword\)/);
assert.match(adminApp, /导出筛选结果/); assert.match(adminApp, /导出筛选结果/);
assert.match(adminApp, /filteredAccounts\.map\(\(item\) => item\.account\.id\)/); assert.match(adminApp, /filteredAccounts\.map\(\(item\) => item\.account\.id\)/);
assert.match(exportRoute, /小红书号\/抖音号/); assert.match(exportRoute, /小红书号\/抖音号/);