feat(interface): 改进仪表盘

This commit is contained in:
2026-01-22 06:13:01 +08:00
parent 76c9537ff0
commit 26e053f79f
14 changed files with 249 additions and 248 deletions

View File

@@ -1,12 +1,15 @@
from typing import Type
from time import sleep
print("欢迎使用基本用户界面!")
print("加载配置... ", end="", flush=True)
from heurams.context import *
print("已完成!")
print("加载用户界面框架... ", end="", flush=True)
from textual.app import App
from textual.driver import Driver
from textual.widgets import Button
print("已完成!")
from heurams.context import config_var
from heurams.services.logger import get_logger
print("加载用户界面布局... ", end="", flush=True)
from .screens.about import AboutScreen
from .screens.dashboard import DashboardScreen
from .screens.llmchat import LLMChatScreen
@@ -16,27 +19,9 @@ from .screens.radio import RadioScreen
from .screens.repocreator import RepoCreatorScreen
from .screens.repoeditor import RepoEditorScreen
from .screens.synctool import SyncScreen
logger = get_logger(__name__)
def environment_check():
from pathlib import Path
logger.debug("检查环境路径")
subdir = ["cache/voice", "repo", "global", "config"]
for i in subdir:
i = Path(config_var.get()["paths"]["data"]) / i
if not i.exists():
logger.info("创建目录: %s", i)
print(f"创建 {i}")
i.mkdir(exist_ok=True, parents=True)
else:
logger.debug("目录已存在: %s", i)
print(f"找到 {i}")
logger.debug("环境检查完成")
print("已完成!")
print(f"组件目录: {rootdir}")
print(f"工作目录: {workdir}")
class HeurAMSApp(App):
TITLE = "潜进"
CSS_PATH = "css/main.tcss"
@@ -61,7 +46,6 @@ class HeurAMSApp(App):
}
def on_mount(self) -> None:
environment_check()
self.push_screen("dashboard")
def on_button_pressed(self, event: Button.Pressed) -> None:

View File

@@ -1,20 +1,29 @@
from textual.app import App
from textual.widgets import Button
from heurams.interface import *
from heurams.context import config_var
from heurams.interface import HeurAMSApp
from heurams.services.logger import get_logger
from .screens.about import AboutScreen
from .screens.dashboard import DashboardScreen
from .screens.precache import PrecachingScreen
from .screens.repocreator import RepoCreatorScreen
logger = get_logger(__name__)
def environment_check():
from pathlib import Path
logger.debug("检查环境路径")
subdir = ["cache/voice", "repo", "global", "config"]
for i in subdir:
i = Path(config_var.get()["paths"]["data"]) / i
if not i.exists():
logger.info("创建目录: %s", i)
print(f"创建 {i}")
i.mkdir(exist_ok=True, parents=True)
else:
logger.debug("目录已存在: %s", i)
print(f"找到 {i}")
logger.debug("环境检查完成")
def main():
environment_check()
app = HeurAMSApp()
app.run()
app.run(inline=False)
if __name__ == "__main__":
main()

View File

@@ -1,7 +1,20 @@
NavigatorScreen {
align: center middle;
}
.repo_listitem {
layout: grid;
grid-size: 2;
}
.repo_listitem_btn {
dock: right;
offset: -5% 0
}
#dialog {
grid-size: 2;
grid-gutter: 1 1;
@@ -40,6 +53,10 @@ LLMChatScreen {
background: $surface;
}
#dashboardtop {
height: 4
}
#input-container {
height: 3;
margin-top: 1;

View File

