From 0691a54ad3c9b7fdaa85c8a850ed1cefc278e5e4 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Thu, 11 Dec 2025 20:24:41 +0800 Subject: [PATCH] bugfix --- kdb/architech.md | 248 -------------------------------------------- kdb/crud.md | 91 ++++++++++++++++ kdb/design.md | 36 +++++++ kdb/example.dspy | 3 +- kdb/foldertree.md | 29 ++++++ kdb/module_logic.md | 71 +++++++++++++ kdb/tbldef.md | 49 +++++++++ 7 files changed, 278 insertions(+), 249 deletions(-) delete mode 100644 kdb/architech.md create mode 100644 kdb/crud.md create mode 100644 kdb/design.md create mode 100644 kdb/foldertree.md create mode 100644 kdb/module_logic.md create mode 100644 kdb/tbldef.md diff --git a/kdb/architech.md b/kdb/architech.md deleted file mode 100644 index b24f779..0000000 --- a/kdb/architech.md +++ /dev/null @@ -1,248 +0,0 @@ -# 模块开发规范 -一下假设开发的模块名称为mymodule - -模块使用ahserver后台和bricks开发h5规范前端web应用,模块需要遵守以下约素: - -* 模块目录必须符合下面的模块目录结构要求 - -* 函数export,定义模块可被dspy脚本和ui前端界面或其他模块调用函数 - -## 列表形式的数据表crud定义 - -当一张数据表不是树形结构的就是表形结构的crud - -表形机构表的crud的json说明 -{ - "tblname" # 表名 - "alias" # 别名,当需多个crud界面时,可用alias来生成份不同的功能 - "title" # 标题,如果不给定,使用数据表定义中的表标题 - "params":{ # crud 的参数 - "sortby" # 指定排序字段,可以多个字段,用["a desc", "b"]>形式给出按照多个字段排序,"desc“表示倒排,不给定就是正排 - "logined_userorgid" # 可选,如果表中有机构编码id,并且需要按照机构过滤 - "logined_userid" # 可选,如果表中有用户id,并且需要登录用户过滤 - "confidential_fields" # 可选,敏感字段名数组,如果表中有敏感字段,要填写 - "editor":{ # 给定编辑时form初始化参数 - # 需要参考bricks的Form控件 - "binds":[ # 比如添加事件处理 - { - "wid":"province_id", # 指定form的事件名 - "event":"changed", # 事件,比如数据变化 - "actiontype":"script", # 事件处理类型 - "target":"city_id", # 目标控件 - "script": # 脚本内容,规定用js脚本 - } - ] - }, - "browserfields": { # 列表显示的参数 - "exclouded": ["id"], # 不显示的字段列表 - "alters": { # 需要改变的字段属性 - "field1":{ # 例子:将字段field1改为选项输入 - "uitype":"code", # 设置输入类型为"code" - # uitype类型也可以用dataurl设置一个url从服务器获取数据 - # 如果设置了打他URL, datamethod和dataparams可选 - "data":[ # 设置选项数据内容 - { - "value":"v1", # value是数据值 - "text": "显示项"# text是此值对应的显示内容 - }, - ... - ] - } - } - }, - "editexclouded": [ # 编辑时不包含的字段列表 - ], - "subtables":[ # 可选,外键清单(表中存在字段指向本表主键记录) - { - "field" # 外键表字段 - "title" # 可选,不选用外键表的表标题 - "url" # 当alias定义时需要,用{{entire_url(...)方式定义 -指向表的url - "subtable" # 外键表名称 - } - ] - } -} - -## 树形结构的数据表crud -当一张数据表中存在一个父节点的字段指向本表中另条记录的主键id,那么这个表就是一个树形>结构的表 - -树形机构表的crud的json数据说明 -{ - "tblname" # 表名 - "alias" # 别名,当需多个crud界面时,可用alias来生成份不同的功能 - "uitype": "tree"# 给定uitype为"tree"指定用树状结构数据crud - "title" # 标题,如果不给定,使用数据表定义中的表标题 - "params":{ # crud 的参数 - "idField": # 必须,指定树节点的id字段 - "textField" # 指定树节点显示内容字段 - "sortby" # 指定排序字段,可以多个字段,用[a desc, b]形式>给出按照多个字段排序,"desc“表示倒排,不给定就是正排 - "confidential_fields" # 可选,敏感字段名数组,如果表中有敏感字段,要填写 - "browserfields": { # 列表显示的参数 - "alters": {} # 需要改变的字段属性 - } - "logined_userorgid" # 可选,如果表中有机构编码id,并且需要按照机构过滤 - "logined_userid" # 可选,如果表中有用户id,并且需要登录用户过滤 - "editable" # true代表可编辑,false表示不可编辑,通常给定true - "edit_exclouded_fields" # 设置不参与编辑(新增和修改)字段,数组 - "parentField" # 父节点字段 - "subtables":[ # 外键清单(表中存在字段指向本表主键记录) - { - "field" # 外键表字段 - "title" # 可选,不选用外键表的表标题 - "url" # 当alias定义时需要,用{{entire_url(...)方式定义 -指向表的url - "subtable" # 外键表名称 - } - ], - } -} - -## 数据库表定义规范 -模块中需要定义数据表要遵守一下规范 - -数据库表用一个json格式文件或数据来定义,具体规范如下 - -{ - "summary":[ # 仅一条记录 - { - "name" # 表名 - "title" # 表标题 - "primary" # 主键=“id”, 所有表均以id为主键 - "catelog" # 可选项:entity relation dimession indication - } - ], - "fields":[ # 字段 - { - "name" - "title" - "type" #可选项有:str char short long llong date time timestamp float double ddouble decimal text - "length" - "dec" - "nullable" # 可选项:yes no - "default" - "comments" # 注释 - } - ] - "indexes":[ - { - "name" # 每个索引一个,idxname不能重复一个表中 - "idxtype" # unique or index - "idxfields" # 字段名或字段名数组[f1,f1] - } - ] - “codes":[ # 如果一个字段数据可以从其他表中获得,可以通过下面的模式定义选择输入逻 -辑 - { - "field" # 字段的名字 - "table" # 数据来源表 - "valuefield" # 数据来源表值字段 - "textfield" # 数据来源表显示字段 - "cond" # 检索条件 - } - ] -] -说明: -id字段全部使用str 32类型 -字典中的length:如果type是str char float double ddouble decimal中的一个,则必为>0的>数字 -字典中的dec: 如果type是float double ddouble decimal中的一个,则必须是>0的数字 - - -## 模块目录结构 -``` -mymodule - | - +--mymodule目录 # 存放模块的主要逻辑py代码 - | | - | +--init.py # 模块初始化脚本,需要定义一个load_mymodule()函数,此函>数需要将在ui和dspy文件中用到的函数通过ServerEnv实例传过去 - | | - | +--__init__.py #python模块所需 - | | - | +--其他源码.py # 模块中需要的其他py源码文件 - | - +--wwwroot目录 # web服务脚本,文件以.ui和.dspy结束,ui文件支持jinja2模>板,前端控件文件,内容为json格式的控件描述文本, dspy是ahserver支持的受限python脚本>,可以按照需要设置下级目录 - | - +--models目录 # 模块使用的数据表以.xlsx后缀存放在此目录中 - | - +--json目录 # 存放json文件,定义数据表的CRUD逻辑 - | - +--pyproject.toml文件 # pip打包文件, 其中项目名字与mymodule相同 - | - +--README.md文件 # 模块自说明文件 - | - +--init目录 # 模块初始化目录 - | - +--data.xlsx # 初始化数据,一个sheet一个表,一行一个记录,第一行为字>段名 - | - +--script.py # 初始化脚本 -``` - -## mymodule/init.py的主要内容 -``` -from ahserver.serverenv import ServerEnv -from appPublic.worker import awaitify -from .x import a, b, c # a,b, c是协程 -from .y import x, y # x, y是普通函数 - -def load_mymodule(): # mymodule需替换为实际的模块名字 - env = ServerEnv() - env.a = a # 脚本中用"a" 调用"a" - env.b = b # 脚本中用"b"调用"b" - env.cc = c # 脚本中用"cc"调用"c" - env.y = awaitify(y) # 将函数包装为协程 - env.x = awaitify(x) # 将函数包装为协程 -``` -注释:这里的load_mymodule中的mymodule是模块名字,而不是“mymodule”本身 - -## 模块设计要求 - -* 模块中的主要逻辑用py源码实现,放在mymodule目录下 - -* 客户端业务功能放在wwwroot目录下,以.ui和.dspy后缀结束,用.ui文件遵守jinja2规范, 而.dspy文件是一个受控的脚本 - -* 返回客户端数据的功能放在wwwroot目录下,以.dspy后缀结束 - -## ui, dspy可以直接使用的变量 - -### request -aiohttp.Request实例,每个客户端请求有一个独立的Request实例 - -request._run_ns可以获得所有在.ui和.dspy源码中可以使用的变量,通过ahserver.ServerEnv 传递 - -### params_kw -DictObject(dict子类, 支持a.b方式获取属性)实例,接收到客户端传来的数据,如果有文件>,文件都保存在服务器指定的位置,params_kw中属性名保存的是其相对路径,可用FileStorage().realPath(params_kw.myfile)来获得文件在服务器中的实际路径。 - -### get_user() -来自rbac模块,协程函数,获得当前登录用户,如果用户没有登录,返回None - -### get_userorgid() -来自rbac模块,协程函数,获得当前登录用户的机构id,如果用户没有登录,返回None - -## pyproject.toml和README.md -编写pyproject.toml文件和README.md文件 - -## 模块中使用的编码 -模块中如果用到编码,编码需保存在appbase模块的appcodes表和appcodes_kv两个表中 -appcodes(编码表)有如下字段: -[ - "id" # str 32, 主键,可设置为数据表字段名称 - "name" # 编码名称 - "hierarchy_flg", # str 1, '0':单级编码,“1”:多级编码 -] -appcodes_kv(编码键值表)字段如下 -[ - "id", # str, 32,主键,唯一值 - "parentid" # str, 32, 一级编码为appcodes表的id, 否则为上级编码键值记录的id - “k" # str 32, 编码值 - “v” “ str 255,编码显示文本 -] - -python 模块设计要完成 -1)定义模块所需的数据库表,每个数据表使用二级标题为"models/<表名>.json", 内容为原始格式的json文档 -2)初始化数据, 二级标题为"init/data.json", 内容为原始格式初始化数据; -3)mymodule下的init.py源码,二级标题为“mymodule/init.py",内容为原始格式的代码 -4)mymodule下的其他代码,二级标题为“mymodule/x.py”,内容为原始格式的用中文编写伪代码,描述业务处理逻辑,说明使用的接口以及提供的接口 -5)二级标题“init/script.py“,提供中文编写的初始化业务处理逻辑伪代码 -6) 二级标题pyproject.toml和README.md, 内容原始格式的完整内容 -7) 前端界面设计,每个界面一个设计文档,文档中使用bricks的控件组合描述界面,如果需要的控件bricks中没有,按照bricks控件扩展规范编写新控件代码,二级标题为“wwwroot/myui.ui" 内容为ui界面内容 -8)bricks扩展控件,二级标题为"wwwroot/ext.js", 和 “wwwroot/ext.css", 内容分别为原始格式的js和css diff --git a/kdb/crud.md b/kdb/crud.md new file mode 100644 index 0000000..9abcc8b --- /dev/null +++ b/kdb/crud.md @@ -0,0 +1,91 @@ +## 列表形式的数据表crud定义 + +当一张数据表不是树形结构的就是表形结构的crud + +表形机构表的crud的json说明 +{ + "tblname" # 表名 + "alias" # 别名,当需多个crud界面时,可用alias来生成份不同的功能 + "title" # 标题,如果不给定,使用数据表定义中的表标题 + "params":{ # crud 的参数 + "sortby" # 指定排序字段,可以多个字段,用["a desc", "b"]>形式给出按照多个字段排序,"desc“表示倒排,不给定就是正排 + "logined_userorgid" # 可选,如果表中有机构编码id,并且需要按照机构过滤 + "logined_userid" # 可选,如果表中有用户id,并且需要登录用户过滤 + "confidential_fields" # 可选,敏感字段名数组,如果表中有敏感字段,要填写 + "editor":{ # 给定编辑时form初始化参数 + # 需要参考bricks的Form控件 + "binds":[ # 比如添加事件处理 + { + "wid":"province_id", # 指定form的事件名 + "event":"changed", # 事件,比如数据变化 + "actiontype":"script", # 事件处理类型 + "target":"city_id", # 目标控件 + "script": # 脚本内容,规定用js脚本 + } + ] + }, + "browserfields": { # 列表显示的参数 + "exclouded": ["id"], # 不显示的字段列表 + "alters": { # 需要改变的字段属性 + "field1":{ # 例子:将字段field1改为选项输入 + "uitype":"code", # 设置输入类型为"code" + # uitype类型也可以用dataurl设置一个url从服务器获取数据 + # 如果设置了打他URL, datamethod和dataparams可选 + "data":[ # 设置选项数据内容 + { + "value":"v1", # value是数据值 + "text": "显示项"# text是此值对应的显示内容 + }, + ... + ] + } + } + }, + "editexclouded": [ # 编辑时不包含的字段列表 + ], + "subtables":[ # 可选,外键清单(表中存在字段指向本表主键记录) + { + "field" # 外键表字段 + "title" # 可选,不选用外键表的表标题 + "url" # 当alias定义时需要,用{{entire_url(...)方式定义 +指向表的url + "subtable" # 外键表名称 + } + ] + } +} + +## 树形结构的数据表crud +当一张数据表中存在一个父节点的字段指向本表中另条记录的主键id,那么这个表就是一个树形>结构的表 + +树形机构表的crud的json数据说明 +{ + "tblname" # 表名 + "alias" # 别名,当需多个crud界面时,可用alias来生成份不同的功能 + "uitype": "tree"# 给定uitype为"tree"指定用树状结构数据crud + "title" # 标题,如果不给定,使用数据表定义中的表标题 + "params":{ # crud 的参数 + "idField": # 必须,指定树节点的id字段 + "textField" # 指定树节点显示内容字段 + "sortby" # 指定排序字段,可以多个字段,用[a desc, b]形式>给出按照多个字段排序,"desc“表示倒排,不给定就是正排 + "confidential_fields" # 可选,敏感字段名数组,如果表中有敏感字段,要填写 + "browserfields": { # 列表显示的参数 + "alters": {} # 需要改变的字段属性 + } + "logined_userorgid" # 可选,如果表中有机构编码id,并且需要按照机构过滤 + "logined_userid" # 可选,如果表中有用户id,并且需要登录用户过滤 + "editable" # true代表可编辑,false表示不可编辑,通常给定true + "edit_exclouded_fields" # 设置不参与编辑(新增和修改)字段,数组 + "parentField" # 父节点字段 + "subtables":[ # 外键清单(表中存在字段指向本表主键记录) + { + "field" # 外键表字段 + "title" # 可选,不选用外键表的表标题 + "url" # 当alias定义时需要,用{{entire_url(...)方式定义 +指向表的url + "subtable" # 外键表名称 + } + ], + } +} + diff --git a/kdb/design.md b/kdb/design.md new file mode 100644 index 0000000..4947671 --- /dev/null +++ b/kdb/design.md @@ -0,0 +1,36 @@ + +## ui, dspy可以直接使用的变量 + +### request +aiohttp.Request实例,每个客户端请求有一个独立的Request实例 + +request._run_ns可以获得所有在.ui和.dspy源码中可以使用的变量,通过ahserver.ServerEnv 传递 + +### params_kw +DictObject(dict子类, 支持a.b方式获取属性)实例,接收到客户端传来的数据,如果有文件>,文件都保存在服务器指定的位置,params_kw中属性名保存的是其相对路径,可用FileStorage().realPath(params_kw.myfile)来获得文件在服务器中的实际路径。 + +### get_user() +来自rbac模块,协程函数,获得当前登录用户,如果用户没有登录,返回None + +### get_userorgid() +来自rbac模块,协程函数,获得当前登录用户的机构id,如果用户没有登录,返回None + +## pyproject.toml和README.md +编写pyproject.toml文件和README.md文件 + +## 模块中使用的编码 +模块中如果用到编码,编码需保存在appbase模块的appcodes表和appcodes_kv两个表中 +appcodes(编码表)有如下字段: +[ + "id" # str 32, 主键,可设置为数据表字段名称 + "name" # 编码名称 + "hierarchy_flg", # str 1, '0':单级编码,“1”:多级编码 +] +appcodes_kv(编码键值表)字段如下 +[ + "id", # str, 32,主键,唯一值 + "parentid" # str, 32, 一级编码为appcodes表的id, 否则为上级编码键值记录的id + “k" # str 32, 编码值 + “v” “ str 255,编码显示文本 +] + diff --git a/kdb/example.dspy b/kdb/example.dspy index e391502..b64081d 100644 --- a/kdb/example.dspy +++ b/kdb/example.dspy @@ -3,7 +3,7 @@ dspy脚本可用的变量 ahserver/globalEnv.py程序中推送到ServerEnv中的变量 各个模块init_mymodule函数推送的变量 request -""" +``` info(f'{params_kw=}, {request.url=}, {request.path=}') def vcode(): codes = [ str(random.randint(0, 10)) for i in range(6) ] @@ -29,3 +29,4 @@ async with db.sqlorContext('sage') as sor: return PopError(title='Error', message=f'{params_kw.cell_no} generate validate code error') +``` diff --git a/kdb/foldertree.md b/kdb/foldertree.md new file mode 100644 index 0000000..67657cd --- /dev/null +++ b/kdb/foldertree.md @@ -0,0 +1,29 @@ +## 模块目录结构 +一下假设新建模块名称为“mymodule" +``` +mymodule + | + +--mymodule目录 # 存放模块的主要逻辑py代码 + | | + | +--init.py # 模块初始化脚本,需要定义一个load_mymodule()函数,此函数将在ui和dspy文件中用到的模块变量通过ServerEnv实例传过去 + | | + | +--__init__.py #python模块所需 + | | + | +--其他源码.py # 模块中需要的其他py源码文件 + | + +--wwwroot目录 # web服务脚本,文件以.ui和.dspy结束,ui文件支持jinja2模>板,前端控件文件,内容为json格式的控件描述文本, dspy是ahserver支持的受限python脚本>,可以按照需要设置下级目录 + | + +--models目录 # 模块使用的数据表以表定义规范要求json数据以.json后缀文件存放在此目录中 + | + +--json目录 # 存放json文件,定义数据表的CRUD逻辑 + | + +--pyproject.toml文件 # pip打包文件, 其中项目名字与mymodule相同 + | + +--README.md文件 # 模块自说明文件 + | + +--init目录 # 模块初始化目录 + | + +--data.xlsx # 初始化数据,一个sheet一个表,一行一个记录,第一行为字>段名 + | + +--script.py # 初始化脚本 +``` diff --git a/kdb/module_logic.md b/kdb/module_logic.md new file mode 100644 index 0000000..d74ed4f --- /dev/null +++ b/kdb/module_logic.md @@ -0,0 +1,71 @@ +## 要求 + +* 模块中的主要逻辑用py源码实现,放在mymodule目录下 + +* 客户端业务功能放在wwwroot目录下,以.ui和.dspy后缀结束,用.ui文件遵守jinja2规范, 而.dspy文件是一个受控的脚本 + +* .dspy中不允许import模块 + +* 假设模块名为”mymodule“ +## mymodule目录 +“mymodule”为模块名称, 模块目录下存放以py结束的代码文件,其中init.py文件为必须 +在此目录下的代码中可以通过ahserver.serverenv模块的ServerEnv来引用其他模块的放进来的变量 + +### init.py的主要内容 +``` +from ahserver.serverenv import ServerEnv +from appPublic.worker import awaitify +from .x import a, b, c # 从同目录下的源码x.py中import a,b, c是协程 +from .y import x, y # 从同目录下源码y.py中import x, y是普通函数 + +def load_mymodule(): # mymodule需替换为实际的模块名字 + env = ServerEnv() + env.a = a # 脚本中用"a" 调用"a" + env.b = b # 脚本中用"b"调用"b" + env.cc = c # 脚本中用"cc"调用"c" + env.y = awaitify(y) # 将函数包装为协程 + env.x = awaitify(x) # 将函数包装为协程 +``` +注释:这里的load_mymodule中的mymodule是模块名字,而不是“mymodule”本身 + +模块的其他代码都需要放在这个目录中,而模块中所有需要在ui,dspy脚本中用到的变量均需要通过init.py函数的load_mymodule()函数传递 + +## ui, dspy可以直接使用的变量 + + +### request +aiohttp.Request实例,每个客户端请求有一个独立的Request实例 + +request._run_ns可以获得所有在.ui和.dspy源码中可以使用的变量,通过ahserver.ServerEnv 传递 + +### params_kw +DictObject(dict子类, 支持a.b方式获取属性)实例,接收到客户端传来的数据,如果有文件>,文件都保存在服务器指定的位置,params_kw中属性名保存的是其相对路径,可用FileStorage().realPath(params_kw.myfile)来获得文件在服务器中的实际路径。 + +### get_user() +来自rbac模块,协程函数,获得当前登录用户,如果用户没有登录,返回None + +### get_userorgid() +来自rbac模块,协程函数,获得当前登录用户的机构id,如果用户没有登录,返回None + +### 各个模块通过load_xxxx()放到ServerEnv()中的变量 +XXXX是模块名称 + +## pyproject.toml和README.md +编写pyproject.toml文件和README.md文件 + +## 模块中使用的编码 +模块中如果用到编码,编码需保存在appbase模块的appcodes表和appcodes_kv两个表中 +appcodes(编码表)有如下字段: +[ + "id" # str 32, 主键,可设置为数据表字段名称 + "name" # 编码名称 + "hierarchy_flg", # str 1, '0':单级编码,“1”:多级编码 +] +appcodes_kv(编码键值表)字段如下 +[ + "id", # str, 32,主键,唯一值 + "parentid" # str, 32, 一级编码为appcodes表的id, 否则为上级编码键值记录的id + “k" # str 32, 编码值 + “v” “ str 255,编码显示文本 +] + diff --git a/kdb/tbldef.md b/kdb/tbldef.md new file mode 100644 index 0000000..3b72021 --- /dev/null +++ b/kdb/tbldef.md @@ -0,0 +1,49 @@ +## 数据库表定义规范 +模块中需要定义数据表要遵守一下规范 + +数据库表用一个json格式文件或数据来定义,具体规范如下 + +{ + "summary":[ # 仅一条记录 + { + "name" # 表名 + "title" # 表标题 + "primary" # 主键=“id”, 所有表均以id为主键 + "catelog" # 可选项:entity relation dimession indication + } + ], + "fields":[ # 字段 + { + "name" + "title" + "type" #可选项有:str char short long llong date time timestamp float double ddouble decimal text + "length" + "dec" + "nullable" # 可选项:yes no + "default" + "comments" # 注释 + } + ] + "indexes":[ + { + "name" # 每个索引一个,idxname不能重复一个表中 + "idxtype" # unique or index + "idxfields" # 字段名或字段名数组[f1,f1] + } + ] + “codes":[ # 如果一个字段数据可以从其他表中获得,可以通过下面的模式定义选择输入逻 +辑 + { + "field" # 字段的名字 + "table" # 数据来源表 + "valuefield" # 数据来源表值字段 + "textfield" # 数据来源表显示字段 + "cond" # 检索条件 + } + ] +] +说明: +id字段全部使用str 32类型 +字典中的length:如果type是str char float double ddouble decimal中的一个,则必为>0的>数字 +字典中的dec: 如果type是float double ddouble decimal中的一个,则必须是>0的数字 +