first commit

This commit is contained in:
yumoqing 2025-07-16 15:06:49 +08:00
commit c22035c5c4
105 changed files with 1179 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# msp
managed service platform

49
app/ext.py Normal file
View File

@ -0,0 +1,49 @@
from ahserver.serverenv import ServerEnv
def UiWindow(title, icon, content, cheight=10, cwidth=15):
return {
"widgettype":"PopupWindow",
"options":{
"author":"cc",
"cwidth":cwidth,
"cheight":cheight,
"title":title,
"content":content,
"icon":icon or entire_url('/bricks/imgs/app.png'),
"movable":True,
"auto_open":True
}
}
def UiError(title="出错", message="出错啦", timeout=5):
return {
"widgettype":"Error",
"options":{
"author":"tr",
"timeout":timeout,
"cwidth":15,
"cheight":10,
"title":title,
"message":message
}
}
def UiMessage(title="消息", message="后台消息", timeout=5):
return {
"widgettype":"Message",
"options":{
"author":"tr",
"timeout":timeout,
"cwidth":15,
"cheight":10,
"title":title,
"message":message
}
}
def load_bricksExt():
g = ServerEnv()
g.UiError = UiError
g.UiMessage = UiMessage
g.UiWindow = UiWindow

29
app/mspapp.py Normal file
View File

@ -0,0 +1,29 @@
import json
import os
from appPublic.worker import awaitify
from appPublic.registerfunction import RegisterFunction
from appPublic.jsonConfig import getConfig
from ahserver.serverenv import ServerEnv
from ahserver.webapp import webapp
from rbac.init import load_rbac
from msp.init import load_msp
from ext import load_bricksExt
from time import time
def get_module_dbname(mname):
return "msp"
def init_func():
g = ServerEnv()
g.get_module_dbname = get_module_dbname
rf = RegisterFunction()
rf.register('get_module_dbname', get_module_dbname)
load_msp()
load_rbac()
load_bricksExt()
if __name__ == '__main__':
webapp(init_func)

71
conf/config.json Normal file
View File

@ -0,0 +1,71 @@
{
"logger":{
"name":"msp",
"levelname":"info",
"logfile":"$[workdir]$/logs/msp.log"
},
"databases":{
"msp":{
"driver":"aiomysql",
"async_mode":true,
"coding":"utf8",
"maxconn":100,
"dbname":"msp",
"kwargs":{
"user":"test",
"db":"msp",
"password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=",
"host":"localhost"
}
}
},
"filesroot":"$[workdir]$/files",
"website":{
"paths":[
["$[workdir]$/wwwroot",""]
],
"client_max_size":10000,
"host":"0.0.0.0",
"port":10100,
"coding":"utf-8",
"indexes":[
"index.html",
"index.tmpl",
"index.ui",
"index.dspy",
"index.md"
],
"startswiths":[
{
"leading":"/idfile",
"registerfunction":"idFileDownload"
}
],
"processors":[
[".ws","ws"],
[".xterm","xterm"],
[".proxy","proxy"],
[".llm", "llm"],
[".llms", "llms"],
[".llma", "llma"],
[".xlsxds","xlsxds"],
[".sqlds","sqlds"],
[".tmpl.js","tmpl"],
[".tmpl.css","tmpl"],
[".html.tmpl","tmpl"],
[".bcrud", "bricks_crud"],
[".tmpl","tmpl"],
[".app","app"],
[".bui","bui"],
[".ui","bui"],
[".dspy","dspy"],
[".md","md"]
],
"session_max_time":3000,
"session_issue_time":2500,
"session_redis":{
"url":"redis://127.0.0.1:6379"
}
}
}

3
json/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/usr/bin/bash
xls2ui -m ../models -o ../wwwroot msp *.json

22
json/devgroup.json Normal file
View File