@@ -1,12 +1,14 @@
"""仪表盘界面"""
from functools import reduce
import pathlib
from pathlib import Path
from textual.app import ComposeResult
from textual.containers import ScrollableContainer
from textual.containers import ScrollableContainer, Container, Horizontal, Vertical
from textual.screen import Screen
from textual.widgets import Button, Footer, Header, Label, ListItem, ListView, Static
from textual.layouts import horizontal
import heurams.kernel.particles as pt
import heurams.services.timer as timer
@@ -42,21 +44,35 @@ class DashboardScreen(Screen):
self.repostat = {}
self.title2dirname = {}
self.title2repo = {}
self.dirname2repo = {}
self._load_data()
def compose(self) -> ComposeResult:
"""组合界面组件"""
yield Header(show_clock=True)
yield ScrollableContainer(
Label('欢迎使用 "潜进" 启发式辅助记忆调度器', classes="title-label"),
Label(
f"当前 UNIX 日时间戳: {timer.get_daystamp()} (UTC+{config_var.get()['timezone_offset'] / 3600})"
),
Label(f"全局算法设置: {config_var.get()['algorithm']['default']}"),
Label("选择待学习或待修改的项目:", classes="title-label"),
ListView(id="repo-list", classes="repo-list-view"),
Label(f'"潜进" 启发式辅助记忆调度器 版本 {version.ver} '),
)
with ScrollableContainer():
yield Horizontal(
Vertical(
Label('欢迎使用 "潜进" 启发式辅助记忆调度器'),
Label(
f"当前 UNIX 日时间戳: {timer.get_daystamp()} (UTC+{config_var.get()['timezone_offset'] / 3600})"
),
Label(f"全局算法设置: {config_var.get()['algorithm']['default']}"),
Label("选择待学习或待修改的项目:"),
classes="column",
),
Vertical(
Label(f"已加载 {len(self.repostat)} 个单元集", classes='dataview'),
Label(f"共计 {reduce(lambda x, y: x + y, map(lambda x: x.get('unit_sum'), self.repostat.values()))} 个单元", classes='dataview'),
Label(f"已激活 {reduce(lambda x, y: x + y, map(lambda x: x.get('activated_sum'), self.repostat.values()))} 个单元", classes='dataview'),
Label(""),
classes="column",
),
id="dashboardtop"
)
yield ListView(id="repo-list", classes="repo-list-view")
yield Label(f'"潜进" 启发式辅助记忆调度器 版本 {version.ver} ')
yield Footer()
def _load_data(self):
@@ -105,6 +121,7 @@ class DashboardScreen(Screen):
self.repostat[dirname] = stat
self.title2dirname[title] = dirname
self.title2repo[title] = repo
self.dirname2repo[dirname] = repo
def on_mount(self) -> None:
"""挂载组件时初始化"""
@@ -132,7 +149,7 @@ class DashboardScreen(Screen):
for repotitle in repotitles:
prompt = self.repostat[self.title2dirname[repotitle]]["prompt"]
list_item = ListItem(Label(prompt))
list_item = ListItem(Label(prompt), Button(f"开始学习", flat=True, variant="primary", classes="repo_listitem_btn", id=f"launch_{self.repostat[self.title2dirname[repotitle]]['dirname']}"), classes="repo_listitem")
repo_list_widget.append(list_item)
# if not self.stay_enabled[repodir]:
@@ -169,6 +186,9 @@ class DashboardScreen(Screen):
self.app.push_screen(NavigatorScreen())
def on_button_pressed(self, event: Button.Pressed) -> None:
logger.debug(f"event.button.id: {event.button.id}")
"""处理按钮点击事件"""
if event.button.id == "navigator-button":
self.action_open_navigator()
if str(event.button.id).startswith("launch_"): # type: ignore
from .preparation import launch
launch(repo=self.dirname2repo[event.button.id[7:]], app=self.app, scheduled_num=-1) # type: ignore
# TODO: 这样启动的记忆实例的状态机无法绑定到 PreparationScreen 中

View File

