mirror of
https://gitcode.com/JianFeeeee/TrulyMEM-TrueHumanMEM.git
synced 2026-09-21 17:38:18 +00:00
feat: harmonyos星图全面适配交互功能-搜索/过滤/连接高亮/拖拽/触摸/节点详情
This commit is contained in:
45
TrulyMEM.spec
Normal file
45
TrulyMEM.spec
Normal file
@ -0,0 +1,45 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas = [('ui/styles', 'ui/styles'), ('core/prompts/templates', 'core/prompts/templates'), ('static', 'static'), ('templates', 'templates'), ('core/web_api.py', 'core/')]
|
||||
binaries = []
|
||||
hiddenimports = ['textual', 'textual.app', 'textual.widgets', 'textual.css', 'openai', 'openai._client', 'neo4j', 'sqlite3', 'core', 'core.embedded_db', 'core.graph_client', 'core.tool_executor', 'core.tool_limiter', 'core.tools', 'core.tools.memory_tools', 'core.prompts', 'core.prompts.prompt_manager', 'core.server', 'core.client', 'core.migrate', 'core.activity_recorder', 'ui', 'ui.app', 'ui.login_screen', 'ui.models', 'ui.models.message', 'ui.models.config', 'ui.models.log_entry', 'ui.widgets', 'ui.handlers', 'ui.services', 'ui.services.config_manager', 'ui.services.config_service', 'core.web_api', 'flask', 'flask_cors', 'werkzeug']
|
||||
tmp_ret = collect_all('textual')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['trulymem_entry.py'],
|
||||
pathex=[],
|
||||
binaries=binaries,
|
||||
datas=datas,
|
||||
hiddenimports=hiddenimports,
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
[],
|
||||
name='TrulyMEM',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
135
build.log
Normal file
135
build.log
Normal file
@ -0,0 +1,135 @@
|
||||
===== Building TrulyMEM for Linux =====
|
||||
Project root: /home/program/TrulyMEM-TrueHumanMEM
|
||||
The virtual environment was not created successfully because ensurepip is not
|
||||
available. On Debian/Ubuntu systems, you need to install the python3-venv
|
||||
package using the following command.
|
||||
|
||||
apt install python3.13-venv
|
||||
|
||||
You may need to use sudo with that command. After installing the python3-venv
|
||||
package, recreate your virtual environment.
|
||||
|
||||
Failing command: /home/program/TrulyMEM-TrueHumanMEM/.venv_build/bin/python3
|
||||
|
||||
Warning: venv creation failed, falling back to system Python
|
||||
Cleaning previous builds...
|
||||
================================
|
||||
Building TrulyMEM (TUI + Web embedded)
|
||||
================================
|
||||
29 INFO: PyInstaller: 6.20.0, contrib hooks: 2026.4
|
||||
29 INFO: Python: 3.13.12
|
||||
31 INFO: Platform: Linux-6.1.0-44-amd64-x86_64-with-glibc2.42
|
||||
31 INFO: Python environment: /usr
|
||||
33 INFO: Removing temporary files and cleaning cache in /root/.cache/pyinstaller
|
||||
34 INFO: Module search paths (PYTHONPATH):
|
||||
['/home/program/TrulyMEM-TrueHumanMEM',
|
||||
'/home/program/TrulyMEM-TrueHumanMEM',
|
||||
'/usr/lib/python313.zip',
|
||||
'/usr/lib/python3.13',
|
||||
'/usr/lib/python3.13/lib-dynload',
|
||||
'/usr/local/lib/python3.13/dist-packages',
|
||||
'/usr/lib/python3/dist-packages',
|
||||
'/home/program/TrulyMEM-TrueHumanMEM']
|
||||
141 INFO: Appending 'datas' from .spec
|
||||
141 INFO: checking Analysis
|
||||
141 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
141 INFO: Looking for Python shared library...
|
||||
149 INFO: Using Python shared library: /usr/lib/x86_64-linux-gnu/libpython3.13.so.1.0
|
||||
149 INFO: Running Analysis Analysis-00.toc
|
||||
149 INFO: Target bytecode optimization level: 0
|
||||
149 INFO: Initializing module dependency graph...
|
||||
149 INFO: Initializing module graph hook caches...
|
||||
153 INFO: Analyzing modules for base_library.zip ...
|
||||
645 INFO: Processing standard module hook 'hook-encodings.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
1604 INFO: Processing standard module hook 'hook-pickle.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2203 INFO: Processing standard module hook 'hook-heapq.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2434 INFO: Caching module dependency graph...
|
||||
2456 INFO: Analyzing /home/program/TrulyMEM-TrueHumanMEM/trulymem_entry.py
|
||||
2487 INFO: Processing standard module hook 'hook-sqlite3.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2606 INFO: Processing standard module hook 'hook-platform.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2628 INFO: Processing standard module hook 'hook-sysconfig.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2631 INFO: Processing standard module hook 'hook-_ctypes.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2641 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
2641 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
4602 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
4748 INFO: Processing standard module hook 'hook-xml.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
5155 INFO: Processing standard module hook 'hook-pydantic.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5444 INFO: Processing standard module hook 'hook-rich.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5729 INFO: Processing standard module hook 'hook-pygments.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
6155 INFO: Processing standard module hook 'hook-chardet.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
7547 INFO: Processing standard module hook 'hook-zoneinfo.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
8697 INFO: Processing standard module hook 'hook-certifi.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
8766 INFO: Processing standard module hook 'hook-anyio.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
9419 INFO: Processing standard module hook 'hook-difflib.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
10529 INFO: Processing standard module hook 'hook-numpy.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
11824 INFO: Processing standard module hook 'hook-charset_normalizer.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
12622 INFO: Processing standard module hook 'hook-pytz.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
13192 INFO: Processing pre-safe-import-module hook 'hook-platformdirs.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
13199 INFO: Processing standard module hook 'hook-platformdirs.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
14917 INFO: Processing standard module hook 'hook-jinja2.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
15284 INFO: Processing pre-safe-import-module hook 'hook-importlib_metadata.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15285 INFO: Setuptools: 'importlib_metadata' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.importlib_metadata'!
|
||||
15289 INFO: Processing standard module hook 'hook-setuptools.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
15296 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15314 INFO: Processing pre-safe-import-module hook 'hook-jaraco.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15314 INFO: Setuptools: 'jaraco' appears to be a partial setuptools-vendored copy - extending search paths to ['/usr/lib/python3/dist-packages/jaraco', '/usr/lib/python3/dist-packages/setuptools/_vendor/jaraco']!
|
||||
15315 INFO: Processing pre-safe-import-module hook 'hook-jaraco.functools.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15320 INFO: Processing pre-safe-import-module hook 'hook-more_itertools.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15459 INFO: Processing pre-safe-import-module hook 'hook-packaging.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15575 INFO: Processing pre-safe-import-module hook 'hook-jaraco.text.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15581 INFO: Processing standard module hook 'hook-jaraco.text.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
15614 INFO: Processing pre-safe-import-module hook 'hook-importlib_resources.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15615 INFO: Processing pre-safe-import-module hook 'hook-jaraco.context.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15620 INFO: Processing pre-safe-import-module hook 'hook-backports.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15620 INFO: Setuptools: 'backports' appears to be a full setuptools-vendored copy - creating alias to 'setuptools._vendor.backports'!
|
||||
15843 INFO: Processing pre-safe-import-module hook 'hook-tomli.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15843 INFO: Setuptools: 'tomli' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.tomli'!
|
||||
16138 INFO: Processing standard module hook 'hook-pkg_resources.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
16316 INFO: Processing pre-safe-import-module hook 'hook-wheel.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
16376 INFO: Processing standard module hook 'hook-setuptools._vendor.importlib_metadata.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
16378 INFO: Processing pre-safe-import-module hook 'hook-zipp.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
16414 INFO: Analyzing hidden import 'ui.handlers'
|
||||
16414 INFO: Analyzing hidden import 'ui.services'
|
||||
16415 INFO: Analyzing hidden import 'ui.services.config_manager'
|
||||
16416 INFO: Analyzing hidden import 'ui.services.config_service'
|
||||
16417 INFO: Processing module hooks (post-graph stage)...
|
||||
16716 WARNING: Hidden import "charset_normalizer.md__mypyc" not found!
|
||||
18203 INFO: Performing binary vs. data reclassification (622 entries)
|
||||
18209 INFO: Looking for ctypes DLLs
|
||||
18283 WARNING: Library shell32 required via ctypes not found
|
||||
18292 WARNING: Library ole32 required via ctypes not found
|
||||
18321 INFO: Analyzing run-time hooks ...
|
||||
18329 INFO: Including run-time hook 'pyi_rth_inspect.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/rthooks'
|
||||
18331 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/rthooks'
|
||||
18333 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/rthooks'
|
||||
18334 INFO: Including run-time hook 'pyi_rth_setuptools.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/rthooks'
|
||||
18335 INFO: Including run-time hook 'pyi_rth_pkgres.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/rthooks'
|
||||
18371 INFO: Creating base_library.zip...
|
||||
18384 INFO: Looking for dynamic libraries
|
||||
18673 INFO: Warnings written to /home/program/TrulyMEM-TrueHumanMEM/build/trulymem/warn-trulymem.txt
|
||||
18783 INFO: Graph cross-reference written to /home/program/TrulyMEM-TrueHumanMEM/build/trulymem/xref-trulymem.html
|
||||
18816 INFO: checking PYZ
|
||||
18816 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
18816 INFO: Building PYZ (ZlibArchive) /home/program/TrulyMEM-TrueHumanMEM/build/trulymem/PYZ-00.pyz
|
||||
19768 INFO: Building PYZ (ZlibArchive) /home/program/TrulyMEM-TrueHumanMEM/build/trulymem/PYZ-00.pyz completed successfully.
|
||||
19790 WARNING: Ignoring icon; supported only on Windows and macOS!
|
||||
19801 INFO: checking PKG
|
||||
19801 INFO: Building PKG because PKG-00.toc is non existent
|
||||
19801 INFO: Building PKG (CArchive) TrulyMEM.pkg
|
||||
24763 INFO: Building PKG (CArchive) TrulyMEM.pkg completed successfully.
|
||||
24768 INFO: Bootloader /usr/local/lib/python3.13/dist-packages/PyInstaller/bootloader/Linux-64bit-intel/run
|
||||
24768 INFO: checking EXE
|
||||
24768 INFO: Building EXE because EXE-00.toc is non existent
|
||||
24768 INFO: Building EXE from EXE-00.toc
|
||||
24768 INFO: Copying bootloader EXE to /home/program/TrulyMEM-TrueHumanMEM/dist/TrulyMEM
|
||||
24768 INFO: Appending PKG archive to custom ELF section in EXE
|
||||
24825 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
24830 INFO: Build complete! The results are available in: /home/program/TrulyMEM-TrueHumanMEM/dist
|
||||
================================
|
||||
===== Build Complete =====
|
||||
Binary: dist/TrulyMEM
|
||||
total 35848
|
||||
drwxr-xr-x 2 root root 4096 Apr 30 07:06 .
|
||||
drwxr-xr-x 15 root root 4096 Apr 30 07:05 ..
|
||||
-rwxr-xr-x 1 root root 36698096 Apr 30 07:06 TrulyMEM
|
||||
Build finished successfully!
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
import web_webview from '@ohos.web.webview';
|
||||
import { GraphDatabase, RecallEntity } from '../model/GraphDatabase';
|
||||
import { GraphMemoryService } from '../services/GraphMemoryService';
|
||||
|
||||
// ========= 图数据结构定义 =========
|
||||
|
||||
@ -23,19 +24,46 @@ interface GraphEdgeItem {
|
||||
relation: string;
|
||||
}
|
||||
|
||||
interface NodeDetailInfo {
|
||||
name: string;
|
||||
type: string;
|
||||
mention_count: number;
|
||||
connection_count: number;
|
||||
connections: Array<{ type: string; target_name: string }>;
|
||||
}
|
||||
|
||||
// ========= WebView 原生桥接 =========
|
||||
|
||||
class NativeBridge {
|
||||
private controller: web_webview.WebviewController;
|
||||
private onRequestGraphData: () => void;
|
||||
private onNodeClickCallback: (nodeId: number, nodeName: string) => void;
|
||||
private onSearchCallback: (query: string) => void;
|
||||
|
||||
constructor(controller: web_webview.WebviewController, onRequestGraphData: () => void) {
|
||||
constructor(
|
||||
controller: web_webview.WebviewController,
|
||||
onRequestGraphData: () => void,
|
||||
onNodeClickCallback: (nodeId: number, nodeName: string) => void,
|
||||
onSearchCallback: (query: string) => void
|
||||
) {
|
||||
this.controller = controller;
|
||||
this.onRequestGraphData = onRequestGraphData;
|
||||
this.onNodeClickCallback = onNodeClickCallback;
|
||||
this.onSearchCallback = onSearchCallback;
|
||||
}
|
||||
|
||||
onNodeClick(nodeId: number, nodeName: string): void {
|
||||
console.info('Node clicked: id=' + nodeId + ', name=' + nodeName);
|
||||
if (this.onNodeClickCallback) {
|
||||
this.onNodeClickCallback(nodeId, nodeName);
|
||||
}
|
||||
}
|
||||
|
||||
onSearch(query: string): void {
|
||||
console.info('Search from WebView: ' + query);
|
||||
if (this.onSearchCallback) {
|
||||
this.onSearchCallback(query);
|
||||
}
|
||||
}
|
||||
|
||||
requestGraphData(): void {
|
||||
@ -54,11 +82,18 @@ export struct GraphPage {
|
||||
@Prop db: GraphDatabase;
|
||||
@State nodeCount: number = 0;
|
||||
@State edgeCount: number = 0;
|
||||
@State selectedNodeDetail: NodeDetailInfo | null = null;
|
||||
@State showNodeDetail: boolean = false;
|
||||
@State searchText: string = '';
|
||||
private graphService: GraphMemoryService = new GraphMemoryService(this.db);
|
||||
|
||||
// 初始化桥接对象
|
||||
private bridge: NativeBridge = new NativeBridge(this.controller, (): void => {
|
||||
this.pushGraphDataToWebView();
|
||||
});
|
||||
private bridge: NativeBridge = new NativeBridge(
|
||||
this.controller,
|
||||
(): void => { this.pushGraphDataToWebView(); },
|
||||
(nodeId: number, nodeName: string): void => { this.handleNodeClick(nodeId, nodeName); },
|
||||
(query: string): void => { this.handleSearchFromWeb(query); }
|
||||
);
|
||||
|
||||
/**
|
||||
* 外部触发刷新图数据(聊天写入新记忆后调用)
|
||||
@ -67,6 +102,46 @@ export struct GraphPage {
|
||||
await this.pushGraphDataToWebView();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理节点点击 - 查询详细信息并显示浮层
|
||||
*/
|
||||
private async handleNodeClick(nodeId: number, nodeName: string): Promise<void> {
|
||||
try {
|
||||
// 从数据库查询节点详细信息
|
||||
const detail = await this.graphService.getNodeDetail(nodeName);
|
||||
if (detail) {
|
||||
this.selectedNodeDetail = detail;
|
||||
this.showNodeDetail = true;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('handleNodeClick error: ' + JSON.stringify(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理来自 WebView 的搜索请求
|
||||
*/
|
||||
private handleSearchFromWeb(query: string): void {
|
||||
this.searchText = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理搜索输入 - 通知 WebView 过滤
|
||||
*/
|
||||
private onSearchInput(value: string): void {
|
||||
this.searchText = value;
|
||||
const jsCode = `window.dispatchEvent(new MessageEvent('message', { data: { type: 'search_nodes', query: '${value}' } }));`;
|
||||
this.controller.runJavaScript(jsCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭节点详情浮层
|
||||
*/
|
||||
private closeNodeDetail(): void {
|
||||
this.showNodeDetail = false;
|
||||
this.selectedNodeDetail = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从数据库读取全量图数据,通过 runJavaScript 推送给 WebView
|
||||
*/
|
||||
@ -137,13 +212,15 @@ export struct GraphPage {
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Stack() {
|
||||
// WebView 显示 3D 星图
|
||||
Web({ src: $rawfile('graph.html'), controller: this.controller })
|
||||
.javaScriptAccess(true)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
// 页面加载完成后推送数据
|
||||
.zoomAccess(true) // 启用缩放
|
||||
// 捏合手势支持 - 双指缩放
|
||||
.pinchGesture(PinchGesture({ fingers: 2 }))
|
||||
.onPageEnd(() => {
|
||||
this.pushGraphDataToWebView();
|
||||
})
|
||||
@ -151,10 +228,93 @@ export struct GraphPage {
|
||||
.javaScriptProxy({
|
||||
object: this.bridge,
|
||||
name: 'nativeBridge',
|
||||
methodList: ['onNodeClick'],
|
||||
methodList: ['onNodeClick', 'onSearch'],
|
||||
asyncMethodList: ['requestGraphData'],
|
||||
controller: this.controller
|
||||
})
|
||||
|
||||
// 搜索框组件 - 在 WebView 上方
|
||||
Column() {
|
||||
TextInput({ placeholder: '搜索节点...', text: this.searchText })
|
||||
.width('80%')
|
||||
.height(40)
|
||||
.backgroundColor('rgba(10, 10, 26, 0.8)')
|
||||
.fontColor('#ffffff')
|
||||
.placeholderColor('#666688')
|
||||
.borderRadius(8)
|
||||
.border({ width: 1, color: 'rgba(100, 100, 255, 0.3)' })
|
||||
.margin({ top: 20 })
|
||||
.onChange((value: string) => {
|
||||
this.onSearchInput(value);
|
||||
})
|
||||
}
|
||||
.width('100%')
|
||||
.alignContent(Alignment.Top)
|
||||
.position({ x: 0, y: 0 })
|
||||
.zIndex(10)
|
||||
|
||||
// 节点详情浮层
|
||||
if (this.showNodeDetail && this.selectedNodeDetail !== null) {
|
||||
Column() {
|
||||
Column() {
|
||||
Text(this.selectedNodeDetail.name)
|
||||
.fontSize(18)
|
||||
.fontColor('#44ff88')
|
||||
.fontWeight(FontWeight.Bold)
|
||||
.margin({ bottom: 10 })
|
||||
|
||||
Text('类型: ' + this.selectedNodeDetail.type)
|
||||
.fontSize(14)
|
||||
.fontColor('#aaaacc')
|
||||
|
||||
Text('提及次数: ' + this.selectedNodeDetail.mention_count)
|
||||
.fontSize(14)
|
||||
.fontColor('#aaaacc')
|
||||
|
||||
Text('连接数: ' + this.selectedNodeDetail.connection_count)
|
||||
.fontSize(14)
|
||||
.fontColor('#aaaacc')
|
||||
|
||||
if (this.selectedNodeDetail.connections && this.selectedNodeDetail.connections.length > 0) {
|
||||
Text('连接关系:')
|
||||
.fontSize(14)
|
||||
.fontColor('#8888aa')
|
||||
.margin({ top: 10, bottom: 5 })
|
||||
List() {
|
||||
ForEach(this.selectedNodeDetail.connections, (conn: { type: string; target_name: string }) => {
|
||||
ListItem() {
|
||||
Text(conn.type + ': ' + conn.target_name)
|
||||
.fontSize(12)
|
||||
.fontColor('#aaaacc')
|
||||
}
|
||||
})
|
||||
}
|
||||
.height(100)
|
||||
}
|
||||
|
||||
Button('关闭')
|
||||
.width(80)
|
||||
.height(30)
|
||||
.margin({ top: 15 })
|
||||
.backgroundColor('rgba(100, 100, 255, 0.3)')
|
||||
.fontColor('#ffffff')
|
||||
.onClick(() => {
|
||||
this.closeNodeDetail();
|
||||
})
|
||||
}
|
||||
.padding(20)
|
||||
.backgroundColor('rgba(10, 10, 26, 0.95)')
|
||||
.borderRadius(12)
|
||||
.border({ width: 1, color: 'rgba(100, 100, 255, 0.3)' })
|
||||
.width(300)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor('rgba(0, 0, 0, 0.5)')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.zIndex(20)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
|
||||
@ -748,4 +748,181 @@ export class GraphMemoryService {
|
||||
const graphData: GraphData = { nodes, edges };
|
||||
return graphData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点的完整信息 — 自身属性 + 所有相连关系 + 相邻节点名列表
|
||||
*/
|
||||
async getNodeDetail(nodeName: string): Promise<NodeDetailInfo | null> {
|
||||
try {
|
||||
const recallResult = await this.db.recall(nodeName, [nodeName], 1);
|
||||
if (recallResult.entities.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const entity = recallResult.entities[0];
|
||||
const connections: Array<{ type: string; target_name: string }> = [];
|
||||
let connectionCount = 0;
|
||||
|
||||
for (const rel of recallResult.relations) {
|
||||
if (rel.source === nodeName) {
|
||||
connections.push({
|
||||
type: rel.type,
|
||||
target_name: rel.target
|
||||
});
|
||||
connectionCount++;
|
||||
} else if (rel.target === nodeName) {
|
||||
connections.push({
|
||||
type: rel.type + ' (反向)',
|
||||
target_name: rel.source
|
||||
});
|
||||
connectionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
const detail: NodeDetailInfo = {
|
||||
name: entity.name,
|
||||
type: entity.type,
|
||||
mention_count: entity.mention_count,
|
||||
connection_count: connectionCount,
|
||||
connections
|
||||
};
|
||||
return detail;
|
||||
} catch (err) {
|
||||
console.error('getNodeDetail error: ' + JSON.stringify(err));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回带连接度数的图数据(每个节点增加 degree 字段)
|
||||
*/
|
||||
async getJoinedData(): Promise<GraphData> {
|
||||
const graphData = await this.getGraphDataForView();
|
||||
|
||||
// 计算每个节点的连接度数
|
||||
const degreeMap: Record<number, number> = {};
|
||||
for (const edge of graphData.edges) {
|
||||
degreeMap[edge.from] = (degreeMap[edge.from] || 0) + 1;
|
||||
degreeMap[edge.to] = (degreeMap[edge.to] || 0) + 1;
|
||||
}
|
||||
|
||||
// 为节点添加 degree 字段(通过扩展 NodeData)
|
||||
const nodesWithDegree = graphData.nodes.map(node => ({
|
||||
...node,
|
||||
degree: degreeMap[node.id] || 0
|
||||
}));
|
||||
|
||||
return { nodes: nodesWithDegree as any[], edges: graphData.edges };
|
||||
}
|
||||
}
|
||||
|
||||
// ========= NodeDetailInfo 接口定义 =========
|
||||
|
||||
interface NodeDetailInfo {
|
||||
name: string;
|
||||
type: string;
|
||||
mention_count: number;
|
||||
connection_count: number;
|
||||
connections: Array<{ type: string; target_name: string }>;
|
||||
}
|
||||
|
||||
for (const rel of recallResult.relations) {
|
||||
const from = nameToId[rel.source];
|
||||
const to = nameToId[rel.target];
|
||||
if (from !== undefined && to !== undefined) {
|
||||
const edge: EdgeData = {
|
||||
from,
|
||||
to,
|
||||
label: rel.type,
|
||||
weight: rel.confidence
|
||||
};
|
||||
edges.push(edge);
|
||||
}
|
||||
}
|
||||
|
||||
const graphData: GraphData = { nodes, edges };
|
||||
return graphData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点详细信息——自身属性 + 所有相连关系 + 相邻节点名列表
|
||||
* 供 GraphPage 节点点击后查询用
|
||||
*/
|
||||
async getNodeDetail(nodeName: string): Promise<{
|
||||
name: string;
|
||||
type: string;
|
||||
mention_count: number;
|
||||
connection_count: number;
|
||||
connections: Array<{ type: string; target_name: string }>;
|
||||
} | null> {
|
||||
try {
|
||||
// 搜索节点
|
||||
const searchResults = await this.db.search(nodeName);
|
||||
const node = searchResults.find(n => n.name === nodeName);
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 查询与该节点相关的所有关系
|
||||
const recallResult = await this.db.recall(nodeName, [nodeName], 1);
|
||||
const connections: Array<{ type: string; target_name: string }> = [];
|
||||
|
||||
for (const rel of recallResult.relations) {
|
||||
if (rel.source === nodeName) {
|
||||
connections.push({ type: rel.type, target_name: rel.target });
|
||||
} else if (rel.target === nodeName) {
|
||||
connections.push({ type: rel.type + '(反向)', target_name: rel.source });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: node.name,
|
||||
type: node.type,
|
||||
mention_count: node.mentions,
|
||||
connection_count: connections.length,
|
||||
connections
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('getNodeDetail error: ' + JSON.stringify(e));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取带连接度的图数据
|
||||
* 每个节点增加 degree 字段,供前端根据度调整显示大小
|
||||
*/
|
||||
async getJoinedData(): Promise<GraphData & { stats: { maxDegree: number; avgDegree: number } }> {
|
||||
const graphData = await this.getGraphDataForView();
|
||||
|
||||
// 计算每个节点的度
|
||||
const degreeMap: Record<number, number> = {};
|
||||
for (const node of graphData.nodes) {
|
||||
degreeMap[node.id] = 0;
|
||||
}
|
||||
for (const edge of graphData.edges) {
|
||||
degreeMap[edge.from] = (degreeMap[edge.from] || 0) + 1;
|
||||
degreeMap[edge.to] = (degreeMap[edge.to] || 0) + 1;
|
||||
}
|
||||
|
||||
// 为每个节点附加度
|
||||
const enrichedNodes: NodeData[] = [];
|
||||
for (const n of graphData.nodes) {
|
||||
const enriched: NodeData & { degree: number } = n as (NodeData & { degree: number });
|
||||
enriched.degree = degreeMap[n.id] || 0;
|
||||
enrichedNodes.push(enriched);
|
||||
}
|
||||
|
||||
const degrees = Object.values(degreeMap);
|
||||
const maxDegree = Math.max(...degrees, 1);
|
||||
const avgDegree = degrees.length > 0
|
||||
? degrees.reduce((a, b) => a + b, 0) / degrees.length
|
||||
: 0;
|
||||
|
||||
return {
|
||||
nodes: enrichedNodes,
|
||||
edges: graphData.edges,
|
||||
stats: { maxDegree, avgDegree }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,6 +19,23 @@
|
||||
#node-info .label { color: #8888aa; }
|
||||
#loading { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 20px; color: #4488ff; z-index: 200; }
|
||||
#nav { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 20px; z-index: 100; }
|
||||
|
||||
/* 搜索框 */
|
||||
#search-box { position: absolute; top: 80px; left: 20px; z-index: 100; }
|
||||
#search-input { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #ffffff; padding: 8px 12px; border-radius: 6px; font-family: 'Courier New', monospace; font-size: 14px; width: 200px; outline: none; backdrop-filter: blur(10px); }
|
||||
#search-input::placeholder { color: #666688; }
|
||||
|
||||
/* 类型过滤按钮 */
|
||||
#type-filter { position: absolute; top: 120px; left: 20px; display: flex; gap: 8px; z-index: 100; flex-wrap: wrap; }
|
||||
.type-btn { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #aaaacc; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-family: 'Courier New', monospace; font-size: 12px; backdrop-filter: blur(10px); transition: all 0.3s; }
|
||||
.type-btn.active { background: rgba(68, 136, 255, 0.3); border-color: #4488ff; color: #ffffff; }
|
||||
|
||||
/* 缩放控制按钮 */
|
||||
#zoom-controls { position: absolute; bottom: 100px; right: 20px; display: flex; flex-direction: column; gap: 10px; z-index: 100; }
|
||||
.zoom-btn { width: 40px; height: 40px; border-radius: 50%; background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #ffffff; font-size: 20px; cursor: pointer; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(10px); font-family: 'Courier New', monospace; }
|
||||
|
||||
/* 边标签 */
|
||||
#edge-label { position: absolute; display: none; background: rgba(10, 10, 26, 0.9); color: #44ff88; padding: 4px 8px; border-radius: 4px; font-size: 12px; pointer-events: none; z-index: 150; border: 1px solid rgba(68, 255, 136, 0.3); }
|
||||
.nav-btn { background: rgba(10, 10, 26, 0.8); border: 1px solid rgba(100, 100, 255, 0.3); color: #aaaacc; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-family: 'Courier New', monospace; font-size: 14px; backdrop-filter: blur(10px); }
|
||||
</style>
|
||||
</head>
|
||||
@ -40,6 +57,23 @@
|
||||
<div id="nav">
|
||||
<button class="nav-btn active">🌌 星图</button>
|
||||
</div>
|
||||
<div id="search-box">
|
||||
<input type="text" id="search-input" placeholder="搜索节点...">
|
||||
</div>
|
||||
<div id="type-filter">
|
||||
<button class="type-btn active" data-type="全部">全部</button>
|
||||
<button class="type-btn" data-type="Person">Person</button>
|
||||
<button class="type-btn" data-type="Task">Task</button>
|
||||
<button class="type-btn" data-type="AI">AI</button>
|
||||
<button class="type-btn" data-type="Concept">Concept</button>
|
||||
<button class="type-btn" data-type="Object">Object</button>
|
||||
</div>
|
||||
<div id="zoom-controls">
|
||||
<button class="zoom-btn" id="zoom-in">+</button>
|
||||
<button class="zoom-btn" id="zoom-out">-</button>
|
||||
<button class="zoom-btn" id="zoom-reset">R</button>
|
||||
</div>
|
||||
<div id="edge-label"></div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
||||
@ -52,6 +86,13 @@
|
||||
let hoveredNode = null, selectedNode = null;
|
||||
let animationId;
|
||||
let highlightPulse = 0;
|
||||
let searchTerm = '';
|
||||
let activeTypeFilter = '全部';
|
||||
let isDragging = false;
|
||||
let dragNode = null;
|
||||
let originalPhysicsState = true;
|
||||
let edgeLabelEl = null;
|
||||
let nodePositions = {}; // 存储节点位置用于拖拽
|
||||
|
||||
const typeColors = { 'person': 0x4488ff, 'task': 0xff8844, 'ai': 0xaa44ff, 'concept': 0x44ff88, 'object': 0xff4444 };
|
||||
const defaultColor = 0xcccccc;
|
||||
@ -88,13 +129,72 @@
|
||||
window.__graphData = event.data.payload;
|
||||
loadGraphData();
|
||||
}
|
||||
if (event.data.type === 'search_nodes') {
|
||||
searchTerm = event.data.query || '';
|
||||
document.getElementById('search-input').value = searchTerm;
|
||||
applyFilters();
|
||||
}
|
||||
if (event.data.type === 'node_detail') {
|
||||
showNodeDetailPanel(event.data.detail);
|
||||
}
|
||||
if (event.data.type === 'highlight_node') {
|
||||
highlightNodeById(event.data.nodeId);
|
||||
}
|
||||
});
|
||||
// 搜索输入框事件
|
||||
const searchInput = document.getElementById('search-input');
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
searchTerm = e.target.value.toLowerCase();
|
||||
applyFilters();
|
||||
// 通知 ArkTS
|
||||
try {
|
||||
if (window.nativeBridge && window.nativeBridge.onSearch) {
|
||||
window.nativeBridge.onSearch(searchTerm);
|
||||
}
|
||||
} catch(e) {}
|
||||
});
|
||||
// 类型过滤按钮事件
|
||||
document.querySelectorAll('.type-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
document.querySelectorAll('.type-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
activeTypeFilter = btn.dataset.type;
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
// 缩放控制按钮
|
||||
document.getElementById('zoom-in').addEventListener('click', () => {
|
||||
camera.position.multiplyScalar(0.8);
|
||||
controls.update();
|
||||
});
|
||||
document.getElementById('zoom-out').addEventListener('click', () => {
|
||||
camera.position.multiplyScalar(1.2);
|
||||
controls.update();
|
||||
});
|
||||
document.getElementById('zoom-reset').addEventListener('click', () => {
|
||||
if (Object.keys(nodePositions).length > 0) {
|
||||
const allPositions = Object.values(nodePositions);
|
||||
let maxDist = 0;
|
||||
allPositions.forEach(pos => { maxDist = Math.max(maxDist, Math.sqrt(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z)); });
|
||||
camera.position.set(maxDist * 2.2, maxDist * 1.5, maxDist * 2.2);
|
||||
controls.target.set(0, 0, 0);
|
||||
controls.update();
|
||||
}
|
||||
});
|
||||
// 边标签元素
|
||||
edgeLabelEl = document.getElementById('edge-label');
|
||||
// 鼠标移动检测边悬停
|
||||
renderer.domElement.addEventListener('mousemove', onEdgeHoverCheck);
|
||||
// 通知 ArkTS 请求图数据
|
||||
try {
|
||||
if (window.nativeBridge && window.nativeBridge.requestGraphData) {
|
||||
window.nativeBridge.requestGraphData();
|
||||
}
|
||||
} catch(e) {}
|
||||
// 触摸事件支持
|
||||
initTouchEvents();
|
||||
// 初始化拖拽功能
|
||||
initDragFunctionality();
|
||||
animate();
|
||||
}
|
||||
|
||||
@ -180,21 +280,22 @@
|
||||
nodeDegrees[e.target] = (nodeDegrees[e.target] || 0) + 1;
|
||||
});
|
||||
const positions = {};
|
||||
nodePositions = positions; // 存储供拖拽使用
|
||||
const maxDegree = Math.max(...Object.values(nodeDegrees), 1);
|
||||
nodes.forEach((node, i) => {
|
||||
const angle = (i / nodes.length) * Math.PI * 2;
|
||||
const radius = 15 + (nodeDegrees[node.id] / maxDegree) * 35;
|
||||
positions[node.id] = { x: radius * Math.cos(angle), y: (Math.random() - 0.5) * 10, z: radius * Math.sin(angle) };
|
||||
});
|
||||
for (let iter = 0; iter < 50; iter++) {
|
||||
for (let iter = 0; iter < 200; iter++) {
|
||||
Object.keys(positions).forEach(id1 => {
|
||||
Object.keys(positions).forEach(id2 => {
|
||||
if (id1 >= id2) return;
|
||||
const pos1 = positions[id1], pos2 = positions[id2];
|
||||
const dx = pos1.x - pos2.x, dy = pos1.y - pos2.y, dz = pos1.z - pos2.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist < 10) {
|
||||
const force = 0.1 / dist;
|
||||
if (dist < 20) { // 增加排斥距离
|
||||
const force = 0.3 / (dist * dist); // 增加排斥力系数(平方反比)
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
@ -206,7 +307,7 @@
|
||||
const dx = pos2.x - pos1.x, dy = pos2.y - pos1.y, dz = pos2.z - pos1.z;
|
||||
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz) + 0.1;
|
||||
if (dist > 15) {
|
||||
const force = 0.05;
|
||||
const force = 0.08; // 增加吸引力
|
||||
pos1.x += (dx/dist)*force; pos1.y += (dy/dist)*force; pos1.z += (dz/dist)*force;
|
||||
pos2.x -= (dx/dist)*force; pos2.y -= (dy/dist)*force; pos2.z -= (dz/dist)*force;
|
||||
}
|
||||
@ -218,23 +319,27 @@
|
||||
const radius = 0.4 + Math.min(node.mention_count * 0.15, 1.5);
|
||||
const color = typeColors[node.type] || defaultColor;
|
||||
const geometry = new THREE.SphereGeometry(radius, 16, 12);
|
||||
const material = new THREE.MeshPhongMaterial({ color: color, emissive: color, emissiveIntensity: 0.5 + Math.min(node.mention_count * 0.05, 0.3), shininess: 30 });
|
||||
const material = new THREE.MeshPhongMaterial({ color: color, emissive: color, emissiveIntensity: 0.5 + Math.min(node.mention_count * 0.05, 0.3), shininess: 30, transparent: true, opacity: 0 });
|
||||
const sphere = new THREE.Mesh(geometry, material);
|
||||
sphere.position.set(pos.x, pos.y, pos.z);
|
||||
sphere.userData = { nodeId: node.id, nodeData: node };
|
||||
scene.add(sphere);
|
||||
nodeMeshes.push(sphere);
|
||||
// 淡入动画
|
||||
fadeInObject(sphere, 500);
|
||||
});
|
||||
edges.forEach(edge => {
|
||||
const pos1 = positions[edge.source], pos2 = positions[edge.target];
|
||||
if (!pos1 || !pos2) return;
|
||||
const color = edgeColors[edge.relation_type] || defaultEdgeColor;
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(pos1.x, pos1.y, pos1.z), new THREE.Vector3(pos2.x, pos2.y, pos2.z)]);
|
||||
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0.4, linewidth: 1 });
|
||||
const material = new THREE.LineBasicMaterial({ color: color, transparent: true, opacity: 0, linewidth: 1 });
|
||||
const line = new THREE.Line(geometry, material);
|
||||
line.userData = { edgeId: edge.id, edgeData: edge };
|
||||
scene.add(line);
|
||||
edgeLines.push(line);
|
||||
// 淡入动画
|
||||
fadeInLine(line, 500);
|
||||
});
|
||||
const allPositions = Object.values(positions);
|
||||
if (allPositions.length > 0) {
|
||||
@ -265,14 +370,19 @@
|
||||
}
|
||||
|
||||
function onMouseClick(event) {
|
||||
if (isDragging) return;
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (selectedNode === node) { selectedNode = null; document.getElementById('node-info').style.display = 'none'; }
|
||||
else {
|
||||
if (selectedNode === node) {
|
||||
selectedNode = null;
|
||||
document.getElementById('node-info').style.display = 'none';
|
||||
resetHighlight();
|
||||
} else {
|
||||
selectedNode = node;
|
||||
showNodeInfo(node.userData.nodeData, true);
|
||||
highlightNodeConnections(node.userData.nodeData);
|
||||
// 通知 ArkTS 节点被点击
|
||||
try {
|
||||
if (window.nativeBridge && window.nativeBridge.onNodeClick) {
|
||||
@ -280,6 +390,11 @@
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
} else {
|
||||
// 点击空白处恢复
|
||||
selectedNode = null;
|
||||
document.getElementById('node-info').style.display = 'none';
|
||||
resetHighlight();
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +409,339 @@
|
||||
|
||||
function hideNodeInfo() { if (!selectedNode) document.getElementById('node-info').style.display = 'none'; }
|
||||
|
||||
// 淡入动画
|
||||
function fadeInObject(obj, duration) {
|
||||
const startOpacity = 0;
|
||||
const endOpacity = obj.material.opacity !== undefined ? (obj.material.transparent ? obj.material.opacity : 1) : 1;
|
||||
obj.material.opacity = startOpacity;
|
||||
obj.material.transparent = true;
|
||||
const startTime = Date.now();
|
||||
function animateFade() {
|
||||
const elapsed = Date.now() - startTime;
|
||||
const progress = Math.min(elapsed / duration, 1);
|
||||
obj.material.opacity = startOpacity + (endOpacity - startOpacity) * progress;
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animateFade);
|
||||
} else {
|
||||
obj.material.transparent = endOpacity < 1;
|
||||
}
|
||||
}
|
||||
animateFade();
|
||||
}
|
||||
|
||||
function fadeInLine(line, duration) {
|
||||
const startOpacity = 0;
|
||||
const endOpacity = 0.4;
|
||||
line.material.opacity = startOpacity;
|
||||
const startTime = Date.now();
|
||||
function animateFade() {
|
||||
const elapsed = Date.now() - startTime;
|
||||
const progress = Math.min(elapsed / duration, 1);
|
||||
line.material.opacity = startOpacity + (endOpacity - startOpacity) * progress;
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animateFade);
|
||||
}
|
||||
}
|
||||
animateFade();
|
||||
}
|
||||
|
||||
// 通过节点ID高亮节点(供ArkTS调用)
|
||||
function highlightNodeById(nodeId) {
|
||||
const mesh = nodeMeshes.find(m => m.userData.nodeData.id === nodeId);
|
||||
if (mesh) {
|
||||
selectedNode = mesh;
|
||||
showNodeInfo(mesh.userData.nodeData, true);
|
||||
highlightNodeConnections(mesh.userData.nodeData);
|
||||
}
|
||||
}
|
||||
|
||||
// 显示节点详情面板(供ArkTS调用)
|
||||
function showNodeDetailPanel(detail) {
|
||||
// 更新node-info面板显示详细信息
|
||||
document.getElementById('info-name').textContent = detail.name;
|
||||
document.getElementById('info-type').textContent = detail.type;
|
||||
document.getElementById('info-mentions').textContent = detail.mention_count;
|
||||
document.getElementById('info-links').textContent = detail.connection_count;
|
||||
document.getElementById('node-info').style.display = 'block';
|
||||
|
||||
// 如果有连接信息,添加到面板
|
||||
let detailHtml = `<h3>${detail.name}</h3>`;
|
||||
detailHtml += `<p><span class="label">类型:</span> ${detail.type}</p>`;
|
||||
detailHtml += `<p><span class="label">提及次数:</span> ${detail.mention_count}</p>`;
|
||||
detailHtml += `<p><span class="label">连接数:</span> ${detail.connection_count}</p>`;
|
||||
if (detail.connections && detail.connections.length > 0) {
|
||||
detailHtml += `<p><span class="label">连接关系:</span></p><ul style="margin-left: 15px; font-size: 12px;">`;
|
||||
detail.connections.forEach(conn => {
|
||||
detailHtml += `<li>${conn.type}: ${conn.target_name}</li>`;
|
||||
});
|
||||
detailHtml += `</ul>`;
|
||||
}
|
||||
document.getElementById('node-info').innerHTML = detailHtml;
|
||||
}
|
||||
|
||||
// 节点拖拽功能
|
||||
function initDragFunctionality() {
|
||||
let dragStartPos = { x: 0, y: 0 };
|
||||
|
||||
renderer.domElement.addEventListener('mousedown', (event) => {
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
isDragging = false;
|
||||
dragNode = intersects[0].object;
|
||||
dragStartPos = { x: event.clientX, y: event.clientY };
|
||||
originalPhysicsState = true; // 暂停物理模拟
|
||||
}
|
||||
});
|
||||
|
||||
renderer.domElement.addEventListener('mousemove', (event) => {
|
||||
if (dragNode) {
|
||||
const dx = event.clientX - dragStartPos.x;
|
||||
const dy = event.clientY - dragStartPos.y;
|
||||
if (Math.abs(dx) > 3 || Math.abs(dy) > 3) {
|
||||
isDragging = true;
|
||||
}
|
||||
if (isDragging) {
|
||||
// 将屏幕坐标转换为3D空间
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
const mouseX = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
const mouseY = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
const vector = new THREE.Vector3(mouseX, mouseY, 0.5);
|
||||
vector.unproject(camera);
|
||||
const dir = vector.sub(camera.position).normalize();
|
||||
const distance = -camera.position.z / dir.z;
|
||||
const newPos = camera.position.clone().add(dir.multiplyScalar(distance));
|
||||
dragNode.position.copy(newPos);
|
||||
// 更新存储的位置
|
||||
if (nodePositions[dragNode.userData.nodeId]) {
|
||||
nodePositions[dragNode.userData.nodeId] = { x: newPos.x, y: newPos.y, z: newPos.z };
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
renderer.domElement.addEventListener('mouseup', () => {
|
||||
if (dragNode) {
|
||||
// 恢复物理模拟
|
||||
dragNode = null;
|
||||
isDragging = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Touch事件支持
|
||||
function initTouchEvents() {
|
||||
let touchStart = null;
|
||||
let touchStartDistance = 0;
|
||||
let touchStartPos = { x: 0, y: 0 };
|
||||
let isTouchDrag = false;
|
||||
|
||||
renderer.domElement.addEventListener('touchstart', (event) => {
|
||||
event.preventDefault();
|
||||
if (event.touches.length === 1) {
|
||||
const touch = event.touches[0];
|
||||
touchStartPos = { x: touch.clientX, y: touch.clientY };
|
||||
isTouchDrag = false;
|
||||
|
||||
// 模拟鼠标事件用于射线检测
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
mouse.x = ((touch.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((touch.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(nodeMeshes);
|
||||
if (intersects.length > 0) {
|
||||
const node = intersects[0].object;
|
||||
if (selectedNode === node) {
|
||||
selectedNode = null;
|
||||
document.getElementById('node-info').style.display = 'none';
|
||||
resetHighlight();
|
||||
} else {
|
||||
selectedNode = node;
|
||||
showNodeInfo(node.userData.nodeData, true);
|
||||
highlightNodeConnections(node.userData.nodeData);
|
||||
try {
|
||||
if (window.nativeBridge && window.nativeBridge.onNodeClick) {
|
||||
window.nativeBridge.onNodeClick(node.userData.nodeData.id, node.userData.nodeData.name);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
} else if (event.touches.length === 2) {
|
||||
// 双指缩放
|
||||
const dx = event.touches[0].clientX - event.touches[1].clientX;
|
||||
const dy = event.touches[0].clientY - event.touches[1].clientY;
|
||||
touchStartDistance = Math.sqrt(dx*dx + dy*dy);
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
renderer.domElement.addEventListener('touchmove', (event) => {
|
||||
event.preventDefault();
|
||||
if (event.touches.length === 1 && controls) {
|
||||
const touch = event.touches[0];
|
||||
const dx = touch.clientX - touchStartPos.x;
|
||||
const dy = touch.clientY - touchStartPos.y;
|
||||
if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
|
||||
isTouchDrag = true;
|
||||
}
|
||||
// 模拟OrbitControls的鼠标移动
|
||||
if (isTouchDrag) {
|
||||
const rotateSpeed = 0.005;
|
||||
controls.rotateLeft(-dx * rotateSpeed);
|
||||
controls.rotateUp(-dy * rotateSpeed);
|
||||
controls.update();
|
||||
touchStartPos = { x: touch.clientX, y: touch.clientY };
|
||||
}
|
||||
} else if (event.touches.length === 2 && controls) {
|
||||
// 双指缩放
|
||||
const dx = event.touches[0].clientX - event.touches[1].clientX;
|
||||
const dy = event.touches[0].clientY - event.touches[1].clientY;
|
||||
const distance = Math.sqrt(dx*dx + dy*dy);
|
||||
const scale = touchStartDistance / distance;
|
||||
camera.position.multiplyScalar(scale);
|
||||
controls.update();
|
||||
touchStartDistance = distance;
|
||||
}
|
||||
}, { passive: false });
|
||||
|
||||
renderer.domElement.addEventListener('touchend', (event) => {
|
||||
if (event.touches.length === 0) {
|
||||
isTouchDrag = false;
|
||||
}
|
||||
}, { passive: false });
|
||||
}
|
||||
|
||||
// 搜索和类型过滤
|
||||
function applyFilters() {
|
||||
nodeMeshes.forEach(mesh => {
|
||||
const nodeData = mesh.userData.nodeData;
|
||||
const nameMatch = nodeData.name.toLowerCase().includes(searchTerm);
|
||||
const typeMatch = activeTypeFilter === '全部' || nodeData.type === activeTypeFilter;
|
||||
|
||||
if (nameMatch && typeMatch) {
|
||||
mesh.material.transparent = false;
|
||||
mesh.material.opacity = 1;
|
||||
mesh.scale.setScalar(1);
|
||||
} else {
|
||||
mesh.material.transparent = true;
|
||||
mesh.material.opacity = 0.2;
|
||||
mesh.scale.setScalar(0.8);
|
||||
}
|
||||
});
|
||||
// 同时过滤边
|
||||
edgeLines.forEach(line => {
|
||||
const edgeData = line.userData.edgeData;
|
||||
const sourceNode = nodes.find(n => n.id === edgeData.source);
|
||||
const targetNode = nodes.find(n => n.id === edgeData.target);
|
||||
const sourceMatch = sourceNode && sourceNode.name.toLowerCase().includes(searchTerm) && (activeTypeFilter === '全部' || sourceNode.type === activeTypeFilter);
|
||||
const targetMatch = targetNode && targetNode.name.toLowerCase().includes(searchTerm) && (activeTypeFilter === '全部' || targetNode.type === activeTypeFilter);
|
||||
|
||||
if ((sourceMatch || targetMatch) && searchTerm === '' && activeTypeFilter === '全部') {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.4;
|
||||
} else if (sourceMatch || targetMatch) {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.6;
|
||||
} else {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 连接高亮
|
||||
function highlightNodeConnections(nodeData) {
|
||||
const connectedNodeIds = new Set();
|
||||
const connectedEdgeIds = new Set();
|
||||
|
||||
// 找出所有连接的节点和边
|
||||
edges.forEach(edge => {
|
||||
if (edge.source === nodeData.id || edge.target === nodeData.id) {
|
||||
connectedNodeIds.add(edge.source);
|
||||
connectedNodeIds.add(edge.target);
|
||||
connectedEdgeIds.add(edge.id);
|
||||
}
|
||||
});
|
||||
|
||||
nodeMeshes.forEach(mesh => {
|
||||
const meshNodeId = mesh.userData.nodeData.id;
|
||||
if (meshNodeId === nodeData.id) {
|
||||
// 选中的节点
|
||||
mesh.material.emissiveIntensity = 1.0;
|
||||
mesh.scale.setScalar(1.5);
|
||||
} else if (connectedNodeIds.has(meshNodeId)) {
|
||||
// 直接连接的节点
|
||||
mesh.material.emissiveIntensity = 0.8;
|
||||
mesh.scale.setScalar(1.3);
|
||||
mesh.material.transparent = false;
|
||||
mesh.material.opacity = 1;
|
||||
} else {
|
||||
// 无关系的节点
|
||||
mesh.material.transparent = true;
|
||||
mesh.material.opacity = 0.15;
|
||||
mesh.material.emissiveIntensity = 0.2;
|
||||
mesh.scale.setScalar(0.9);
|
||||
}
|
||||
});
|
||||
|
||||
edgeLines.forEach(line => {
|
||||
if (connectedEdgeIds.has(line.userData.edgeData.id)) {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.8;
|
||||
line.material.linewidth = 2;
|
||||
} else {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.1;
|
||||
line.material.linewidth = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetHighlight() {
|
||||
nodeMeshes.forEach(mesh => {
|
||||
const nodeData = mesh.userData.nodeData;
|
||||
const nameMatch = nodeData.name.toLowerCase().includes(searchTerm);
|
||||
const typeMatch = activeTypeFilter === '全部' || nodeData.type === activeTypeFilter;
|
||||
|
||||
mesh.material.emissiveIntensity = 0.5 + Math.min(nodeData.mention_count * 0.05, 0.3);
|
||||
if (nameMatch && typeMatch) {
|
||||
mesh.material.transparent = false;
|
||||
mesh.material.opacity = 1;
|
||||
mesh.scale.setScalar(1);
|
||||
} else {
|
||||
mesh.material.transparent = true;
|
||||
mesh.material.opacity = 0.2;
|
||||
mesh.scale.setScalar(0.8);
|
||||
}
|
||||
});
|
||||
edgeLines.forEach(line => {
|
||||
line.material.transparent = true;
|
||||
line.material.opacity = 0.4;
|
||||
line.material.linewidth = 1;
|
||||
});
|
||||
}
|
||||
|
||||
// 边标签显示
|
||||
function onEdgeHoverCheck(event) {
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
|
||||
// 检查边悬停
|
||||
const edgeIntersects = raycaster.intersectObjects(edgeLines);
|
||||
if (edgeIntersects.length > 0) {
|
||||
const edge = edgeIntersects[0].object;
|
||||
const edgeData = edge.userData.edgeData;
|
||||
edgeLabelEl.textContent = edgeData.relation_type || '关系';
|
||||
edgeLabelEl.style.display = 'block';
|
||||
edgeLabelEl.style.left = (event.clientX - rect.left + 10) + 'px';
|
||||
edgeLabelEl.style.top = (event.clientY - rect.top - 10) + 'px';
|
||||
} else {
|
||||
edgeLabelEl.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function onWindowResize() {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
|
||||
221
full_output.log
Normal file
221
full_output.log
Normal file
@ -0,0 +1,221 @@
|
||||
Reading package lists...
|
||||
Building dependency tree...
|
||||
Reading state information...
|
||||
python3 is already the newest version (3.13.9-3).
|
||||
python3 set to manually installed.
|
||||
python3-pip is already the newest version (26.0.1+dfsg-1).
|
||||
You might want to run 'apt --fix-broken install' to correct these.
|
||||
The following packages have unmet dependencies:
|
||||
libxfont2 : Depends: libfontenc1 (>= 1:1.1.8) but 1:1.1.4-1 is to be installed
|
||||
python3-venv : Depends: python3.13-venv (>= 3.13.5-1~) but it is not going to be installed
|
||||
Depends: python3 (= 3.13.5-1) but 3.13.9-3 is to be installed
|
||||
xserver-common : Depends: x11-xkb-utils but it is not going to be installed
|
||||
Recommends: xfonts-base but it is not going to be installed
|
||||
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).
|
||||
|
||||
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
|
||||
|
||||
Reading package lists...
|
||||
Building dependency tree...
|
||||
Reading state information...
|
||||
Correcting dependencies... Done
|
||||
Solving dependencies...
|
||||
Upgrading:
|
||||
libfontenc1 libxt-dev
|
||||
|
||||
Installing dependencies:
|
||||
libxt6t64 x11-xkb-utils
|
||||
|
||||
REMOVING:
|
||||
libxt6
|
||||
|
||||
apt-listchanges: Reading changelogs...
|
||||
dpkg-preconfigure: unable to re-open stdin: No such file or directory
|
||||
Summary:
|
||||
Upgrading: 2, Installing: 2, Removing: 1, Not Upgrading: 708
|
||||
Download size: 0 B / 778 kB
|
||||
Space needed: 526 kB / 419 GB available
|
||||
|
||||
(Reading database…
|
||||
(Reading database… 5%
|
||||
(Reading database… 10%
|
||||
(Reading database… 15%
|
||||
(Reading database… 20%
|
||||
(Reading database… 25%
|
||||
(Reading database… 30%
|
||||
(Reading database… 35%
|
||||
(Reading database… 40%
|
||||
(Reading database… 45%
|
||||
(Reading database… 50%
|
||||
(Reading database… 55%
|
||||
(Reading database… 60%
|
||||
(Reading database… 65%
|
||||
(Reading database… 70%
|
||||
(Reading database… 75%
|
||||
(Reading database… 80%
|
||||
(Reading database… 85%
|
||||
(Reading database… 90%
|
||||
(Reading database… 95%
|
||||
(Reading database… 100%
|
||||
(Reading database… 103500 files and directories currently installed.)
|
||||
Preparing to unpack …/libxt-dev_1%3a1.2.1-1.2+b2_amd64.deb…
|
||||
Unpacking libxt-dev:amd64 (1:1.2.1-1.2+b2) over (1:1.2.1-1.1)…
|
||||
dpkg: libxt6:amd64: dependency problems, but removing anyway as you requested:
|
||||
x11-xserver-utils depends on libxt6.
|
||||
x11-utils depends on libxt6 (>= 1:1.1.0).
|
||||
libxmu6:amd64 depends on libxt6.
|
||||
libxaw7:amd64 depends on libxt6.
|
||||
libgs10:amd64 depends on libxt6.
|
||||
|
||||
(Reading database…
|
||||
(Reading database… 5%
|
||||
(Reading database… 10%
|
||||
(Reading database… 15%
|
||||
(Reading database… 20%
|
||||
(Reading database… 25%
|
||||
(Reading database… 30%
|
||||
(Reading database… 35%
|
||||
(Reading database… 40%
|
||||
(Reading database… 45%
|
||||
(Reading database… 50%
|
||||
(Reading database… 55%
|
||||
(Reading database… 60%
|
||||
(Reading database… 65%
|
||||
(Reading database… 70%
|
||||
(Reading database… 75%
|
||||
(Reading database… 80%
|
||||
(Reading database… 85%
|
||||
(Reading database… 90%
|
||||
(Reading database… 95%
|
||||
(Reading database… 100%
|
||||
(Reading database… 103501 files and directories currently installed.)
|
||||
Removing libxt6:amd64 (1:1.2.1-1.1)…
|
||||
Selecting previously unselected package libxt6t64:amd64.
|
||||
(Reading database…
|
||||
(Reading database… 5%
|
||||
(Reading database… 10%
|
||||
(Reading database… 15%
|
||||
(Reading database… 20%
|
||||
(Reading database… 25%
|
||||
(Reading database… 30%
|
||||
(Reading database… 35%
|
||||
(Reading database… 40%
|
||||
(Reading database… 45%
|
||||
(Reading database… 50%
|
||||
(Reading database… 55%
|
||||
(Reading database… 60%
|
||||
(Reading database… 65%
|
||||
(Reading database… 70%
|
||||
(Reading database… 75%
|
||||
(Reading database… 80%
|
||||
(Reading database… 85%
|
||||
(Reading database… 90%
|
||||
(Reading database… 95%
|
||||
(Reading database… 100%
|
||||
(Reading database… 103495 files and directories currently installed.)
|
||||
Preparing to unpack …/libxt6t64_1%3a1.2.1-1.2+b2_amd64.deb…
|
||||
Unpacking libxt6t64:amd64 (1:1.2.1-1.2+b2)…
|
||||
Preparing to unpack …/libfontenc1_1%3a1.1.8-1+b2_amd64.deb…
|
||||
Unpacking libfontenc1:amd64 (1:1.1.8-1+b2) over (1:1.1.4-1)…
|
||||
Selecting previously unselected package x11-xkb-utils.
|
||||
Preparing to unpack …/x11-xkb-utils_7.7+9_amd64.deb…
|
||||
Unpacking x11-xkb-utils (7.7+9)…
|
||||
Setting up libfontenc1:amd64 (1:1.1.8-1+b2)…
|
||||
Setting up libxt6t64:amd64 (1:1.2.1-1.2+b2)…
|
||||
Setting up x11-xkb-utils (7.7+9)…
|
||||
Setting up libxt-dev:amd64 (1:1.2.1-1.2+b2)…
|
||||
Processing triggers for man-db (2.11.2-2)…
|
||||
Processing triggers for libc-bin (2.42-14)…
|
||||
needrestart is being skipped since dpkg has failed
|
||||
Reading package lists...
|
||||
Building dependency tree...
|
||||
Reading state information...
|
||||
Solving dependencies...
|
||||
Some packages could not be installed. This may mean that you have
|
||||
requested an impossible situation or if you are using the unstable
|
||||
distribution that some required packages have not yet been created
|
||||
or been moved out of Incoming.
|
||||
The following information may help to resolve the situation:
|
||||
|
||||
The following packages have unmet dependencies:
|
||||
python3-venv : Depends: python3.13-venv (>= 3.13.5-1~) but it is not going to be installed
|
||||
Depends: python3 (= 3.13.5-1) but 3.13.9-3 is to be installed
|
||||
E: Unable to satisfy dependencies. Reached two conflicting assignments:
|
||||
1. python3-venv:amd64=3.13.5-1 is selected for install
|
||||
2. python3-venv:amd64=3.13.5-1 Depends python3 (= 3.13.5-1)
|
||||
but none of the choices are installable:
|
||||
- python3:amd64=3.13.5-1 is not selected for install
|
||||
===== Building TrulyMEM for Linux =====
|
||||
Project root: /home/program/TrulyMEM-TrueHumanMEM
|
||||
The virtual environment was not created successfully because ensurepip is not
|
||||
available. On Debian/Ubuntu systems, you need to install the python3-venv
|
||||
package using the following command.
|
||||
|
||||
apt install python3.13-venv
|
||||
|
||||
You may need to use sudo with that command. After installing the python3-venv
|
||||
package, recreate your virtual environment.
|
||||
|
||||
Failing command: /home/program/TrulyMEM-TrueHumanMEM/.venv_build/bin/python3
|
||||
|
||||
Warning: venv creation failed, falling back to system Python
|
||||
Cleaning previous builds...
|
||||
================================
|
||||
Building TrulyMEM (TUI + Web embedded)
|
||||
================================
|
||||
31 INFO: PyInstaller: 6.20.0, contrib hooks: 2026.4
|
||||
31 INFO: Python: 3.13.12
|
||||
33 INFO: Platform: Linux-6.1.0-44-amd64-x86_64-with-glibc2.42
|
||||
33 INFO: Python environment: /usr
|
||||
36 INFO: Removing temporary files and cleaning cache in /root/.cache/pyinstaller
|
||||
37 INFO: Module search paths (PYTHONPATH):
|
||||
['/home/program/TrulyMEM-TrueHumanMEM',
|
||||
'/home/program/TrulyMEM-TrueHumanMEM',
|
||||
'/usr/lib/python313.zip',
|
||||
'/usr/lib/python3.13',
|
||||
'/usr/lib/python3.13/lib-dynload',
|
||||
'/usr/local/lib/python3.13/dist-packages',
|
||||
'/usr/lib/python3/dist-packages',
|
||||
'/home/program/TrulyMEM-TrueHumanMEM']
|
||||
158 INFO: Appending 'datas' from .spec
|
||||
158 INFO: checking Analysis
|
||||
158 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
159 INFO: Looking for Python shared library...
|
||||
166 INFO: Using Python shared library: /usr/lib/x86_64-linux-gnu/libpython3.13.so.1.0
|
||||
166 INFO: Running Analysis Analysis-00.toc
|
||||
166 INFO: Target bytecode optimization level: 0
|
||||
166 INFO: Initializing module dependency graph...
|
||||
166 INFO: Initializing module graph hook caches...
|
||||
170 INFO: Analyzing modules for base_library.zip ...
|
||||
651 INFO: Processing standard module hook 'hook-encodings.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
943 INFO: Processing standard module hook 'hook-heapq.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
1656 INFO: Processing standard module hook 'hook-pickle.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2496 INFO: Caching module dependency graph...
|
||||
2519 INFO: Analyzing /home/program/TrulyMEM-TrueHumanMEM/trulymem_entry.py
|
||||
2554 INFO: Processing standard module hook 'hook-sqlite3.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2678 INFO: Processing standard module hook 'hook-platform.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2702 INFO: Processing standard module hook 'hook-sysconfig.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2706 INFO: Processing standard module hook 'hook-_ctypes.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
2716 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
2717 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
4768 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
4924 INFO: Processing standard module hook 'hook-xml.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
5338 INFO: Processing standard module hook 'hook-pydantic.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5622 INFO: Processing standard module hook 'hook-rich.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5908 INFO: Processing standard module hook 'hook-pygments.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
6310 INFO: Processing standard module hook 'hook-chardet.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
7729 INFO: Processing standard module hook 'hook-zoneinfo.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
8919 INFO: Processing standard module hook 'hook-certifi.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
8990 INFO: Processing standard module hook 'hook-anyio.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
9647 INFO: Processing standard module hook 'hook-difflib.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
10808 INFO: Processing standard module hook 'hook-numpy.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
12163 INFO: Processing standard module hook 'hook-charset_normalizer.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
12999 INFO: Processing standard module hook 'hook-pytz.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
13591 INFO: Processing pre-safe-import-module hook 'hook-platformdirs.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
13598 INFO: Processing standard module hook 'hook-platformdirs.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
15377 INFO: Processing standard module hook 'hook-jinja2.py' from '/usr/local/lib/python3.13/dist-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
15747 INFO: Processing pre-safe-import-module hook 'hook-importlib_metadata.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15747 INFO: Setuptools: 'importlib_metadata' appears to be a setuptools-vendored copy - creating alias to 'setuptools._vendor.importlib_metadata'!
|
||||
15752 INFO: Processing standard module hook 'hook-setuptools.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks'
|
||||
15759 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
15778 INFO: Processing pre-safe-import-module hook 'hook-jaraco.py' from '/usr/local/lib/python3.13/dist-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
Reference in New Issue
Block a user