修改readme

日志函数
增加依赖安装
截屏
增加入口函数
This commit is contained in:
Fromsko 2024-01-03 17:47:42 +08:00
parent fa542e57f1
commit 65007987f2
5 changed files with 291 additions and 3 deletions

View File

@ -8,8 +8,8 @@ pyweb是一个基于Pywebview构建的开箱即用的模板旨在帮助快速
- [x] 界面展示
- [x] 数据处理
- [x] 用户认证
- [x] 数据库集成
- [ ] 用户认证
- [ ] 数据库集成
- [ ] 数据可视化
- [ ] 文件上传和下载
@ -27,7 +27,7 @@ python run main.py
## 📷 截屏
<!-- ![截屏](screenshot.png) -->
![截屏](./res/screenshot.png)
## 🤝 贡献

48
libs/log/__init__.py Normal file
View File

@ -0,0 +1,48 @@
"""
提供 logger 对象
> 其他任何 "libs" 模块都应使用此模块的 "logger" 来打印日志
Tip:
移除 `logging` 改用 `loguru.logger`
"""
import wrapt
from loguru import logger
class Logger:
def __init__(self, name):
self.__log = logger.bind(name=name)
self.__log.add(
sink=f"{name}.log",
format="{time} | {level} | {message}",
rotation="1 week",
)
def __call__(self, func):
@wrapt.decorator
def wrapper(wrapped, instance, args, kwargs):
resp = wrapped(*args, **kwargs)
self.info(f"{wrapped.__name__}|=> {resp}")
return resp
return wrapper(func)
@property
def info(self):
return self.__log.info
@property
def warn(self):
return self.__log.warn
@property
def error(self):
return self.__log.error
@property
def debug(self):
return self.__log.debug
__all__ = [
'Logger',
]

7
requirements.txt Normal file
View File

@ -0,0 +1,7 @@
pywebview
fastapi[all]
httpx
requests
pymysql
aiomysql
aiofiles

BIN
res/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

233
webui.py Normal file
View File

@ -0,0 +1,233 @@
"""
@Author: skong
@File : webui.py
@notes : Web UI with backend
"""
from typing import Optional, Any, List
from pydantic import BaseModel
import webview
import webview.menu as wm
from webview import Window
from libs.log import Logger
class Config:
"""
配置基类
"""
_version = 3.6
_base_name: str = "知识图谱"
_base_url: str = "http://localhost:8090"
_web: webview = webview
_menu_items: List = []
_default_view: Optional[Window] = None
log: Logger = Logger("webui")
__html = """
<head>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #f2f2f2;
font-family: Arial, sans-serif;
}
.container {
text-align: center;
width: auto;
height: auto;
}
h1 {
font-size: 24px;
margin-bottom: 20px;
}
button {
padding: 10px 20px;
font-size: 18px;
background-color: #4CAF50;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<h1>服务已经运行!!!</h1>
<button onclick="pywebview.api.close_window()">关闭程序</button>
</div>
</body>
"""
Router: dict[dict] = {
"frontend": {
"title": f"{_base_name}-前端",
"url": _base_url,
},
"backend":{
"title": f"{_base_name}-后端",
"url": f"{_base_url}/docs"
},
"index":{
"title": f"{_base_name}-{_version}",
"url": "",
"html": __html,
},
}
def get_config(self, key: str, view: Optional[Window]) -> Any:
"""获取配置信息
参数:
- `key`: 需要获取的键
- `view`: 视图(不存在则获取本地配置)
示例:
```python
# 默认视图
self.get_config('window.screen.width', default_view)
# 配置信息
self.get_config('version')
```
"""
if view is not None:
return view.evaluate_js(key)
else:
...
def auto_resize(
self,
width: Optional[int]= None,
height: Optional[int]=None,
view: Optional[Window] =None,
):
"""自适应窗口大小
参数:
- `view`: 视图
- `width`: 宽度
- `height`: 高度
示例:
```python
self.auto_resize(view)
```
"""
if view is None:
view = self._default_view
if isinstance(view, Window):
if width is None and height is None:
screens = self._web.screens[0]
width = int(screens.width*0.85)
height = int(screens.height*0.85)
view.resize(width, height)
else:
self.log.error("Window is not found")
def close_window(self, window:Window):
"""
关闭窗口
"""
self._default_view.destroy()
class MenuModel(BaseModel):
"""
菜单数据模型
"""
title: Optional[str]
url: Optional[str]
html: Optional[str]
class Handler(Config):
def add_menu(self, key: str, view: list[object]):
"""
增加菜单
"""
try:
self._menu_items.insert(0, wm.Menu(key, view))
except Exception as err:
self.log.error(err)
def frontend(self):
"""
前端
"""
return self.render(MenuModel(**self.Router['frontend']))
def backend(self):
"""
后端
"""
return self.render(MenuModel(**self.Router['backend']))
def index(self):
"""
主页
"""
return self.render(MenuModel(**self.Router['index']))
def render(self, info: MenuModel):
"""渲染页面
参数:
- `info`: 数据模型或者空类型
示例:
```python
def index(self):
return self.render(info=self.Router['index'])
```
"""
self.auto_resize()
self._default_view.title = info.title
if info.html is not None:
self._default_view.load_html(info.html)
else:
self._default_view.load_url(info.url)
def start_webview(self):
"""
启动 `WebView` 程序
"""
self._default_view = self._web.create_window(
self.Router['index']['title'],
html=self.Router['index']['html'],
# confirm_close=True,
)
self._default_view.expose(self.close_window)
self._web.start(menu=self._menu_items)
if __name__ == '__main__':
app = Handler()
app.add_menu(
'服务选择',
[
wm.MenuAction('前端', app.frontend),
wm.MenuSeparator(),
wm.MenuAction("后端", app.backend),
],
)
app.add_menu(
'主页',
[
wm.MenuAction('运行状况', app.index),
wm.MenuSeparator(),
wm.MenuAction('自适应窗口', app.auto_resize),
],
)
app.start_webview()