@@ -123,36 +123,41 @@ class PreparationScreen(Screen):
event.stop()
logger.debug("按下按钮")
if event.button.id == "start_memorizing_button":
atoms = list()
for i in self.repo.ident_index:
n = pt.Nucleon.create_on_nucleonic_data(
nucleonic_data=self.repo.nucleonic_data_lict.get_itemic_unit(i)
)
e = pt.Electron.create_on_electonic_data(
electronic_data=self.repo.electronic_data_lict.get_itemic_unit(i)
)
a = pt.Atom(n, e, self.repo.orbitic_data)
atoms.append(a)
atoms_to_provide = list()
left_new = self.scheduled_num
for i in atoms:
i: pt.Atom
if i.registry["electron"].is_activated():
if i.registry["electron"].is_due():
atoms_to_provide.append(i)
else:
left_new -= 1
if left_new >= 0:
atoms_to_provide.append(i)
import heurams.kernel.reactor as rt
from .memoqueue import MemScreen
pheser = rt.Phaser(atoms_to_provide)
save_func = self.repo.persist_to_repodir
memscreen = MemScreen(pheser, save_func, repo=self.repo)
self.app.push_screen(memscreen)
launch(repo=self.repo, app=self.app, scheduled_num=self.scheduled_num)
elif event.button.id == "precache_button":
self.action_precache()
def launch(repo, app, scheduled_num):
if scheduled_num == -1:
scheduled_num = config_var.get()["scheduled_num"]
atoms = list()
for i in repo.ident_index:
n = pt.Nucleon.create_on_nucleonic_data(
nucleonic_data=repo.nucleonic_data_lict.get_itemic_unit(i)
)
e = pt.Electron.create_on_electonic_data(
electronic_data=repo.electronic_data_lict.get_itemic_unit(i)
)
a = pt.Atom(n, e, repo.orbitic_data)
atoms.append(a)
atoms_to_provide = list()
left_new = scheduled_num
for i in atoms:
i: pt.Atom
if i.registry["electron"].is_activated():
if i.registry["electron"].is_due():
atoms_to_provide.append(i)
else:
left_new -= 1
if left_new >= 0:
atoms_to_provide.append(i)
import heurams.kernel.reactor as rt
from .memoqueue import MemScreen
pheser = rt.Phaser(atoms_to_provide)
save_func = repo.persist_to_repodir
memscreen = MemScreen(pheser, save_func, repo=repo)
app.push_screen(memscreen)

View File

@@ -5,7 +5,7 @@ from typing import TypedDict
from textual.containers import Container
from textual.message import Message
from textual.widget import Widget
from textual.widgets import Button, Label
from textual.widgets import Button, Label, Markdown
import heurams.kernel.particles as pt
import heurams.kernel.puzzles as pz
@@ -66,7 +66,7 @@ class ClozePuzzle(BasePuzzleWidget):
def compose(self):
yield Label(self.puzzle.wording, id="sentence")
yield Label(f"当前输入: {self.inputlist}", id="inputpreview")
yield Markdown(f"> {self.listprint(self.inputlist)}", id="inputpreview")
# 渲染当前问题的选项
with Container(id="btn-container"):
for i in self.ans:
@@ -77,9 +77,18 @@ class ClozePuzzle(BasePuzzleWidget):
yield Button("退格", id="delete")
def listprint(self, lst):
s = ""
if lst:
lastone = lst[-1]
for i in lst[:-1]:
s += (i + ' ')
s += f" `{lastone}`"
return s
def update_display(self):
preview = self.query_one("#inputpreview")
preview.update(f"当前输入: {self.inputlist}") # type: ignore
preview.update(f"> {self.listprint(self.inputlist)}") # type: ignore
def on_button_pressed(self, event: Button.Pressed) -> None:
button_id = event.button.id

View File

@@ -67,9 +67,7 @@ class Recognition(BasePuzzleWidget):
f";{delim}": ";",
f":{delim}": ":",
}
nucleon = self.atom.registry["nucleon"]
metadata = self.atom.registry["nucleon"]
primary = cfg["primary"]
with Center():