From aae5024f02f23f6d3f7b58149da206a8c500732b Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 4 Jun 2025 15:23:10 +0800 Subject: [PATCH] bugfix --- app/fileMGR.py | 20 ++++++++++++ conf/config.json | 77 +++++++++++++++++++++++++++++++++++++++++++++ filemgr/filemgr.py | 54 ++++++++++++++++++++++++------- filemgr/init.py | 8 +++++ models/file.xlsx | Bin 16662 -> 16723 bytes models/folder.xlsx | Bin 16368 -> 16410 bytes 6 files changed, 147 insertions(+), 12 deletions(-) create mode 100644 app/fileMGR.py create mode 100755 conf/config.json create mode 100644 filemgr/init.py diff --git a/app/fileMGR.py b/app/fileMGR.py new file mode 100644 index 0000000..68424d2 --- /dev/null +++ b/app/fileMGR.py @@ -0,0 +1,20 @@ +from bricks_for_python.init import load_bricks +from appbase.init import load_appbase +from rbac.init import load_rbac +from filemgr.init import load_filemgr +from ahserver.webapp import webapp + +def get_module_dbname(mn): + return 'sage' + +def init(): + g = ServerEnv() + g.get_module_dbname = get_module_dbname + load_appbase() + load_rbac() + load_filemgr() + load_bricks() + +if __name__ == '__main__': + webapp(init) + diff --git a/conf/config.json b/conf/config.json new file mode 100755 index 0000000..69adf6d --- /dev/null +++ b/conf/config.json @@ -0,0 +1,77 @@ +{ + "password_key":"!@#$%^&*(*&^%$QWERTYUIqwertyui234567", + "logger":{ + "name":"sage", + "levelname":"clientinfo", + "logfile":"$[workdir]$/logs/sage.log" + }, + "filesroot":"$[workdir]$/files", + "databases":{ + "mediadb":{ + "driver":"aiomysql", + "async_mode":true, + "coding":"utf8", + "maxconn":100, + "dbname":"mediadb", + "kwargs":{ + "user":"test", + "db":"mediadb", + "password":"QUZVcXg5V1p1STMybG5Ia6mX9D0v7+g=", + "host":"localhost" + } + } + }, + "website":{ + "paths":[ + ["$[workdir]$/wwwroot",""] + ], + "client_max_size":20000, + "host":"0.0.0.0", + "port":9080, + "coding":"utf-8", + "indexes":[ + "index.html", + "index.tmpl", + "index.ui", + "index.dspy", + "index.md" + ], + "startswiths":[ + { + "leading":"/idfile", + "registerfunction":"idfile" + } + ], + "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_oops":{ + "url":"redis://127.0.0.1:6379" + } + }, + "langMapping":{ + "zh-Hans-CN":"zh-cn", + "zh-CN":"zh-cn", + "en-us":"en", + "en-US":"en" + } +} diff --git a/filemgr/filemgr.py b/filemgr/filemgr.py index c3ead16..35ead4d 100644 --- a/filemgr/filemgr.py +++ b/filemgr/filemgr.py @@ -1,7 +1,10 @@ +from traceback import format_exc from ahserver.serverenv import get_serverenv -from appPublic.uniqueID import getID -from sqlor.dbpools import DBPools from ahserver.auth_api import get_userinfo +from sqlor.dbpools import DBPools +from appPublic.uniqueID import getID +from appPublic.log import debug, error, exception +from appbase.params import get_parmas def get_dbname(): f = get_serverenv('get_module_dbname') @@ -33,9 +36,11 @@ class FileMgr: ns['orgid'] = userinfo.userorgid, ns['biztype'] = self.biztype ns['id'] = getID() + ns['cur_size'] = 0 + ns['max_size'] = await get_params(sor, userinfo.userid, 'folder_max_size); await sor.C('folderinfo', ns) - return UiMessage(title='folderinfo', 'add record successful') - return UiError(title='folderinfo', 'add record failed') + return True + return False async def delete_bizinfo_node(self, request, ns): userinfo = await get_session_userinfo(request) @@ -46,8 +51,8 @@ class FileMgr: ns1['biztype'] = self.biztype ns1['id'] = ns['id'] await sor.D('folderinfo', ns1) - return UiMessage(title='folderinfo', 'delete record successful') - return UiError(title='folderinfo', 'delete record failed') + return True + return False async def update_bizinfo_node(self, request, ns): userinfo = await get_session_userinfo(request) @@ -60,8 +65,8 @@ class FileMgr: recs = await sor.R('folderinfo', ns1) if len(recs) > 0: await sor.U('folderinfo', ns1) - return UiMessage(title='folderinfo', 'delete record successful') - return UiError(title='folderinfo', 'delete record failed') + return True + return return async def add_folder(self, request, ns): userinfo = await get_session_userinfo(request) @@ -72,8 +77,8 @@ class FileMgr: ns1['biztype'] = self.biztype ns1['id'] = ns['id'] await sor.D('folderinfo', ns1) - return UiMessage(title='folderinfo', 'delete record successful') - return UiError(title='folderinfo', 'delete record failed') + return True + return False async def get_subfolder(self, request, fid, fiid): userinfo = await get_session_userinfo(request) @@ -148,6 +153,31 @@ where id = ${fiid}$ ns1['biztype'] = self.biztype ns1['id'] = ns['id'] await sor.D('folderinfo', ns1) - return UiMessage(title='folderinfo', 'delete record successful') - return UiError(title='folderinfo', 'delete record failed') + return True + return False + + async def delete_file(self, request, fid, fiid): + userinfo = await get_session_userinfo(request) + dbname = get_dbname() + db = DBPools() + async with db.sqlorContext(dbname) as sor: + sql = """select a.id as fiid, b.* +from folderinfo a, file b +where a.id = ${fiid}$ + and b.id = ${fid}$ + and a.orgid = ${orgid} + and b.userid = ${userid}$ + and a.biztype = ${biztype}$""" + ns = { + 'fid':fid, + 'fiid':fiid, + 'userid':userinfo.userid, + 'orgid':userinfo.userorgid, + 'biztype':self.biztype + } + recs = await sor.sqlExe(sql, ns) + if len(recs) > 0: + await sor.D('file', {'id': fid}) + return True + return False diff --git a/filemgr/init.py b/filemgr/init.py new file mode 100644 index 0000000..a64a6d1 --- /dev/null +++ b/filemgr/init.py @@ -0,0 +1,8 @@ +from ahserver.serverenv import ServerEnv +from filemgr.filemgr import FileMgr + +def load_filemgr(): + g = ServerEnv() + g.FileMgr = FileMgr + + diff --git a/models/file.xlsx b/models/file.xlsx index 3a3d6c2691b6fac56968308592f24860bcb097be..4b73848e676606bc446f54c6f50260534b5613e9 100644 GIT binary patch delta 3215 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 B?z{j1 delta 3236 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 diff --git a/models/folder.xlsx b/models/folder.xlsx index a69d9ab76c7245be9599cb42d95cf29a275fcf70..ce19cb34f134ae3381586265a415333bec5a0b66 100644 GIT binary patch delta 2945 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 V(7viFAa(_GwW>U+s^Y)ce*pz2fL{Or delta 2912 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 l4k5&Sxd~(dfX5%V%=BLb6fPG5C*N1W%_CH