@ -0,0 +1,22 @@
{
"tblname": "devgroup",
"title":"设备组",
"params": {
"sortby":"name",
"logined_userid":"ownerid",
"browserfields": {
"exclouded": ["id", "ownerid"],
"alters": {}
},
"editexclouded": [
"id", "ownerid"
],
"subtables":[
{
"field":"devgroupid",
"title":"主机",
"subtable":"hostdev"
}
]
}
}

38
json/hostdev.json Normal file
View File

@ -0,0 +1,38 @@
{
"tblname": "hostdev",
"title":"主机",
"params": {
"sortby":"name",
"confidential_fields":["passwd"],
"logined_userid":"ownerid",
"confidential_fields":["passwd", "client_key", "passphrase"],
"toolbar":{
"tools":[
{
"name":"sshcon",
"label":"ssh连接",
"selected_row":true,
"tip":"ssh链接到主机"
}
]
},
"binds":[
{
"wid":"self",
"event":"sshcon",
"actiontype":"urlwidget",
"target":"self",
"options":{
"url":"{{entire_url('../connecthost.ui')}}"
}
}
],
"browserfields": {
"exclouded": ["id", "ownerid", "passwd", "client_key", "passphrase", "devgroupid"],
"alters": {}
},
"editexclouded": [
"id", "ownerid", "devgroupid"
]
}
}

17
json/jumperhost.json Normal file
View File

@ -0,0 +1,17 @@
{
"models_dir": "${HOME}$/py/msp/models",
"output_dir": "${HOME}$/py/sage/wwwroot/_a/jumperhost",
"dbname": "sage",
"tblname": "jumperhost",
"title":"跳板主机",
"params": {
"sortby":"stepno",
"browserfields": {
"exclouded": ["id", "jumperid"],
"cwidth": {}
},
"editexclouded": [
"id", "jumperid"
]
}
}

BIN
models/atomservice.xlsx Normal file

Binary file not shown.

BIN
models/devgroup.xlsx Normal file

Binary file not shown.

BIN
models/hostdev.xlsx Normal file

Binary file not shown.

BIN
models/mixservice.xlsx Normal file

Binary file not shown.

BIN
models/mixserviceitem.xlsx Normal file

Binary file not shown.

206
models/mysql.ddl.sql Normal file
View File

