Commit d37ef8cb authored by Chunchi Che's avatar Chunchi Che

update Filter.tsx

parent da5f8e50
Pipeline #23027 failed with stages
in 13 minutes and 30 seconds
......@@ -2,14 +2,14 @@ import { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api";
interface FtsConditions {
export interface FtsConditions {
// 过滤条件
types?: number[]; // 卡片类型
levels?: number[]; // 星阶/刻度/link值
atk?: [number, number]; // 攻击力区间
def?: [number, number]; // 防御力区间
race?: number; // 种族
attribute?: number; // 属性
races?: number[]; // 种族
attributes?: number[]; // 属性
}
export interface FtsParams {
query: string; // 用于全文检索的query
......@@ -32,11 +32,15 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] {
for (const text of ftsTexts) {
const id = text.id;
if (id) {
const sql = `SELECT * FROM datas ${getFtsCondtions(conditions)}`;
const filterConditions = getFtsCondtions(conditions);
const sql = `SELECT * FROM datas WHERE ${
filterConditions == "" ? "ID = $id" : `ID = $id AND ${filterConditions}`
}`;
const dataStmt = db.prepare(sql);
const data: CardData = dataStmt.getAsObject({ $id: id });
ftsMetas.push({ id, data, text });
if (Object.values(data).filter((v) => v !== undefined).length > 0) {
ftsMetas.push({ id, data, text });
}
}
}
......@@ -44,7 +48,7 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] {
}
function getFtsCondtions(conditions: FtsConditions): string {
const { types, levels, atk, def, race, attribute } = conditions;
const { types, levels, atk, def, races, attributes } = conditions;
const typesCondition = types
?.map((type) => `(types & ${type}) > 0`)
......@@ -54,9 +58,10 @@ function getFtsCondtions(conditions: FtsConditions): string {
.join(" OR ");
const atkCondition = atk ? `atk BETWEEN ${atk[0]} AND ${atk[1]}` : undefined;
const defCondition = def ? `def BETWEEN ${def[0]} AND ${def[1]}` : undefined;
const raceCondition = race !== undefined ? `race = ${race}` : undefined;
const attributeCondition =
attribute !== undefined ? `attribute = ${attribute}` : undefined;
const raceCondition = races?.map((race) => `race = ${race}`).join(" OR ");
const attributeCondition = attributes
?.map((attribute) => `attribute = ${attribute}`)
.join(" OR ");
const merged = [
typesCondition,
......@@ -67,8 +72,8 @@ function getFtsCondtions(conditions: FtsConditions): string {
attributeCondition,
]
.filter((condition) => condition !== undefined)
.map((condition) => `(${condition})`)
// .map((condition) => `(${condition})`)
.join(" AND ");
return merged !== "" ? `WHERE ${merged}` : "";
return merged;
}
......@@ -7,7 +7,7 @@
import initSqlJs, { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api/cards";
import { CardMeta } from "@/api/cards";
import { useConfig } from "@/config";
import { pfetch } from "@/infra";
......
......@@ -7,6 +7,11 @@ import {
Select,
type SelectProps,
} from "antd";
import { useState } from "react";
import { fetchStrings, Region } from "@/api";
import { Attribute2StringCodeMap, Race2StringCodeMap } from "@/common";
import { FtsConditions } from "@/middleware/sqlite/fts";
import styles from "./Filter.module.scss";
......@@ -19,7 +24,11 @@ for (let i = 10; i < 36; i++) {
});
}
export const Filter: React.FC = () => {
export const Filter: React.FC<{
conditions: FtsConditions;
applyCallback: (newConditons: FtsConditions) => void;
}> = ({ conditions, applyCallback }) => {
const [newConditions, setNewConditions] = useState<FtsConditions>({});
return (
<>
<div className={styles.title}>卡片筛选</div>
......@@ -41,7 +50,20 @@ export const Filter: React.FC = () => {
allowClear
style={{ width: "100%" }}
placeholder="Please select"
options={options}
options={Array.from(Attribute2StringCodeMap.entries()).map(
([key, value]) => ({
value: key,
label: fetchStrings(Region.System, value),
})
)}
defaultValue={conditions.attributes ?? []}
onChange={(values) => {
// @ts-ignore
setNewConditions((prev) => {
prev.attributes = values;
return prev;
});
}}
/>
</div>
<div className={styles.item}>
......@@ -102,7 +124,9 @@ export const Filter: React.FC = () => {
</div>
</div>
<div className={styles.btns}>
<Button type="primary">确定</Button>
<Button type="primary" onClick={() => applyCallback(newConditions)}>
确定
</Button>
<Button type="text">&nbsp;</Button>
</div>
</>
......
......@@ -27,6 +27,7 @@ import { subscribeKey } from "valtio/utils";
import { type CardMeta, searchCards } from "@/api";
import { isExtraDeckCard, isToken } from "@/common";
import { FtsConditions } from "@/middleware/sqlite/fts";
import { deckStore, type IDeck, initStore } from "@/stores";
import {
Background,
......@@ -206,10 +207,12 @@ const DeckEditor: React.FC<{
const Search: React.FC = () => {
const { modal } = App.useApp();
const [searchWord, setSearchWord] = useState("");
const [searchConditions, setSearchConditions] = useState<FtsConditions>({});
const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const [filterOpen, setFilterOpen] = useState(false);
const handleSearch = async () => {
const result = (
await searchCards({ query: searchWord, conditions: {} })
await searchCards({ query: searchWord, conditions: searchConditions })
).filter((card) => !isToken(card.data.type ?? 0)); // 衍生物不显示
setSearchResult(result);
};
......@@ -254,8 +257,17 @@ const Search: React.FC = () => {
centered: true,
title: null,
icon: null,
content: <Filter />,
content: (
<Filter
conditions={searchConditions}
applyCallback={(newConditions) => {
setSearchConditions(newConditions);
setFilterOpen(false);
}}
/>
),
footer: null,
open: filterOpen,
});
}}
>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment