This document provides a high-level introduction to CatchFishIfYouCan, a uTools plugin for finding missing names from reference lists. It explains what the plugin does, its key features, and the overall technical architecture. For details on the problem domain and use cases, see Use Case and Motivation. For architectural deep-dive, see High-Level Architecture.
CatchFishIfYouCan (漏网之鱼) is a productivity plugin for the uTools desktop platform that solves a specific comparison problem: given a reference list of names and an input text (e.g., survey responses, attendance records), identify which names from the reference list are missing from the input text.
The plugin eliminates the need for manual Excel sorting or VLOOKUP formulas by providing a one-click solution accessible through uTools' quick panel and super panel interfaces. Users can select text from any source (including Excel cells), invoke the plugin with a keyboard shortcut, and immediately see which names are missing.
Key terminology:
Sources: README.md5-49 src/plugin.json1-36
The plugin provides two primary feature sets, exposed through three uTools commands defined in plugin.json:
| Feature Code | Command | Description |
|---|---|---|
catch | "查找漏网之鱼" | Find missing names by comparing input text against selected namelists |
set | "设置名单" | Open configuration modal to manage existing namelists |
new | "新建名单" | Create a new namelist from selected text or file input |
Finding Missing Names (catch feature):
Namelist Management (set and new features):
.txt, .csv, .md, .markdown)Sources: README.md22-32 src/plugin.json5-35
CatchFishIfYouCan is built using the following technologies:
Core dependencies:
ref and computedutools.dbStorage), native dialogs, and lifecycle eventsThe application runs in an Electron-based environment where uTools provides both the platform APIs and the runtime container.
Sources: README.md63 src/plugin.json2-4
The plugin follows a layered architecture with clear separation between platform integration, application logic, UI components, and data persistence.
Key architectural components:
| Layer | Component | Primary Responsibility |
|---|---|---|
| Platform | uTools Entry Points | Capture user actions (text selection, command invocation) |
| Platform | utools.dbStorage | Persist namelists with key pattern names_* |
| Application | app.js | Initialize Vue app, manage shared state (query, isModalOpen, paraNames) |
| Application | plugin.json | Define three features: catch, set, new |
| Component | MainWindowComp | Display results, handle findFish() workflow |
| Component | ConfigModalComp | Manage namelist CRUD operations |
| Data | store.js | Provide reactive allLists ref, CRUD methods, findFish() algorithm |
| Data | preload.js | Securely expose createReadStream, statSync, writeFile to renderer |
Sources: Diagrams 1, 2, 3, 4 from system architecture analysis
This diagram maps the actual code entities and their communication patterns:
Data flow patterns:
Read-heavy path (Finding missing names):
catch feature → app.js receives query → MainWindowComp reads store.allLists → computes allNamesArray → calls store.findFish() → displays resultsWrite-heavy path (Managing namelists):
set or new feature → ConfigModalComp opens → user creates/updates/deletes → calls store.setList()/store.removeList() → persists to utools.dbStorage → triggers store.updateAllLists() → updates reactive allLists refFile I/O path:
utools.showOpenDialog() or utools.showSaveDialog() → user selects file → component calls window.preload.createReadStream() or window.preload.writeFile() → preload script executes Node.js fs operationsSources: Diagram 4 from system architecture analysis
The core business logic is implemented in the findFish() function within store.js. This algorithm identifies missing names by:
| characters to prevent duplicate matchingExample: Given allNames = ["张三", "张三丰", "李四"] and namesString = "张三丰李四":
"|李四""||"["张三"]This prevents "张三" from matching the substring within "张三丰".
Sources: Diagram 5 from system architecture analysis
The plugin exposes three distinct entry points configured in plugin.json:
Feature configuration details:
catch feature (src/plugin.json7-15):
over (requires text selection)MainWindowComp displays with query pre-filledset feature (src/plugin.json18-22):
ConfigModalComp for managing existing listsnew feature (src/plugin.json24-34):
over (requires text selection)ConfigModalComp opens in creation mode with paraNames setSources: src/plugin.json5-35
Namelists are stored using the uTools database with a namespaced key pattern:
Storage schema:
names_<title> where <title> is the user-defined namelist name{title: string, data: string[]} where data is the array of namesThe store.updateAllLists() function synchronizes the reactive allLists ref with the database by:
utools.dbStoragenames_allLists ref to trigger Vue reactivityThis pattern ensures that all components observing allLists automatically re-render when namelists change.
Sources: Diagram 3 from system architecture analysis
For more detailed information on specific aspects of the system:
MainWindowComp and the finding workflowConfigModalCompstore.js APIs and algorithmsRefresh this wiki
This wiki was recently refreshed. Please wait 5 days to refresh again.