@ -0,0 +1,206 @@
-- ./atomservice.xlsx
drop table if exists atomservice;
CREATE TABLE atomservice
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(99) comment '服务名称',
`description` VARCHAR(500) comment '描述',
`ownerid` VARCHAR(32) comment '属主id',
`paramsdesc` longtext comment '参数描述',
`script` longtext comment '脚本'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '原子服务'
;
-- ./hostdev.xlsx
drop table if exists hostdev;
CREATE TABLE hostdev
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(99) comment '主机名称',
`description` VARCHAR(500) comment '描述',
`ownerid` VARCHAR(32) comment '属主id',
`host` VARCHAR(400) comment '域名或ip',
`port` int comment '端口',
`user` VARCHAR(400) comment '用户',
`ssh_method` VARCHAR(1) comment 'ssh方法',
`passwd` VARCHAR(400) comment '用户密码',
`client_key` longtext comment '私钥',
`passphrase` VARCHAR(100) comment '私钥密码',
`devgroupid` VARCHAR(32) comment '设备组id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '主机设备'
;
-- ./service_log.xlsx
drop table if exists service_log;
CREATE TABLE service_log
(
`id` VARCHAR(32) comment 'id',
`servname` VARCHAR(100) comment '服务名称',
`date` date comment '主机名称',
`timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP comment '描述',
`hostid` VARCHAR(32) comment '主机id',
`serviceid` VARCHAR(32) comment '服务id',
`params` longtext comment '参数',
`user_orgid` VARCHAR(32) comment '用户机构id',
`userid` VARCHAR(32) comment '用户id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '服务日志'
;
-- ./techservice.xlsx
drop table if exists techservice;
CREATE TABLE techservice
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(100) comment '服务名称',
`description` longtext comment '描述',
`script` longtext comment '服务脚本',
`params_ui` longtext comment '参数',
`ownerid` VARCHAR(32) comment '属主机构',
`enable_date` date comment '启用日期',
`disable_date` date comment '禁用日期'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '技术服务'
;
-- ./mixservice.xlsx
drop table if exists mixservice;
CREATE TABLE mixservice
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(99) comment '服务名称',
`description` VARCHAR(500) comment '描述',
`ownerid` VARCHAR(32) comment '属主id',
`paramsdesc` longtext comment '参数描述',
`script` longtext comment '脚本'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '混合服务'
;
-- ./devgroup.xlsx
drop table if exists devgroup;
CREATE TABLE devgroup
(
`id` VARCHAR(32) comment 'id',
`name` VARCHAR(99) comment '组名称',
`description` VARCHAR(500) comment '描述',
`ownerid` VARCHAR(32) comment '属主id',
`enterhostid` VARCHAR(32) comment '跳板机id'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '设备组'
;
CREATE INDEX devgroup_idx1 ON devgroup(ownerid);
-- ./mixserviceitem.xlsx
drop table if exists atomservice;
CREATE TABLE atomservice
(
`id` VARCHAR(32) comment 'id',
`mixid` VARCHAR(32) comment '混合服务id',
`serviceid` VARCHAR(32) comment '服务id',
`hostvar` VARCHAR(99) comment '主机变量名'
,primary key(id)
)
engine=innodb
default charset=utf8
comment '原子服务'
;

BIN
models/service_log.xlsx Normal file

Binary file not shown.

BIN
models/techservice.xlsx Normal file

Binary file not shown.

9
msp/certbot.sh Normal file
View File

@ -0,0 +1,9 @@
sudo apt update
sudo apt install python3 python3-venv libaugeas0
sudo apt-get remove certbot
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot certbot-nginx
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
sudo certbot --nginx
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null

3
msp/coturn/data.json Normal file
View File

@ -0,0 +1,3 @@
{
"port":13478
}

7
msp/coturn/install.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
sudo apt install -y coturn
sed 's/#listening-port=.*/listening-port=i13478/' -i /etc/turnserver.conf
sudo systemctl enable coturn
sudo systemctl restart coturn

8
msp/getdbname.py Normal file
View File

@ -0,0 +1,8 @@
from ahserver.serverenv import get_serverenv
def get_dbname():
f = get_serverenv('get_module_dbname')
if f:
return f('msp')
return None

88
msp/hostdev.py Normal file
View File

@ -0,0 +1,88 @@
import os
import codecs
from appPublic.log import debug, error, exception
from appPublic.folderUtils import temp_file
from appPublic.sshx import SSHNode
from sqlor.dbpools import DBPools
from .getdbname import get_dbname
async def write_client_key(prikey):
client_key = temp_file()
with codecs.open(client_key, 'w', 'utf-8') as f:
f.write(host.client_key)
return client_key
async def _gethostdev(sor, hostid):
sql1 = """select a.*, b.enterhostid from hostdev a, devgroup b
where a.id=${id}$
and a.devgroupid = b.id"""
sql = """
select x.*,
y.host as jhost,
y.port as jport,
y.user as juser,
y.ssh_method as jssh_method,
y.passwd as jpassword,
y.client_key as jclient_key,
y.passphrase as jpassphrase
from (""" + sql1 + """) a left join hostdev b
on a.enterhostid = b.id
"""
recs = await sor.sqlExe(sql, {'id':hostid})
if len(recs) == 0:
return None
return rec[0]
async def hostdev_node(hostid, sor=None):
host = None
if sor:
host = await _gethostdev(sor, hostid)
else:
db = DBPools()
dbname = get_dbname()
async with db.sqlorContext(dbname) as sor:
host = await _gethostdev(sor, hostid)
jumpers = []
jclient_key = None
client_key = None
node = None
if host.jssh_method == '0':
jumper = {
'host':host.jhost,
'port':host.jport,
'username':host.juser,
'password':host.jpassword
}
jumpers.append(jumper)
else:
jclient_key = write_client_key(host.jclient_key)
jumper = {
'host':host.jhost,
'port':host.jport,
'client_keys': [ client_key ],
'passphrase': jhost.passphrase
}
jumpers.append(jumper)
if host.ssh_method == '0': # password
node = SSHNode(host.host,
username=host.user,
port=host.port or 22,
password=host.passwd,
jumpers=jumpers)
else:
client_key = write_client_key(host.client_key)
node = SSHNode(host.host,
username=host.user,
port=host.port or 22,
client_keys=[client_key],
passphrase=host.passphrase,
jumpers=jumpers)
if jclient_key:
node.jclient_key_file = jclient_key
if client_key:
node.client_key_file = client_key
return node

9
msp/init.py Normal file
View File

@ -0,0 +1,9 @@
from ahserver.serverenv import ServerEnv
from .hostdev import hostdev_node
from .service import service4host, get_service_params_form
def load_msp():
g = ServerEnv()
g.service4host = service4host
g.hostdev_node = hostdev_node
g.get_service_params_form = get_service_params_form

52
msp/service.py Normal file
View File

@ -0,0 +1,52 @@
import os
import codecs
import json
from traceback import format_exc
from appPublic.log import debug, error, exception
from appPublic.myTE import MyTemplateEngine
from appPublic.folderUtils import temp_file
from sqlor.dbpools import DBPools
from ahserver.serverenv import get_serverenv
from .getdbname import get_dbname
from .hostdev import hostdev_node
async def get_service_params_form(serviceid):
dbname = get_dbname()
db = DBPools()
async with db.sqlorContext(dbname) as sor:
servs = await sor.R('techservice', {'id':serviceid})
if len(servs) == 0:
e = Exception(f'techservice has not service with {serviceid=}')
exception(f'{e},{format_exc()}')
serv = servs[0]
fui = json.loads(serv.params_ui)
fui.fields.append({
'name':'serviceid',
'uitype':'hide',
'value':service
})
return fui
async def service4host(serviceid, hostid, parmas):
userinfos = {k:v for k,v in params.items() if k in ['userid', 'userorgid']}
params = {k:v for k,v in params.items() if k not in ['userid', 'userorgid']}
te = MyTemplateEngine(['.'])
dbname = get_dbname()
db = DBPools()
async with db.sqlorContext(dbname) as sor:
servs = await sor.R('techservice', {'id':serviceid})
if len(servs) == 0:
e = Exception(f'techservice has not service with {serviceid=}')
exception(f'{e},{format_exc()}')
serv = servs[0]
script = te.renders(serv.script, params)
tmpf = temp_file(subffix='.sh')
with codecs.open(tmpf, 'w', 'utf-8') as f:
f.write(script)
node = await hostdev_node(hostid)
async with node.get_connector() as conn:
cmd = f'/tmp/{os.path.basename(tmpf)}'
await conn.l2r(tmpf, cmd)
await conn.run(f'chmod +x {cmd}')
x = await conn.run(f'bash {cmd}')
debug(f'{x.output=}')

23
msp/stun/README.md Normal file
View File

@ -0,0 +1,23 @@
# stun server
## 安装
开源stunserver 从[stunserver](https://github.com/jselbie/stunserver.git)下载源代码,并按照说明安装依赖并编译完成
使用本目录的install.sh 完成安装
## 启动
sudo systemctl restart stund
# turnserver
## 安装
apt install coturn
## 修改配置
/etc/turnserver
将listening-port修改为13479
保存并重启coturn服务
## 启动
sudo systemctl restart coturn

19
msp/stun/install.sh Executable file
View File

@ -0,0 +1,19 @@
sudo cp stunserver /usr/local/bin
chmod + /usr/local/bin/stunserver
sudo cat > /etc/systemd/system/stund.service <<!!
[Unit]
Description=Gadget Webserver base on aiothhp
After=network.target mariadb.service
[Service]
ExecStart=/usr/local/bin/stunserver --primaryport 13478
ExecStop=/usr/bin/killall stunserver
KillMode=process
[Install]
WantedBy=multi-user.target
Alias=gadget.service
!!
sudo systemctl daemon-reload
sudo systemctl enable stund.service
sudo systemctl restart stund.service

BIN
msp/stun/stunserver Executable file

Binary file not shown.

1
msp/version.py Normal file
View File

@ -0,0 +1 @@
__version__ = '0.0.1'

0
requirements.txt Normal file
View File

56
script/msp.nginx Normal file
View File

@ -0,0 +1,56 @@
server {
if ($host = kymoz.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 10080;
server_name msp.kymoz.com;
rewrite ^(.*)$ https://${server_name}$1 permanent;
}
server {
listen 10443 ssl;
autoindex on;
client_max_body_size 20m;
server_name msp.kymoz.com;
ssl_certificate /etc/letsencrypt/live/kymoz.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/kymoz.com/privkey.pem; # managed by Certbot
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Url "$scheme://$host:$server_port$request_uri";
index index.html index.htm;
proxy_buffering off;
location ~^/ip$ {
return 200 "$remote_addr";
}
location /wss/ {
proxy_pass http://localhost:10101/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Prepath 'wss';
}
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Origin *;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-real-ip $remote_addr;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_pass http://localhost:10100/;
}
}

13
script/msp.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=maneged service platform service
Documention=msp service to control msp service start or stoop
After=mariadb.service
Wants=systemd-networkd.service
Requires=nginx.service
[Service]
Type=forking
ExecStart=su - ymq -c "cd; py/msp/script/run.sh"
ExecStop=su - ymq "cd; bin/killname msp.py"
[Install]
WantedBy=multi-user.target

6
script/run.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/bash
$HOME/bin/killname app/mspapp.py
$HOME/py3/bin/python $HOME/py/msp/app/mspapp.py -w $HOME/py/msp -p 10100 >> $HOME/py/msp/logs/msp.log 2>&1 &
$HOME/py3/bin/python $HOME/py/msp/app/mspapp.py -w $HOME/py/msp -p 10101 >> $HOME/py/msp/logs/msp.log 2>&1 &

52
setup.py Executable file
View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
from msp.version import __version__
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
required = []
with open('requirements.txt', 'r') as f:
ls = f.read()
required = ls.split('\n')
with open('msp/version.py', 'r') as f:
x = f.read()
y = x[x.index("'")+1:]
z = y[:y.index("'")]
version = z
with open("README.md", "r") as fh:
long_description = fh.read()
name = "msp"
description = "msp"
author = "yumoqing"
email = "yumoqing@gmail.com"
package_data = {}
setup(
name="msp",
version=version,
# uncomment the following lines if you fill them out in release.py
description=description,
author=author,
author_email=email,
platforms='any',
install_requires=required ,
packages=[
"msp"
],
package_data=package_data,
keywords = [
],
url="https://github.com/yumoqing/msp",
long_description=long_description,
long_description_content_type="text/markdown",
classifiers = [
'Operating System :: OS Independent',
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License',
],
)

81
wwwroot/accordion.ui Normal file
View File

@ -0,0 +1,81 @@
{
"widgettype":"Accordion",
"options":{
"width":"300px",
"flexShrink": 0,
"height":"100%",
"keyselectable":true,
"bgcolor":"#888888",
"item_size":"28px",
"items":[
{
"name":"models",
"refresh":true,
"label":"单模型对话",
"content":{
"widgettype":"urlwidget",
"options":{
"refresh":true,
"url":"{{entire_url('models/modeltypemenu.dspy')}}"
}
}
},
{
"name":"models_comp",
"refresh":true,
"label":"多模型对话",
"content":{
"widgettype":"urlwidget",
"options":{
"refresh":true,
"url":"{{entire_url('models/modelcomp.ui')}}"
}
}
},
{
"name":"agents",
"refresh":true,
"label":"智能体",
"content":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('agents/index.ui')}}"
}
}
},
{
"name":"apps",
"refresh":true,
"label":"应用",
"content":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('apps/index.ui')}}"
}
}
},
{
"name":"tunes",
"refresh":true,
"label":"模型调优",
"content":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('tunes/index.ui')}}"
}
}
},
{
"name":"feelog",
"refresh":true,
"label":"费用记录",
"content":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('fee/menu.ui')}}"
}
}
}
]
}
}

38
wwwroot/app_panel.ui Normal file
View File

@ -0,0 +1,38 @@
{
"widgettype":"HBox",
"options":{
"css":"filler"
},
"subwidgets":[
{
"widgettype":"Image",
"options":{
"height":"100%",
"css":"clickable",
"popup":{
"options":{
"auto_dismiss":true
},
"popup_event":"click",
"popup_desc":{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('menu.ui')}}"
}
},
"popupwindow":false
},
"url":"{{entire_url('/imgs/msp.png')}}"
}
},
{
"widgettype":"Title4",
"options":{
"i18n":true,
"otext":"服务平台",
"wrap":true,
"halign":"left"
}
}
]
}

17
wwwroot/bottom.ui Normal file
View File

@ -0,0 +1,17 @@
{
"widgettype":"HBox",
"options":{
"cheight":2,
"bgcolor":"#e5e5e5"
},
"subwidgets":[
{
"widgettype":"Text",
"options":{
"otext":"© 2024 版权所有 慢龟终至",
"i18n":true,
"wrap":true
}
}
]
}

15
wwwroot/center.ui Normal file
View File

@ -0,0 +1,15 @@
{
"widgettype":"VBox",
"id":"page_center",
"options":{
"css":"filler"
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('msp_profile.ui')}}"
}
}
]
}

25
wwwroot/connecthost.ui Normal file
View File

@ -0,0 +1,25 @@
{
"widgettype":"PopupWindow",
"options":{
"auto_open":true,
"auto_destroy":true,
"archor":"cc",
"cwidth":45,
"cheight":40,
"movable":true,
"icon":"{{entire_url('/imgs/terminal.png')}}",
"title":"{{params_kw.name}}",
"content":{
"widgettype":"Wterm",
"options":{
"height":"100%",
"width":"100%",
"term_options":{
"fontSize":24
},
"ws_url":"{{entire_url('https://msp.kymoz.com:10443/wss/ws/connecthost.xterm')}}?hostid={{params_kw.id}}"
}
}
}
}

15
wwwroot/get_code.dspy Normal file
View File

@ -0,0 +1,15 @@
debug(f'{params_kw=}')
ns = params_kw.copy()
db = DBPools()
sql = f"""select {params_kw.tblvalue} as {params_kw.valueField},
{params_kw.tbltext} as {params_kw.textField}
from {params_kw.table} where 1=1 """
if params_kw.cond:
sql += f"and {params_kw.cond}"
print('sql=', sql)
dbname = await rfexe('get_module_dbname', 'msp')
async with db.sqlorContext(dbname) as sor:
rs = await sor.sqlExe(sql, ns)
return rs
return []

BIN
wwwroot/imgs/baichuan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
wwwroot/imgs/bc_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/bc_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/bc_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/bl_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/bl_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/bl_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/br_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/br_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/br_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/chatgpt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
wwwroot/imgs/cl_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/cl_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
wwwroot/imgs/cl_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/cr_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/cr_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
wwwroot/imgs/cr_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/deepseek.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
wwwroot/imgs/dot_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
wwwroot/imgs/doubao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
wwwroot/imgs/download.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
wwwroot/imgs/ii_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/ii_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
wwwroot/imgs/ii_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
wwwroot/imgs/key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

BIN
wwwroot/imgs/like.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/imgs/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
wwwroot/imgs/logout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
wwwroot/imgs/minimax.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
wwwroot/imgs/minimax.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
wwwroot/imgs/moonshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
wwwroot/imgs/msp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
wwwroot/imgs/ollama.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
wwwroot/imgs/people.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/imgs/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
wwwroot/imgs/qianfan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
wwwroot/imgs/qianwen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
wwwroot/imgs/register.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
wwwroot/imgs/sage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
wwwroot/imgs/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
wwwroot/imgs/sensetime.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/imgs/submit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
wwwroot/imgs/tc_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/tc_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/tc_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/terminal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

BIN
wwwroot/imgs/tl_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/tl_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/tl_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/tr_black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/tr_empty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
wwwroot/imgs/tr_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
wwwroot/imgs/unlike.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
wwwroot/imgs/upload.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
wwwroot/imgs/user.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
wwwroot/imgs/wechat.svg Normal file
View File

@ -0,0 +1 @@
<svg width="128" height="110" xmlns="http://www.w3.org/2000/svg"><path d="M86.635 33.334c1.467 0 2.917.113 4.358.283C87.078 14.392 67.58.111 45.321.111 20.44.111.055 17.987.055 40.687c0 13.104 6.781 23.863 18.115 32.209l-4.527 14.352 15.82-8.364c5.666 1.182 10.207 2.395 15.858 2.395 1.42 0 2.829-.073 4.227-.189-.886-3.19-1.398-6.53-1.398-9.996 0-20.845 16.98-37.76 38.485-37.76zm-24.34-12.936c3.407 0 5.665 2.363 5.665 5.954 0 3.576-2.258 5.97-5.666 5.97-3.392 0-6.795-2.395-6.795-5.97 0-3.591 3.403-5.954 6.795-5.954zM30.616 32.323c-3.393 0-6.818-2.395-6.818-5.971 0-3.591 3.425-5.954 6.818-5.954 3.392 0 5.65 2.363 5.65 5.954 0 3.576-2.258 5.97-5.65 5.97z"/><path d="M127.945 70.52c0-19.075-18.108-34.623-38.448-34.623-21.537 0-38.5 15.548-38.5 34.623 0 19.108 16.963 34.622 38.5 34.622 4.508 0 9.058-1.2 13.584-2.395l12.414 7.167-3.404-11.923c9.087-7.184 15.854-16.712 15.854-27.471zm-50.928-5.97c-2.254 0-4.53-2.362-4.53-4.773 0-2.378 2.276-4.771 4.53-4.771 3.422 0 5.665 2.393 5.665 4.771 0 2.41-2.243 4.773-5.665 4.773zm24.897 0c-2.24 0-4.498-2.362-4.498-4.773 0-2.378 2.258-4.771 4.498-4.771 3.392 0 5.665 2.393 5.665 4.771 0 2.41-2.273 4.773-5.665 4.773z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
wwwroot/imgs/zhifubao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
wwwroot/imgs/zhipu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

27
wwwroot/index.ui Normal file
View File

@ -0,0 +1,27 @@
{
"widgettype":"VBox",
"options":{
"width":"100%",
"height":"100%"
},
"subwidgets":[
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('top.ui')}}"
}
},
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('center.ui')}}"
}
},
{
"widgettype":"urlwidget",
"options":{
"url":"{{entire_url('bottom.ui')}}"
}
}
]
}

6
wwwroot/keypress.ui Normal file
View File

@ -0,0 +1,6 @@
{
"widgettype":"KeyPress",
"options":{
"height":"100%"
}
}

21
wwwroot/menu.ui Normal file
View File

@ -0,0 +1,21 @@
{
"widgettype":"Menu",
"options":{
"cwidth":10,
"target":"page_center",
"items":[
{
"name":"home",
"label":"主页",
"url":"{{entire_url('msp_profile.ui')}}"
}
{% if get_user() %}
,{
"name":"group",
"label":"设备组",
"url":"{{entire_url('devgroup')}}"
}
{% endif %}
]
}
}

Some files were not shown because too many files have changed in this diff Show More