From a7239543a9a0df939dd268f3a6f2e2f3b6d208ac Mon Sep 17 00:00:00 2001 From: godo Date: Fri, 10 Jan 2025 14:35:58 +0800 Subject: [PATCH] change search --- README.md | 7 +- frontend/src/components/computer/Computer.vue | 24 +++- frontend/src/system/core/FileOs.ts | 16 ++- godo/cmd/main.go | 1 + godo/files/search.go | 114 ++++++++++++++++++ godo/go.mod | 6 +- godo/go.sum | 12 +- 7 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 godo/files/search.go diff --git a/README.md b/README.md index 07b9857..ca3e9ac 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,9 @@ - 新增配置本地代理和远程代理,本地代理可实现本机ip映射外部域名,远程代理内嵌frpc设置后可实现内网用户外网域名访问。 - 修改锁屏机制,确保外网访问安全。 - 支持本地聊天ai对话文件和联网搜索。 -- 支持知识库根据文件智能生成,一键生成知识库索引,一键搜索知识库。 +- 支持知识库根据文件夹智能生成,一键添加知识库索引,一键搜索知识库。 - 新增复制/粘贴快捷键 +- 新增文件检索,支持分词查询文档内容 ## 🏭 第三阶段目标(一月底发布) 1. **文档处理与Markdown智能升级**:(已完成) @@ -28,7 +29,7 @@ - **纠错优化**:智能识别并纠正文档中的语法、拼写错误,确保内容准确无误。 - **智能提纲生成**:自动梳理文章结构,生成逻辑清晰的提纲,助您轻松驾驭复杂文档。 -2. **本地文件级知识库管理**: +2. **本地文件级知识库管理**:(已完成) - 引入全新的知识库管理系统,实现对本地文件的智能分类、标签化管理与高效检索,让您的知识积累更加有序、便捷。 3. **图形处理一键生图**: @@ -440,7 +441,7 @@ chmod +x osadmin_linux_amd64 - 承诺永久开源 - 允许企业/个人单独使用,但需保留版权信息 - 如用于商业活动或二次开发后发售,请购买相关版权 -- 不提供私下维护工作,如有bug请 [issures](https://gitee.com/ruitao_admin/godoos/issues) 提交 +- 不提供私下维护工作,如有bug请 [issures](https://gitee.com/godoos/godoos/issues) 提交 - 请尊重作者的劳动成果 ## 💌 支持作者 diff --git a/frontend/src/components/computer/Computer.vue b/frontend/src/components/computer/Computer.vue index 7ca850d..6d59794 100644 --- a/frontend/src/components/computer/Computer.vue +++ b/frontend/src/components/computer/Computer.vue @@ -312,7 +312,7 @@ let chosenCallback: (rect: Rect) => void = () => { // }; function onChosen(callback: (rect: Rect) => void) { - console.log(callback) + //console.log(callback) chosenCallback = callback; } @@ -377,10 +377,26 @@ async function handleNavRefresh(path: string) { refersh(); } } -async function handleNavSearch(path: string) { - console.log(path) +async function handleNavSearch(query: string) { + //console.log(query) //setRouter("search:" + path); - refersh(); + if (query == "") { + system.fs.readdir(router_url.value).then((file: any) => { + if (file) { + currentList.value = [...file]; + refersh(); + } + }); + }else{ + system.fs.search(router_url.value,query).then((file: any) => { + if (file) { + currentList.value = [...file]; + //refersh(); + } + }); + } + + } document.addEventListener('paste', function() { if(router_url.value !== "/" && !router_url.value.startsWith("/B")){ diff --git a/frontend/src/system/core/FileOs.ts b/frontend/src/system/core/FileOs.ts index 8e64130..e301141 100644 --- a/frontend/src/system/core/FileOs.ts +++ b/frontend/src/system/core/FileOs.ts @@ -76,6 +76,13 @@ export async function handleUnlink(path: string): Promise { } return await res.json(); } +export async function handleSearch(path: string,query:string): Promise { + const res = await fetchGet(`${API_BASE_URL}/search?path=${encodeURIComponent(path)}&query=${encodeURIComponent(query)}`); + if (!res.ok) { + return false; + } + return await res.json(); +} export async function handleClear(): Promise { const res = await fetchGet(`${API_BASE_URL}/clear`); @@ -298,9 +305,12 @@ export const useOsFile = () => { } return false; }, - async search(path: string, options: any) { - console.log('search:', path, options) - return true; + async search(path: string, query: string) { + const response = await handleSearch(path, query); + if (response && response.data) { + return response.data; + } + return false; }, async zip(path: string, ext: string) { const response = await handleZip(path, ext); diff --git a/godo/cmd/main.go b/godo/cmd/main.go index a8851ed..92e2758 100644 --- a/godo/cmd/main.go +++ b/godo/cmd/main.go @@ -111,6 +111,7 @@ func OsStart() { fileRouter.HandleFunc("/zip", files.HandleZip).Methods(http.MethodGet) fileRouter.HandleFunc("/unzip", files.HandleUnZip).Methods(http.MethodGet) fileRouter.HandleFunc("/watch", files.WatchHandler).Methods(http.MethodGet) + fileRouter.HandleFunc("/search", files.HandleSarch).Methods(http.MethodGet) fileRouter.HandleFunc("/setfilepwd", files.HandleSetFilePwd).Methods(http.MethodGet) fileRouter.HandleFunc("/onlyofficecallback", files.OnlyOfficeCallbackHandler).Methods(http.MethodPost) diff --git a/godo/files/search.go b/godo/files/search.go new file mode 100644 index 0000000..d8edd17 --- /dev/null +++ b/godo/files/search.go @@ -0,0 +1,114 @@ +package files + +import ( + "encoding/json" + "godo/libs" + "godo/office" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/ikawaha/kagome-dict/ipa" + "github.com/ikawaha/kagome/v2/tokenizer" +) + +func HandleSarch(w http.ResponseWriter, r *http.Request) { + path := r.URL.Query().Get("path") + query := r.URL.Query().Get("query") + if err := validateFilePath(path); err != nil { + libs.HTTPError(w, http.StatusBadRequest, err.Error()) + return + } + if query == "" { + libs.HTTPError(w, http.StatusBadRequest, "query is empty") + return + } + basePath, err := libs.GetOsDir() + if err != nil { + libs.HTTPError(w, http.StatusInternalServerError, err.Error()) + return + } + searchPath := filepath.Join(basePath, path) + var osFileInfos []*OsFileInfo + + // Initialize tokenizer + t, err := tokenizer.New(ipa.Dict(), tokenizer.OmitBosEos()) + if err != nil { + panic(err) + } + + // Tokenize the query + queryTokens := t.Tokenize(query) + queryWords := make([]string, 0, len(queryTokens)) + for _, token := range queryTokens { + queryWords = append(queryWords, token.Surface) + } + + err = filepath.Walk(searchPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if strings.HasPrefix(info.Name(), ".") { + return nil + } + osFileInfo, err := GetFileInfo(path, "", "") + if err != nil { + return err + } + if !info.IsDir() { + doc, err := office.GetDocument(path) + if err == nil { + osFileInfo.Content = doc.Content + + // Tokenize the file content + contentTokens := t.Tokenize(osFileInfo.Content) + contentWords := make([]string, 0, len(contentTokens)) + for _, token := range contentTokens { + contentWords = append(contentWords, token.Surface) + } + + // Check if any query word is in the content words + for _, queryWord := range queryWords { + if containsIgnoreCase(contentWords, queryWord) { + //osFileInfo.Path = strings.TrimPrefix(path, basePath) + osFileInfos = append(osFileInfos, osFileInfo) + break + } + } + } + } else { + // Check if the path or filename contains the query + if strings.Contains(strings.ToLower(path), strings.ToLower(query)) { + //osFileInfo.Path = strings.TrimPrefix(path, basePath) + osFileInfos = append(osFileInfos, osFileInfo) + } + } + + return nil + }) + if err != nil { + libs.HTTPError(w, http.StatusInternalServerError, err.Error()) + return + } + for i, osFileInfo := range osFileInfos { + osFileInfos[i].Path = strings.TrimPrefix(osFileInfo.Path, basePath) + osFileInfos[i].OldPath = strings.TrimPrefix(osFileInfo.OldPath, basePath) + } + res := libs.APIResponse{ + Message: "Directory read successfully.", + Data: osFileInfos, + } + json.NewEncoder(w).Encode(res) +} + +// Helper function to check if a slice contains a string (case insensitive) +func containsIgnoreCase(slice []string, item string) bool { + itemLower := strings.ToLower(item) + for _, s := range slice { + if strings.ToLower(s) == itemLower { + return true + } + } + return false +} diff --git a/godo/go.mod b/godo/go.mod index 944aa2d..68081cc 100644 --- a/godo/go.mod +++ b/godo/go.mod @@ -12,9 +12,10 @@ require ( github.com/ebitengine/purego v0.8.1 github.com/fsnotify/fsnotify v1.7.0 github.com/gorilla/mux v1.8.1 + github.com/ikawaha/kagome-dict/ipa v1.2.0 + github.com/ikawaha/kagome/v2 v2.10.0 github.com/mattetti/filebuffer v1.0.1 github.com/minio/selfupdate v0.6.0 - github.com/ncruces/go-sqlite3 v0.21.3 github.com/ncruces/go-sqlite3/gormlite v0.21.0 github.com/richardlehane/mscfb v1.0.4 github.com/shirou/gopsutil v3.21.11+incompatible @@ -29,10 +30,11 @@ require ( aead.dev/minisign v0.2.0 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect + github.com/ikawaha/kagome-dict v1.1.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/jmoiron/sqlx v1.4.0 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/ncruces/go-sqlite3 v0.21.3 // indirect github.com/ncruces/julianday v1.0.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/richardlehane/msoleps v1.0.1 // indirect diff --git a/godo/go.sum b/godo/go.sum index 9b95803..69dd19f 100644 --- a/godo/go.sum +++ b/godo/go.sum @@ -1,6 +1,5 @@ aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk= aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ= -filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/EndFirstCorp/peekingReader v0.0.0-20171012052444-257fb6f1a1a6 h1:t27CGFMv8DwGwqRPEa2VNof5I/aZwO6q2gfJhN8q0U4= github.com/EndFirstCorp/peekingReader v0.0.0-20171012052444-257fb6f1a1a6/go.mod h1:zpqkXxDsVfEIUZEWvT9yAo8OmRvSlRrcYQ3Zs8sSubA= github.com/PuerkitoBio/goquery v1.10.1 h1:Y8JGYUkXWTGRB6Ars3+j3kN0xg1YqqlwvdTV8WTFQcU= @@ -20,23 +19,24 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/ikawaha/kagome-dict v1.1.0 h1:ePU16KkyonhYLo4YDf/UExmZJBhY/6C946T1SOg1TI4= +github.com/ikawaha/kagome-dict v1.1.0/go.mod h1:tcbTxQQll5voEBnJqGYt2zJuCouUL6buAOrpSxzo9Fg= +github.com/ikawaha/kagome-dict/ipa v1.2.0 h1:lgehXOf2USDkBwGPEBD9sbbOBk3WlkhZ2zejPSLjIJA= +github.com/ikawaha/kagome-dict/ipa v1.2.0/go.mod h1:LRtB3BXipG3Iu4V+KI/E1E7r9GMa79WgAH6IAW4wy6A= +github.com/ikawaha/kagome/v2 v2.10.0 h1:gObyHxSPVudvHXHQecyVAv3DohIifx9MtA8ErXlx+1g= +github.com/ikawaha/kagome/v2 v2.10.0/go.mod h1:IEyFbC0oCkMMaIvTAU3O4IrM5mK0AyWJwM41Tb4u77U= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= -github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattetti/filebuffer v1.0.1 h1:gG7pyfnSIZCxdoKq+cPa8T0hhYtD9NxCdI4D7PTjRLM= github.com/mattetti/filebuffer v1.0.1/go.mod h1:YdMURNDOttIiruleeVr6f56OrMc+MydEnTcXwtkxNVs= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU= github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM= github.com/ncruces/go-sqlite3 v0.21.3 h1:hHkfNQLcbnxPJZhC/RGw9SwP3bfkv/Y0xUHWsr1CdMQ=