Skip to content

Commit

Permalink
feat: search by query
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Apr 2, 2024
1 parent 8378316 commit 4f44c51
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 74 deletions.
5 changes: 4 additions & 1 deletion src/components/ScreenshotCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const debouncedSize = refDebounced(
);
const imgRef = shallowRef<HTMLImageElement>();
const imgLoadTime = shallowRef(0);
const clickImg = (ev: MouseEvent) => {
if (!props.rootNode) return;
Expand Down Expand Up @@ -64,7 +65,8 @@ const percent = (n: number) => {
return `${n * 100}%`;
};
const positionStyle = computed(() => {
debouncedSize.value;
debouncedSize.value; // 在窗口大小变化后触发更新
imgLoadTime.value; // 在图片加载完成后触发更新
const img = imgRef.value;
const attr = props.focusNode?.attr;
if (!props.focusNode || !img || !attr) {
Expand Down Expand Up @@ -137,6 +139,7 @@ const hoverPositionStyle = shallowRef({ left: '0', top: '0' });
@mouseover="imgHover = true"
@mouseleave="imgHover = false"
@mousemove="imgMove"
@load="imgLoadTime = Date.now()"
/>
<div
:style="positionStyle"
Expand Down
148 changes: 88 additions & 60 deletions src/components/SearchCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ import { buildEmptyFn, copy } from '@/utils/others';
import { githubJpgStorage, githubZipStorage } from '@/utils/storage';
import { githubUrlToSelfUrl } from '@/utils/url';
import JSON5 from 'json5';
import { useRouter } from 'vue-router';
import { useRouter, useRoute } from 'vue-router';
import { onMounted } from 'vue';
const router = useRouter();
const route = useRoute();
const props = withDefaults(
defineProps<{
Expand Down Expand Up @@ -58,76 +60,102 @@ const selectorResults = shallowReactive<
)[]
>([]);
const expandedKeys = shallowRef<number[]>([]);
const searchBySelector = errorTry(() => {
if (!props.rootNode) {
message.error(`根节点不存在`);
const searchSelector = (text: string) => {
const selector = errorWrap(
() => parseSelector(text),
(e) => {
if (typeof e == 'string') {
return e;
}
return `非法选择器`;
},
);
if (
selectorResults.find(
(s) =>
typeof s.selector == 'object' &&
s.selector.toString() == selector.toString(),
)
) {
message.warning(`不可重复选择`);
return;
}
const text = selectorText.value.trim();
if (!text) return;
if (enableSearchBySelector.value) {
const selector = errorWrap(
() => parseSelector(text),
(e) => {
if (typeof e == 'string') {
return e;
}
return `非法选择器`;
},
);
if (
selectorResults.find(
(s) =>
typeof s.selector == 'object' &&
s.selector.toString() == selector.toString(),
)
) {
message.warning(`不可重复选择`);
return;
}
const results = selector.querySelectorTrackAll(props.rootNode);
if (results.length == 0) {
message.success(`没有选择到节点`);
return;
const results = selector.querySelectorTrackAll(props.rootNode);
if (results.length == 0) {
message.success(`没有选择到节点`);
return;
}
message.success(`选择到 ${results.length} 个节点`);
selectorResults.unshift({ selector, nodes: results, key: Date.now() });
return results.length;
};
const searchString = (text: string) => {
if (
selectorResults.find(
(s) => typeof s.selector == 'string' && s.selector.toString() == text,
)
) {
message.warning(`不可重复搜索`);
return;
}
const results: RawNode[] = [];
const stack: RawNode[] = [props.rootNode];
while (stack.length > 0) {
const n = stack.pop()!;
if (getNodeLabel(n).includes(text)) {
results.push(n);
}
message.success(`选择到 ${results.length} 个节点`);
selectorResults.unshift({ selector, nodes: results, key: Date.now() });
stack.push(...[...n.children].reverse());
}
if (results.length == 0) {
message.success(`没有搜索到节点`);
return;
}
message.success(`搜索到 ${results.length} 个节点`);
selectorResults.unshift({
selector: text,
nodes: results,
key: Date.now(),
});
return results.length;
};
const refreshExpandedKeys = () => {
const newNode = selectorResults[0].nodes[0];
if (Array.isArray(newNode)) {
props.onUpdateFocusNode(newNode[0]);
} else {
if (
selectorResults.find(
(s) => typeof s.selector == 'string' && s.selector.toString() == text,
)
) {
message.warning(`不可重复选择`);
return;
}
const results: RawNode[] = [];
const stack: RawNode[] = [props.rootNode];
while (stack.length > 0) {
const n = stack.pop()!;
if (getNodeLabel(n).includes(text)) {
results.push(n);
}
stack.push(...[...n.children].reverse());
}
if (results.length == 0) {
message.success(`没有搜索到节点`);
return;
}
message.success(`搜索到 ${results.length} 个节点`);
selectorResults.unshift({
selector: text,
nodes: results,
key: Date.now(),
});
props.onUpdateFocusNode(newNode);
}
const allKeys = new Set(selectorResults.map((s) => s.key));
const newKeys = expandedKeys.value.filter((k) => allKeys.has(k));
newKeys.push(selectorResults[0].key);
expandedKeys.value = newKeys;
};
const searchBySelector = errorTry(() => {
const text = selectorText.value.trim();
if (!text) return;
if (enableSearchBySelector.value) {
if (!searchSelector(text)) return;
} else {
if (!searchString(text)) return;
}
refreshExpandedKeys();
});
onMounted(async () => {
let count = 0;
if (route.query.gkd) {
count += searchSelector(route.query.gkd as string) || 0;
}
if (route.query.str) {
count += searchString(route.query.str as string) || 0;
}
if (count > 0) {
refreshExpandedKeys();
}
});
const generateRules = errorTry(
async (result: { key: number; selector: Selector; nodes: RawNode[][] }) => {
let jpgUrl = githubJpgStorage[props.snapshot.id];
Expand Down
1 change: 1 addition & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const redirectImport: RouteRecordRedirectOption = (to) => {
return {
path: '/i',
query: {
...to.query,
url,
},
};
Expand Down
15 changes: 15 additions & 0 deletions src/utils/others.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { onMounted, onUnmounted } from 'vue';
import { message } from './discrete';
import root from './root';
import type { LocationQuery } from 'vue-router';

export const obj2form = (...objs: Record<string, unknown>[]) => {
const fd = new FormData();
Expand Down Expand Up @@ -108,3 +109,17 @@ export const timeAgo = (date: number) => {

const emptyFn = () => {};
export const buildEmptyFn = () => emptyFn;

export const filterQuery = (
obj: LocationQuery,
keys: string[],
): LocationQuery => {
const newObj: LocationQuery = {};
keys.forEach((k) => {
const value = obj[k];
if (value !== undefined) {
newObj[k] = value;
}
});
return newObj;
};
29 changes: 17 additions & 12 deletions src/views/ImportPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { toValidURL } from '@/utils/check';
import { loadingBar, message } from '@/utils/discrete';
import { gmOk } from '@/utils/gm';
import { importFromNetwork } from '@/utils/import';
import { delay } from '@/utils/others';
import { githubZipStorage } from '@/utils/storage';
import { githubJpgStorage } from '@/utils/storage';
import { urlStorage, snapshotStorage } from '@/utils/storage';
import { delay, filterQuery } from '@/utils/others';
import {
githubJpgStorage,
githubZipStorage,
snapshotStorage,
urlStorage,
} from '@/utils/storage';
import { githubImageUrlReg, githubZipUrlReg } from '@/utils/url';
import { onMounted, shallowRef } from 'vue';
import { useRoute, useRouter } from 'vue-router';
Expand All @@ -19,6 +22,14 @@ const importUrl = String(route.query.url || ``);
const loading = shallowRef(true);
const tip = shallowRef(`加载中...`);
const goToSnapshot = async (snapshotId: number) => {
router.replace({
name: 'snapshot',
params: { snapshotId },
query: filterQuery(route.query, ['str', 'gkd']),
});
};
onMounted(async () => {
if (!toValidURL(importUrl)) {
message.error(`非法URL参数`);
Expand All @@ -33,10 +44,7 @@ onMounted(async () => {
if (snapshotId) {
const snapshot = await snapshotStorage.getItem(snapshotId);
if (snapshot) {
router.replace({
name: 'snapshot',
params: { snapshotId },
});
goToSnapshot(snapshotId);
return;
} else {
delete urlStorage[importUrl];
Expand All @@ -58,10 +66,7 @@ onMounted(async () => {
}
loading.value = false;
await delay(500);
router.replace({
name: 'snapshot',
params: { snapshotId: snapshot.id },
});
goToSnapshot(snapshot.id);
} else {
tip.value = `获取资源失败`;
}
Expand Down
1 change: 0 additions & 1 deletion src/views/SnapshotPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ watchEffect(async () => {
snapshot.value = localSnapshot;
rootNode.value = listToTree(localSnapshot.nodes);
title.value = '快照-' + localSnapshot.appName || localSnapshot.appId;
await delay(500);
if (!focusNode.value) {
focusNode.value = rootNode.value;
}
Expand Down

0 comments on commit 4f44c51

Please sign in to comment.