mirror of
https://github.com/liufree/obsidian-querydash.git
synced 2026-07-22 05:41:49 +00:00
feat: 实现搜索
This commit is contained in:
parent
a8e785ffde
commit
e32e2e55ec
5 changed files with 149 additions and 20 deletions
|
|
@ -4,6 +4,7 @@
|
||||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"dev": "vite build --watch --mode development",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||||
},
|
},
|
||||||
|
|
@ -13,22 +14,23 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/icons": "^5.0.1",
|
"@ant-design/icons": "^5.0.1",
|
||||||
"@ant-design/pro-components": "^2.4.4",
|
"@ant-design/pro-components": "^2.4.4",
|
||||||
"obsidian-dataview": "^0.5.67",
|
|
||||||
"umi-request": "^1.4.0"
|
"umi-request": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/luxon": "^3.4.2",
|
||||||
"@types/node": "^22.13.8",
|
"@types/node": "^22.13.8",
|
||||||
"@types/react": "^18.0.33",
|
"@types/react": "^18.0.33",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||||
"@typescript-eslint/parser": "5.29.0",
|
"@typescript-eslint/parser": "5.29.0",
|
||||||
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"builtin-modules": "3.3.0",
|
"builtin-modules": "3.3.0",
|
||||||
"husky": "^9",
|
"husky": "^9",
|
||||||
"lint-staged": "^13.2.0",
|
"lint-staged": "^13.2.0",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
|
"obsidian-dataview": "^0.5.67",
|
||||||
"tslib": "2.4.0",
|
"tslib": "2.4.0",
|
||||||
"vite": "^6.2.0",
|
"vite": "^6.2.0",
|
||||||
"vite-plugin-css-injected-by-js": "^3.5.2",
|
"vite-plugin-css-injected-by-js": "^3.5.2"
|
||||||
"@vitejs/plugin-react": "^4.3.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,10 @@ export default class MyPlugin extends Plugin {
|
||||||
|
|
||||||
// 代码块中标注table的绘制成sampleView
|
// 代码块中标注table的绘制成sampleView
|
||||||
this.registerMarkdownCodeBlockProcessor('sample', (source, el, ctx) => {
|
this.registerMarkdownCodeBlockProcessor('sample', (source, el, ctx) => {
|
||||||
|
|
||||||
|
console.log("start")
|
||||||
|
console.log('source',source)
|
||||||
|
console.log('ctx',ctx)
|
||||||
// 插入一个div
|
// 插入一个div
|
||||||
const container = el.createDiv();
|
const container = el.createDiv();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,6 @@ export default class ReactComponent extends MarkdownRenderChild {
|
||||||
|
|
||||||
// 使用 createRoot 渲染 React 组件
|
// 使用 createRoot 渲染 React 组件
|
||||||
const root = createRoot(this.container);
|
const root = createRoot(this.container);
|
||||||
root.render(<TableDemo app={this.app} />);
|
root.render(<TableDemo app={this.app} source={this.source} />);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ import {Button, Dropdown, Space, Tag} from 'antd';
|
||||||
import {useEffect, useRef} from 'react';
|
import {useEffect, useRef} from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import request from 'umi-request';
|
import request from 'umi-request';
|
||||||
import {getAPI} from 'obsidian-dataview';
|
import { getAPI} from 'obsidian-dataview';
|
||||||
import {App,Workspace} from "obsidian";
|
import {App, Workspace} from "obsidian";
|
||||||
|
import {continuedIndent} from "@codemirror/language";
|
||||||
|
|
||||||
export const waitTimePromise = async (time: number = 100) => {
|
export const waitTimePromise = async (time: number = 100) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
|
@ -43,19 +44,116 @@ type GithubIssueItem = {
|
||||||
|
|
||||||
interface MyReactComponentProps {
|
interface MyReactComponentProps {
|
||||||
app: any; // Obsidian的App对象
|
app: any; // Obsidian的App对象
|
||||||
|
source: string; // 当前文件的路径
|
||||||
}
|
}
|
||||||
const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
|
||||||
|
const MyReactComponent: React.FC<MyReactComponentProps> = ({app, source}) => {
|
||||||
const actionRef = useRef<ActionType>();
|
const actionRef = useRef<ActionType>();
|
||||||
|
|
||||||
const dataviewAPI = getAPI();
|
const dv = getAPI(app);
|
||||||
|
|
||||||
const [data, setData] = React.useState<GithubIssueItem[]>([]);
|
const [data, setData] = React.useState<GithubIssueItem[]>([]);
|
||||||
|
|
||||||
|
function parseTableResult(value: any, params:any): Array<Record<string, any>> {
|
||||||
|
const headers: string[] = value.headers;
|
||||||
|
|
||||||
|
const rows: Array<Record<string, any>> = [];
|
||||||
|
console.log("params1", params);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
value.values.forEach((row) => {
|
||||||
|
const values: Record<string, any> = {};
|
||||||
|
|
||||||
|
let flag = []
|
||||||
|
headers.forEach((header, index) => {
|
||||||
|
|
||||||
|
const searchParam = params[header];
|
||||||
|
console.log("searchParam",searchParam);
|
||||||
|
|
||||||
|
|
||||||
|
const value = row[index];
|
||||||
|
// 如果字符串value中不包含searchParam,则排除
|
||||||
|
if(searchParam){
|
||||||
|
flag[index] = value.indexOf(searchParam) > -1;
|
||||||
|
}else{
|
||||||
|
flag[index] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("header",header)
|
||||||
|
console.log("row.value",value)
|
||||||
|
values[header] = value;
|
||||||
|
});
|
||||||
|
rows.push(values);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// params参数去除current和pageSize
|
||||||
|
delete params.current;
|
||||||
|
delete params.pageSize;
|
||||||
|
|
||||||
|
const filteredData = rows.filter(item => {
|
||||||
|
return Object.keys(params).every(key => {
|
||||||
|
console.log("key", key);
|
||||||
|
console.log("params[key]", params[key]);
|
||||||
|
console.log("item[key]", item[key]);
|
||||||
|
if (params[key]) {
|
||||||
|
// If item[key] is empty, return false directly.
|
||||||
|
if (item[key]) {
|
||||||
|
return item[key].toString().toLowerCase().includes(params[key].toString().toLowerCase());
|
||||||
|
}else{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
console.log("rows2", rows);
|
||||||
|
console.log("keyParams", Object.keys(params));
|
||||||
|
console.log("params2", params);
|
||||||
|
|
||||||
|
return filteredData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const executeTableQuery=async (dvApi: any,source:any,params:any) => {
|
||||||
|
// 定义查询语句
|
||||||
|
const sql = source;
|
||||||
|
|
||||||
|
// 使用 Dataview API 执行查询
|
||||||
|
const queryResult = await dvApi.query(sql);
|
||||||
|
console.log("Query Result:", queryResult);
|
||||||
|
console.log("Query Result1:", queryResult.successful);
|
||||||
|
console.log("Query Result2:", queryResult.value);
|
||||||
|
|
||||||
|
const tableData:any =parseTableResult(queryResult.value,params);
|
||||||
|
|
||||||
|
|
||||||
|
console.log("tableData:", tableData);
|
||||||
|
|
||||||
|
// 处理查询结果
|
||||||
|
if (queryResult.successful) {
|
||||||
|
const tableData = queryResult.value;
|
||||||
|
console.log("Query Result:", tableData);
|
||||||
|
// 在这里可以对查询结果进行进一步处理
|
||||||
|
tableData.values.forEach(row => {
|
||||||
|
console.log("Row:", row);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("Query failed:", queryResult.error);
|
||||||
|
}
|
||||||
|
return tableData;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
const data = dataviewAPI.pages().file.lists.values;
|
//executeTableQuery(dv,source,{});
|
||||||
console.log("data",data);
|
|
||||||
setData(data);
|
// const data = dv.pages().file.lists.values;
|
||||||
|
//console.log("data", data);
|
||||||
|
// setData(data);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const columns: ProColumns<GithubIssueItem>[] = [
|
const columns: ProColumns<GithubIssueItem>[] = [
|
||||||
|
|
@ -66,16 +164,17 @@ const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '标题',
|
title: '标题',
|
||||||
|
dataIndex: 'file.name',
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
console.log("record",_),
|
console.log("record,{},text", _,record),
|
||||||
<a onClick={()=>{
|
<a onClick={() => {
|
||||||
// 调用 Obsidian API
|
// 调用 Obsidian API
|
||||||
const file = app.vault.getAbstractFileByPath(record.header.path);
|
const file = app.vault.getAbstractFileByPath(record.File.path);
|
||||||
if (file) {
|
if (file) {
|
||||||
app.workspace.activeLeaf?.openFile(file);
|
app.workspace.activeLeaf?.openFile(file);
|
||||||
}
|
}
|
||||||
}} >
|
}}>
|
||||||
{record.header.path}
|
{record.File.path}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
),
|
),
|
||||||
|
|
@ -87,7 +186,21 @@ const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
||||||
onFilter: true,
|
onFilter: true,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
console.log("record",record),
|
console.log("record", record),
|
||||||
|
<Space>
|
||||||
|
{record.text}
|
||||||
|
</Space>
|
||||||
|
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '文本1',
|
||||||
|
dataIndex: 'file.ctime',
|
||||||
|
filters: true,
|
||||||
|
onFilter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
render: (_, record) => (
|
||||||
|
console.log("record", record),
|
||||||
<Space>
|
<Space>
|
||||||
{record.text}
|
{record.text}
|
||||||
</Space>
|
</Space>
|
||||||
|
|
@ -104,7 +217,7 @@ const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
||||||
editable={{
|
editable={{
|
||||||
type: 'multiple',
|
type: 'multiple',
|
||||||
}}
|
}}
|
||||||
dataSource={data}
|
// dataSource={data}
|
||||||
columnsState={{
|
columnsState={{
|
||||||
persistenceKey: 'pro-table-singe-demos',
|
persistenceKey: 'pro-table-singe-demos',
|
||||||
persistenceType: 'localStorage',
|
persistenceType: 'localStorage',
|
||||||
|
|
@ -115,7 +228,7 @@ const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
||||||
console.log('value: ', value);
|
console.log('value: ', value);
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
rowKey="id"
|
rowKey="title"
|
||||||
search={{
|
search={{
|
||||||
labelWidth: 'auto',
|
labelWidth: 'auto',
|
||||||
}}
|
}}
|
||||||
|
|
@ -142,6 +255,16 @@ const MyReactComponent: React.FC<MyReactComponentProps> = ({ app }) => {
|
||||||
}}
|
}}
|
||||||
dateFormatter="string"
|
dateFormatter="string"
|
||||||
headerTitle="高级表格"
|
headerTitle="高级表格"
|
||||||
|
request={async (params, sort, filter) => {
|
||||||
|
console.log('params:', params);
|
||||||
|
const response = await executeTableQuery(dv,source,params);
|
||||||
|
console.log("response1",response);
|
||||||
|
return {
|
||||||
|
data: response,
|
||||||
|
success: true,
|
||||||
|
total: response.length,
|
||||||
|
};
|
||||||
|
}}
|
||||||
toolBarRender={() => [
|
toolBarRender={() => [
|
||||||
<Button
|
<Button
|
||||||
key="button"
|
key="button"
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,6 @@
|
||||||
"jsx": "react"
|
"jsx": "react"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts"
|
"**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue