Add g and kg catalog filters

This commit is contained in:
Jacky Ser
2026-08-11 09:41:44 +08:00
parent 7b9a56b7fe
commit 9078f19194
2 changed files with 78 additions and 2 deletions

View File

@@ -313,6 +313,12 @@ select:focus, input:focus, textarea:focus { border-color: var(--blue); box-shado
} }
.category-pills button.active { border-color: var(--blue); color: white; background: var(--blue); } .category-pills button.active { border-color: var(--blue); color: white; background: var(--blue); }
.category-pills button.feature-filter:not(.active) { border-color: #f1bf92; color: #a75a19; background: #fff9f3; } .category-pills button.feature-filter:not(.active) { border-color: #f1bf92; color: #a75a19; background: #fff9f3; }
.catalog-scale-filter { display: grid; grid-template-columns: minmax(240px, 330px) 1fr; align-items: end; gap: 14px; margin-top: 13px; padding-top: 13px; border-top: 1px solid #e7ebf1; }
.catalog-scale-filter label { display: grid; gap: 6px; }
.catalog-scale-filter label > span { color: #68758a; font-size: 10px; font-weight: 700; }
.catalog-scale-filter select { width: 100%; height: 42px; padding: 0 12px; }
.catalog-scale-filter p { margin: 0 0 4px; color: #8792a3; font-size: 9px; line-height: 1.55; }
.catalog-scale-filter p strong { color: #657187; }
.catalog-result-count { margin: 11px 2px 0; color: #8792a3; font-size: 10px; } .catalog-result-count { margin: 11px 2px 0; color: #8792a3; font-size: 10px; }
.catalog-result-count strong { color: var(--blue); font-size: 12px; } .catalog-result-count strong { color: var(--blue); font-size: 12px; }
.catalog-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; } .catalog-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@@ -496,6 +502,7 @@ footer > span { color: #9aa4b2; font-size: 10px; }
.catalog-summary { grid-template-columns: repeat(2, 1fr); } .catalog-summary { grid-template-columns: repeat(2, 1fr); }
.catalog-summary button:last-child { grid-column: 1 / -1; } .catalog-summary button:last-child { grid-column: 1 / -1; }
.catalog-toolbar { top: 64px; } .catalog-toolbar { top: 64px; }
.catalog-scale-filter { grid-template-columns: 1fr; align-items: stretch; }
.catalog-grid { grid-template-columns: 1fr; gap: 15px; } .catalog-grid { grid-template-columns: 1fr; gap: 15px; }
.catalog-image-button { height: 280px; } .catalog-image-button { height: 280px; }
.catalog-card-body { padding: 15px; } .catalog-card-body { padding: 15px; }

View File

@@ -94,6 +94,46 @@ function getCategoryCount(category: string) {
return category === SILENT_SERVO_CATEGORY ? SILENT_SERVO_COUNT : CATALOG_COUNTS[category]; return category === SILENT_SERVO_CATEGORY ? SILENT_SERVO_COUNT : CATALOG_COUNTS[category];
} }
type ProductScale = {
key: string;
label: string;
unit: "g" | "kg";
value: number;
};
function getProductScale(product: CatalogProduct): ProductScale | null {
const kilogramMatch = product.name.match(/(\d+(?:\.\d+)?)\s*(?:kg|千克)/i);
if (kilogramMatch) {
const value = Number(kilogramMatch[1]);
return { key: `kg:${value}`, label: `${value}kg`, unit: "kg", value };
}
const gramMatch = product.name.match(/(\d+(?:\.\d+)?)\s*(?:g|克)/i);
if (gramMatch) {
const value = Number(gramMatch[1]);
return { key: `g:${value}`, label: `${value}g`, unit: "g", value };
}
return null;
}
const PRODUCT_SCALE_OPTIONS = [...CATALOG_PRODUCTS.reduce((options, product) => {
const scale = getProductScale(product);
if (!scale) return options;
const current = options.get(scale.key);
options.set(scale.key, { ...scale, count: (current?.count ?? 0) + 1 });
return options;
}, new Map<string, ProductScale & { count: number }>()).values()].sort(
(a, b) => (a.unit === b.unit ? a.value - b.value : a.unit === "g" ? -1 : 1),
);
const GRAM_SCALE_OPTIONS = PRODUCT_SCALE_OPTIONS.filter((option) => option.unit === "g");
const KILOGRAM_SCALE_OPTIONS = PRODUCT_SCALE_OPTIONS.filter((option) => option.unit === "kg");
const UNMARKED_SCALE_COUNT = CATALOG_PRODUCTS.length - PRODUCT_SCALE_OPTIONS.reduce(
(total, option) => total + option.count,
0,
);
function inferWeight(product: CatalogProduct) { function inferWeight(product: CatalogProduct) {
const listedWeight = parseNumbers(product.specs["重量"])[0]; const listedWeight = parseNumbers(product.specs["重量"])[0];
if (Number.isFinite(listedWeight)) return listedWeight; if (Number.isFinite(listedWeight)) return listedWeight;
@@ -280,6 +320,7 @@ export default function Home() {
const [leadId, setLeadId] = useState(""); const [leadId, setLeadId] = useState("");
const [catalogQuery, setCatalogQuery] = useState(""); const [catalogQuery, setCatalogQuery] = useState("");
const [catalogCategory, setCatalogCategory] = useState("全部产品"); const [catalogCategory, setCatalogCategory] = useState("全部产品");
const [catalogScale, setCatalogScale] = useState("all");
const [catalogLimit, setCatalogLimit] = useState(24); const [catalogLimit, setCatalogLimit] = useState(24);
const [selectedCatalogProduct, setSelectedCatalogProduct] = useState<CatalogProduct | null>(null); const [selectedCatalogProduct, setSelectedCatalogProduct] = useState<CatalogProduct | null>(null);
@@ -290,6 +331,8 @@ export default function Home() {
const filteredCatalog = useMemo(() => { const filteredCatalog = useMemo(() => {
const query = catalogQuery.trim().toLowerCase(); const query = catalogQuery.trim().toLowerCase();
return CATALOG_PRODUCTS.filter((product) => { return CATALOG_PRODUCTS.filter((product) => {
const productScale = getProductScale(product)?.key ?? "unmarked";
if (catalogScale !== "all" && productScale !== catalogScale) return false;
const matchesCategory = const matchesCategory =
catalogCategory === "全部产品" || catalogCategory === "全部产品" ||
product.category === catalogCategory || product.category === catalogCategory ||
@@ -307,7 +350,7 @@ export default function Home() {
.toLowerCase(); .toLowerCase();
return haystack.includes(query); return haystack.includes(query);
}); });
}, [catalogCategory, catalogQuery]); }, [catalogCategory, catalogQuery, catalogScale]);
const visibleCatalog = filteredCatalog.slice(0, catalogLimit); const visibleCatalog = filteredCatalog.slice(0, catalogLimit);
const needsEngineer = const needsEngineer =
!top?.coreCompatible || !top?.coreCompatible ||
@@ -894,6 +937,32 @@ export default function Home() {
>{category === SILENT_SERVO_CATEGORY ? `${category} · ${SILENT_SERVO_COUNT}` : category}</button> >{category === SILENT_SERVO_CATEGORY ? `${category} · ${SILENT_SERVO_COUNT}` : category}</button>
))} ))}
</div> </div>
<div className="catalog-scale-filter">
<label>
<span> g / kg </span>
<select
value={catalogScale}
onChange={(event) => {
setCatalogScale(event.target.value);
setCatalogLimit(24);
}}
>
<option value="all"> g / kg </option>
<optgroup label="克重系列g / 克)">
{GRAM_SCALE_OPTIONS.map((option) => (
<option key={option.key} value={option.key}>{option.label}{option.count}</option>
))}
</optgroup>
<optgroup label="千克扭矩等级kg / 千克)">
{KILOGRAM_SCALE_OPTIONS.map((option) => (
<option key={option.key} value={option.key}>{option.label}{option.count}</option>
))}
</optgroup>
<option value="unmarked"> g/kg{UNMARKED_SCALE_COUNT}</option>
</select>
</label>
<p><strong></strong>g/kg/Kg通常表示舵机扭矩等级</p>
</div>
<p className="catalog-result-count"> <p className="catalog-result-count">
<strong>{filteredCatalog.length}</strong> <strong>{filteredCatalog.length}</strong>
</p> </p>
@@ -936,7 +1005,7 @@ export default function Home() {
<div className="catalog-empty"> <div className="catalog-empty">
<strong></strong> <strong></strong>
<p></p> <p></p>
<button type="button" onClick={() => { setCatalogQuery(""); setCatalogCategory("全部产品"); }}> <button type="button" onClick={() => { setCatalogQuery(""); setCatalogCategory("全部产品"); setCatalogScale("all"); }}>
</button> </button>
</div> </div>