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"; ...@@ -2,14 +2,14 @@ import { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api"; import { CardData, CardMeta, CardText } from "@/api";
interface FtsConditions { export interface FtsConditions {
// 过滤条件 // 过滤条件
types?: number[]; // 卡片类型 types?: number[]; // 卡片类型
levels?: number[]; // 星阶/刻度/link值 levels?: number[]; // 星阶/刻度/link值
atk?: [number, number]; // 攻击力区间 atk?: [number, number]; // 攻击力区间
def?: [number, number]; // 防御力区间 def?: [number, number]; // 防御力区间
race?: number; // 种族 races?: number[]; // 种族
attribute?: number; // 属性 attributes?: number[]; // 属性
} }
export interface FtsParams { export interface FtsParams {
query: string; // 用于全文检索的query query: string; // 用于全文检索的query
...@@ -32,11 +32,15 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] { ...@@ -32,11 +32,15 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] {
for (const text of ftsTexts) { for (const text of ftsTexts) {
const id = text.id; const id = text.id;
if (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 dataStmt = db.prepare(sql);
const data: CardData = dataStmt.getAsObject({ $id: id }); const data: CardData = dataStmt.getAsObject({ $id: id });
if (Object.values(data).filter((v) => v !== undefined).length > 0) {
ftsMetas.push({ id, data, text }); ftsMetas.push({ id, data, text });
}
} }
} }
...@@ -44,7 +48,7 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] { ...@@ -44,7 +48,7 @@ export function invokeFts(db: Database, params: FtsParams): CardMeta[] {
} }
function getFtsCondtions(conditions: FtsConditions): string { function getFtsCondtions(conditions: FtsConditions): string {
const { types, levels, atk, def, race, attribute } = conditions; const { types, levels, atk, def, races, attributes } = conditions;
const typesCondition = types const typesCondition = types
?.map((type) => `(types & ${type}) > 0`) ?.map((type) => `(types & ${type}) > 0`)
...@@ -54,9 +58,10 @@ function getFtsCondtions(conditions: FtsConditions): string { ...@@ -54,9 +58,10 @@ function getFtsCondtions(conditions: FtsConditions): string {
.join(" OR "); .join(" OR ");
const atkCondition = atk ? `atk BETWEEN ${atk[0]} AND ${atk[1]}` : undefined; const atkCondition = atk ? `atk BETWEEN ${atk[0]} AND ${atk[1]}` : undefined;
const defCondition = def ? `def BETWEEN ${def[0]} AND ${def[1]}` : undefined; const defCondition = def ? `def BETWEEN ${def[0]} AND ${def[1]}` : undefined;
const raceCondition = race !== undefined ? `race = ${race}` : undefined; const raceCondition = races?.map((race) => `race = ${race}`).join(" OR ");
const attributeCondition = const attributeCondition = attributes
attribute !== undefined ? `attribute = ${attribute}` : undefined; ?.map((attribute) => `attribute = ${attribute}`)
.join(" OR ");
const merged = [ const merged = [
typesCondition, typesCondition,
...@@ -67,8 +72,8 @@ function getFtsCondtions(conditions: FtsConditions): string { ...@@ -67,8 +72,8 @@ function getFtsCondtions(conditions: FtsConditions): string {
attributeCondition, attributeCondition,
] ]
.filter((condition) => condition !== undefined) .filter((condition) => condition !== undefined)
.map((condition) => `(${condition})`) // .map((condition) => `(${condition})`)
.join(" AND "); .join(" AND ");
return merged !== "" ? `WHERE ${merged}` : ""; return merged;
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import initSqlJs, { Database } from "sql.js"; import initSqlJs, { Database } from "sql.js";
import { CardData, CardMeta, CardText } from "@/api/cards"; import { CardMeta } from "@/api/cards";
import { useConfig } from "@/config"; import { useConfig } from "@/config";
import { pfetch } from "@/infra"; import { pfetch } from "@/infra";
......
...@@ -7,6 +7,11 @@ import { ...@@ -7,6 +7,11 @@ import {
Select, Select,
type SelectProps, type SelectProps,
} from "antd"; } 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"; import styles from "./Filter.module.scss";
...@@ -19,7 +24,11 @@ for (let i = 10; i < 36; i++) { ...@@ -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 ( return (
<> <>
<div className={styles.title}>卡片筛选</div> <div className={styles.title}>卡片筛选</div>
...@@ -41,7 +50,20 @@ export const Filter: React.FC = () => { ...@@ -41,7 +50,20 @@ export const Filter: React.FC = () => {
allowClear allowClear
style={{ width: "100%" }} style={{ width: "100%" }}
placeholder="Please select" 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>
<div className={styles.item}> <div className={styles.item}>
...@@ -102,7 +124,9 @@ export const Filter: React.FC = () => { ...@@ -102,7 +124,9 @@ export const Filter: React.FC = () => {
</div> </div>
</div> </div>
<div className={styles.btns}> <div className={styles.btns}>
<Button type="primary">确定</Button> <Button type="primary" onClick={() => applyCallback(newConditions)}>
确定
</Button>
<Button type="text">&nbsp;</Button> <Button type="text">&nbsp;</Button>
</div> </div>
</> </>
......
...@@ -27,6 +27,7 @@ import { subscribeKey } from "valtio/utils"; ...@@ -27,6 +27,7 @@ import { subscribeKey } from "valtio/utils";
import { type CardMeta, searchCards } from "@/api"; import { type CardMeta, searchCards } from "@/api";
import { isExtraDeckCard, isToken } from "@/common"; import { isExtraDeckCard, isToken } from "@/common";
import { FtsConditions } from "@/middleware/sqlite/fts";
import { deckStore, type IDeck, initStore } from "@/stores"; import { deckStore, type IDeck, initStore } from "@/stores";
import { import {
Background, Background,
...@@ -206,10 +207,12 @@ const DeckEditor: React.FC<{ ...@@ -206,10 +207,12 @@ const DeckEditor: React.FC<{
const Search: React.FC = () => { const Search: React.FC = () => {
const { modal } = App.useApp(); const { modal } = App.useApp();
const [searchWord, setSearchWord] = useState(""); const [searchWord, setSearchWord] = useState("");
const [searchConditions, setSearchConditions] = useState<FtsConditions>({});
const [searchResult, setSearchResult] = useState<CardMeta[]>([]); const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const [filterOpen, setFilterOpen] = useState(false);
const handleSearch = async () => { const handleSearch = async () => {
const result = ( const result = (
await searchCards({ query: searchWord, conditions: {} }) await searchCards({ query: searchWord, conditions: searchConditions })
).filter((card) => !isToken(card.data.type ?? 0)); // 衍生物不显示 ).filter((card) => !isToken(card.data.type ?? 0)); // 衍生物不显示
setSearchResult(result); setSearchResult(result);
}; };
...@@ -254,8 +257,17 @@ const Search: React.FC = () => { ...@@ -254,8 +257,17 @@ const Search: React.FC = () => {
centered: true, centered: true,
title: null, title: null,
icon: null, icon: null,
content: <Filter />, content: (
<Filter
conditions={searchConditions}
applyCallback={(newConditions) => {
setSearchConditions(newConditions);
setFilterOpen(false);
}}
/>
),
footer: null, 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