导图社区 PaaS平台学习笔记
PaaS平台学习笔记的思维导图,有组件、移动端组件、样式、操作、页面、数据、服务、流程、应用、门户、发布、配置、代码.... ...
编辑于2023-07-21 14:00:18 四川省PaaS平台学习笔记
组件
一般组件
插入后一般记得要选择关联数据源
组件升级
如果不升级为最新版本,可能执行会报错之类的
图片
插入后一般记得要选择“动态图片地址”
选择器
不要使用“下拉xx”
动态数据集
新增的“计算列”,设置值需要使用“规则设置”中的“计算”属性来设置
统计:“输入框”、“文本”组件可以显示正常
表格
主从从进行的子表再嵌套表格的方式存在问题,不要使用这种方式
序号:设置计算列,再设置计算值为对象的“跨页序号”
字段排序:点击某个字段,会出现“排序”的设置
显示多表头(表头分组)
https://docs.i.newdao.top/devbase/pc-dev-antd/table/moreheader.html
表头合并
设置“表头合并”属性,比如前边一个表头设置为2,后边一个表头设置0,则只会显示第一个表头
页面中放一个表格就报页面编译错?
重启应用试试
表格嵌套表格、子表格
如果子表格不显示主表格的变量,可能是2个表格的id重复了,手动在源码中修改一下表格id
表单
有表单项才能进行必填预警提示,所以在表格中不能进行提示
日历
案例:用原生React组件实现日历自定义渲染
计时器
动态列表
对话框
高级请求
解决前端访问链接出现的跨域问题
外部页面
配置第三方URL
附件
文件预览
参考文档:https://docs.i.newdao.top/mp/file.html https://docs.i.newdao.top/devbase/pc-dev-antd/upload/file-view.html
1、添加“文件预览”应用,需要使用kube集群部署。2、等待文件预览正常运行后,再进行服务注册。3、附件设置文件预览服务为true。
问题
预览地址不对:{"message":"no Route matched with those values"}
需要从门户访问页面进行预览,不能从预览操作中去查看
预览地址原理:
var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址 window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(base64Encode(url)));
js地址转换
encodeURIComponent:https://www.sojson.com/encodeurl.html
base64编码:https://tool.ip138.com/base64/
脱离门户访问
在应用本身加一个路由
测试:在应用的监测->网关监控->
1、添加服务管理:fileview,主机:fileview.newdao-tenant-anli
2、添加路由管理:fileview,Service选择fileview,Paths设置为/fileview,高级选项中的截断Path勾选
在应用内添加 app.m 文件
app.m放置的路径
不能放置在 main 模块下,否则会访问提示访问 /fileview/health 错误
{"msg":"{\"timestamp\":\"2023-04-20T03:11:49.996+00:00\",\"status\":404,\"error\":\"Not Found\",\"message\":\"\",\"path\":\"/fileview/health\"}","status":404}
原因:main.meta 设置了 health-check,会做健康检查
{ "label":"主服务", "dbrest-resource": "class", "health-check":{} }
model/service 新建一个文件夹(名称随意)
放置 app.m
app.m设置
<service> <name>fileview</name> <request_path>/fileview</request_path> <preserve_host>true</preserve_host> <strip_request_path>true</strip_request_path> <upstream_url>http://fileview.newdao-tenant-anli:80/ </upstream_url> </service>
云ide测试,需要重启应用
https://frontcaseanli4-anli-ide.e.newdao.top/fileview/onlinePreview?url=aHR0cHM6Ly9lbnRyeWFubGk0LXZpcC5lLm5ld2Rhby50b3AvZnJvbnRjYXNlL3N0b3JhZ2UvZ2V0T2JqZWN0P3N0b3JlRmlsZU5hbWU9YW5veV9DQTEzMEREMjA0MTAwMDAxQTIyQTE2OTExOUI5QTQ1MDEuZG9jeCZyZWFsRmlsZU5hbWU9MS5kb2N4Jm9wZXJhdGVUeXBlPWZpbGV2aWV3JmZ1bGxmaWxlbmFtZT0xLmRvY3g%3D
运行时应用,应用需要进行发布
标签页
富文本
日期选择器
绑定数据列,类型为日期格式的字段。后期可以在查询中,把日期格式转成字符串
时间转为字符串( 查询条件.月份 , "yyyy-MM" )
序号
数据集新增后事件->生成序号,标识为KJ,格式为%04d,序号为1->赋值,目标列为xx,值为获取下个序号("KJ","%04d",1)
附件
多张图片预览(使用图片组件解决不了多张图片问题)
1、关联图片字段;2、关联字段设置为只读;
文本
移动端
多个文本换行的处理
选中中间的文本,设置“是否可见”为block
导入导出
Excel导入
可以选择导入到UI
Excel导出
数据来源
数据服务
进行过滤条件处理
不导出计算列
查询结果数据
根据过滤条件、分页查询的结果,一般为表格显示的内容
导出计算列
分页设置为-1,导出全部数据
全部数据
不使用
一般操作
数据来源:选择查询结果数据
绑定数据列:不用选择
可以设置导出的列
可以导出为word
如果组件能力不足以搞定复杂的word模板,可以看一下这个框架,用java进行word模板渲染,http://deepoove.com/poi-tl/
高级导入
支持主从数据导入
审批意见
要绑定流程
消息对话框
显示确认、取消按钮,以及设置确认、取消的事件操作,可以自己实现删除操作的确认提示
内嵌页面
父页面监听子页面消息的实现
子页面发送消息: onButton2Click(event/*{{{*/=this._e.Button_onClick/*}}}*/){ if (this.getParentFrame()) { this.getParentFrame().fireEvent("message", { url: "$UI/pcx/yanshi/naqian_ym.w" }) } }
父页面监听消息: onPageFrame0Message(event){ debugger; this.comp("tableCustomData0").setValue("link", event.url); }
设置其他微服务页面
/微服务名/pcxapp/pcx/页面路径/xxx.w
/constructionplatform/pcxapp/pcx/juece_pt/daping_sy.w
注意:不支持pc页面
要使用外部页面来支持pc页面
外部页面组件的页面地址,使用函数来获取,写法:$page.getUrl()
getUrl() { let url = "/pcapp/pc/infoPublish/infoPub.w"; let ret = this.getServiceUrl(url, "entry"); return ret; }
级联选择
数据需要有父id字段
不要使用树结构设置,否则数据只会显示出最上边一级
需要设置组件的“主键”、“父ID”这两列
用户对话框
要配合上下文组件使用
dbproxy
关闭开关
连接参数添加:dbproxy=false
重启应用
作用
分布式事务
数据权限
div
多个div根据宽度同一行显示
float:left;
树结构
loadAllTreeData
组织对话框
默认选中条件
写死
[{'name':'name','value':'技术1','op':'eq'},{'name':'name','value':'技术2','op':'eq','kind':'or'}]
函数返回
$page.abc() abc() { [{'name':'name','value':'技术1','op':'eq'},{'name':'name','value':'技术2','op':'eq','kind':'or'}] }
密码框
浏览器自动填充的内容默认不会绑定到对应字段
值改变时机设置为“键盘输入”
页面加载
可以较好的实现流程详情页面的效果
onButton2Click = ({fid}) => (event) => { let url = this.getUIUrl("$UI/pcx/jiangchou_jyfp.w"); justep.Shell.showPage({ url: url, id: fid, action: "view", process: "preallocation_jiangchoujyfp" }) }
移动端组件
扫一扫
手机上使用:需要下载apploader,通过apploader扫描访问页面再使用扫一扫组件
预览使用:模拟数据
扫码成功事件:通过event.detail.result(旧版本event.originalEvent.result)获取二维码对应的文本内容
视图
代替 div
样式
CSS
要强制刷新页面,去除缓存
:global { .ant-btn { border-color: red; } }
如果不想在门户污染其他页面,最上边再套一个 css
页面的“页面”组件设置 mypage class
.mypage { :global { .ant-switch{ background:red; }; .ant-switch-checked{ background:#00ff02; } } }
设置div滚动条样式
#divPcx5::-webkit-scrollbar { /*滚动条整体样式*/ width: 6px; height: 6px; } #divPcx5::-webkit-scrollbar-thumb { border-radius: 10px; background: #4286ed;/*内层轨道*/ } #divPcx5::-webkit-scrollbar-track-piece { border-radius: 10px; background-color: #2c3595;/*内层滚动槽*/ }
颜色渐变
background: linear-gradient(to right bottom, #1e70f0, #49acfd) !important;
提高优先级
!important
颜色透明
https://zhuanlan.zhihu.com/p/572145422
rgba(255,185,91, 0.3)
全局css
PCX下放置common.js
import "./common.css"
在common.css里边写css
覆盖浏览器自动填充的样式
参考:https://juejin.cn/post/7083833351244611620
:global { .ant-input { background-clip: text; -webkit-text-fill-color: blue; // 改变了字体颜色 } }
动态样式
注意,有些disable的样式会覆盖自己的样式,需要加!important
操作
选择
一般要使用双击
保存
有保存按钮的地方,记得点击保存,否则可能新建后不生效
页面
简单查询页面打开报错
新建应用,可能是组件没更新的问题,点击小扳手,一键更新组件
页面解锁
帮助说明: https://docs.i.newdao.top/default.html?token=eyJleHBpcmUiOjE2NTcxOTkxMTEsInRva2VuIjoiMTU0NDg0OTk3NzA0NDYxOTI2NSIsInVzZXJpZCI6Im5UbFZzcE8zM1FOcUtVbnpPNWYiLCJleHBpcmVzX2luIjozMzE0MzU1MDIyLCJobWFjIjoifUHNmCF15tl3rfG6R1xicu72I0puIiwidXNlcm5hbWUiOiJmeGZzcSJ9
方式一:如要对锁定资源进行解锁,则要使用锁定资源的账号进行资源“提交并更新”操作,方可解锁后操作。 方式二:提供租户管理员对锁定应用进行解锁操作,注:此功能确保被锁定账号确实不存在了或者没在操作情况下使用
页面继承
多个类似页面,比如只是判断状态进行过滤数据,可以采用页面继承的方式,子页面设置不同的过滤条件
页面模板生成
使用 Handlebars 模板语言来生成页面
桌面端新建出fileMode=m的页面
新建页面时选择模板要选择antd模板,如果选择到其他模板,新建出来页面的meta文件中的fileMode=m,这样在打开子页面选择页面源的时候,会显示不出页面来
在开发模式,设置了权限的菜单页面没有在调试门户中显示
预览->设置调试用户(如果之前错过了这一步,需要手动设置一个)
脱离门户访问
在开发ide调试访问
https://smartenergybjlt4-bjlt-ide.e.newdao.top/pcxapp/#/pcx/xiangmu_gk/keshi_hzs
门户链接:https://entrybjlt4-vip.e.newdao.top/smartenergy/pcxapp/#/smartenergy/pcxapp/pcx/xiangmu_gk/keshi_hzs
文件夹名称和页面名称修改后,门户菜单没有更新的bug
打开那个应用的云ide,在浏览器调用一下(其中xxx修改为应用云ide的那个域名): https://xxx/x5/UI2/system/designer/webIde/quickIde/serviceMetaInfo/serviceMetaInfoHelper.j?type=genAllServiceMetaInfo
页面使用新页打开(不在门户打开)
找到页面对应的 .meta:比如 daping_sy.w.meta
menuTypes 添加 openPage 类型:"menuTypes":["func", "openPage"]
数据
自定义数据
注意“自动新增”和“自动加载”的区别
动态数据集
版本锁
version,数字字段,勾选“版本锁”。新建新数据会字段设置为0,旧数据为null不会起作用
创建时间、修改时间
创建时间:字段类型为日期时间,并且高级设置中的“数据库类型”中的“类型”,比如MySQL为timestamp; 修改时间:页面或者代码手动设置?
市场组件中找到动态数据集扩展组件
动态数据集添加固定字段:https://docs.i.newdao.top/default.html?token=eyJ0b2tlbiI6IjE1Mzk0MTIwMjA4NTYzMDM2MTciLCJobWFjIjoin8pTsElA%2B1x1MDAwZSpQp4V548NcdTAwMTSYUFx1MDA3Zlx1MDAxYiIsInVzZXJuYW1lIjoidDE4MTg3NTE4MjY4IiwiZXhwaXJlc19pbiI6MzMxMTc2MjAwMiwidXNlcmlkIjoiblFGSjlYVzMzN1d3Qm4wNHQ1OSIsImV4cGlyZSI6MTY1NTkwMjYwMX0%3D#
树形全路径特性
https://docs.i.newdao.top/default.html?token=eyJ0b2tlbiI6IjE1Mzk0MTIwMjA4NTYzMDM2MTciLCJobWFjIjoin8pTsElA%2B1x1MDAwZSpQp4V548NcdTAwMTSYUFx1MDA3Zlx1MDAxYiIsInVzZXJuYW1lIjoidDE4MTg3NTE4MjY4IiwiZXhwaXJlc19pbiI6MzMxMTc2MjAwMiwidXNlcmlkIjoiblFGSjlYVzMzN1d3Qm4wNHQ1OSIsImV4cGlyZSI6MTY1NTkwMjYwMX0%3D
过滤
查询字段数值为xx,xx,xx(逗号分隔多个值),可以使用“包含”查询
子查询
子查询设置:https://docs.i.newdao.top/default.html?token=eyJ1c2VybmFtZSI6ImFubGlkZXYyIiwiZXhwaXJlIjoxNjYwNzQxOTUxLCJ0b2tlbiI6IjE1NTk3MDk3MjU2NzY4Mzg5MTQiLCJleHBpcmVzX2luIjozMzIxNDQwNzAyLCJobWFjIjoiJDVcdTAwMTVUnNVv8e9i5lx1MDAwZlQx2Fx1MDAxY3r7jFx1MDAxNCIsInVzZXJpZCI6Im5VdkdmNEEzMzBUcXNlbVZoNFkifQ%3D%3D#
约束
判断流程环节来判断约束条件
核准数量判断:条件判断( 获取变量( "activity" ) == "部门经理审批" , 计算行.核准数量 > 0 , 真 )
服务数据集
支持2种接口
1、内部服务,通过服务定义 service.m 的
2、OpenAPI服务
需要有 openapi.json
存储过程数据集
这里需要让存储过程返回 select 数据,否则会报错
如果单独调用存储过程,可以在 mybatis 写配置文件调用
静态数据集
和动态数据集对应,静态数据集的数据不存储在数据库中,存储在文件中。
动态数据集生成model,静态数据集生成vo,因此静态数据集常用于作为服务的请求返回。
视图
记得要手动勾选某个字段为“主键”,否则没有主键,列表选择的时候,会把多条数据合并成1条数据
如果没有设置某一列为主键,表格的选择功能会失效,选择不了
gen-java不生成的问题
加入这个配置项会造成不生成代码:<src>disable</src> <src>disable</src> <name>main</name> <version>1.0.1</version> <framework>maven</framework> <dataframe>mybatis</dataframe>
逻辑删除
参考:https://docs.i.newdao.top/devbase/common-func/set-logic-delete.html
只有在门户操作才生效(需要走dbproxy),在普通的预览不会生效
树形数据级联删除
默认不会级联删除,如果需要级联删除(删除父会把下边多级子都一起删除),需要设置“全路径ID”
连接错误
tomcat java.sql.SQLException: Communications link failure 比如:FixedUrl: jdbc:mysql://entry.newdao-tenant-lyyl:3307
查看门户是否异常,请先保证门户正常运行
不显示数据,提示 503
重启应用试试
专题
数据集关系
主从
关联
关联引用设置
树形
创建数据集
直接创建数据集
使用模板创建数据集
市场组件中找到动态数据集扩展组件
从数据库导入
导入时可将蛇式命名转换成小驼峰
默认禁止建表
物理模型
系统在建表时,还可以执行一段SQL,实现扩展能力。例如从上面可以看出系统没有提供创建多列联合索引的功能,那么可以在“扩展SQL”中添加创建联合索引的SQL。在建表后,系统自动执行这个SQL,给表添加联合索引。
代码模型
gen_java -- 系统生成的文件
main dao SaleOrderMapper.java -- Mapper接口 SaleOrderMapper.xml -- 写sql访问数据库 SaleOrderMapperPlus.java model SaleOrder.java -- 实体类
java -- 开发者的文件
main dao SoCustomMapper.java -- Mapper接口 SoCustomMapper.xml -- 写sql访问数据库 service
数据集组件
主从设置
数据集组件为主从数据,提供下面3个能力: 1. 主数据当前行改变后,立即刷新从数据 2. 新增从数据时,外键列自动设置为主数据的主键值 3. 级联保存:保存主数据集的同时,自动保存从数据集
如果数据集没有设置为从数据集,但是希望在前端页面中享受数据集组件为主从数据提供的能力,可以开启主从设置,设置主数据和关联列,即可实现前端主从功能。
是否共享、绑定共享数据
系统提供的共享数据配置实现跨页面共享数据功能,通过在共享数据配置中,将数据集设置为共享数据集,在需要共享数据的页面中,添加该数据集组件,并设置“是否共享”为true,绑定共享数据,这个数据集组件里面的数据就不从后端数据集中获取,而是使用共享数据。
组件方法
数据集组件提供操作、方法和函数。操作用于在设计页面的无代码开发;方法用于在js中的低代码开发;函数用于在设计页面的表达式编辑中使用
方法
异步方法
在调用方法时,需要注意方法是否异步,例如刷新和保存都是异步方法,需要使用异步方法的调用方式。
刷新:refreshData()
保存:saveAllData()
删除:deleteData()
加载外部数据
函数
数据集函数
JSON:将数据集组件中的数据转为JSON对象
数据访问接口
GET查询数据,POST插入数据,PUT插入或更新数据,DELETE删除数据。客户端通过http请求调用数据访问接口,实现对数据的增删改查。
高级特性
1. 数据集参数
2. 服务端过滤
3. 关联查询
3.1. 【已解决】输出数据集的关联引用有问题,Cannot get database connection info
4. 嵌套数据查询
4.1. 【已解决】Caused by: java.lang.NoSuchMethodError: com.alibaba.fastjson.JSONObject.clone()Lcom/alibaba/fastjson/JSONObject;
5. 跨数据库查询
5.1. 访问其他模块的数据集
5.2. 访问租户内其他应用的数据集
6. 数据集规则
7. 数据集事件
8. 自定义方法
9. 获取附件流
10. 编译扩展
服务
前端服务调用
通过服务组件调用
javascript代码调用 – this.comp(…).send({…}).then(function(data){…})
后端服务调用
常用API
com.justep.util.ContextUtil.getServiceName() //获取当前服务名 com.justep.util.net.ServiceUtil.getServiceUrl(String serviceName) //通过服务名获取Url ServiceUtil.post(HttpServletRequest contextRequest, String serviceName, String path, JSONObject body, Class responseType) ServiceUtil.post(String url, JSONObject body, Map headers, Class responseType) ServiceUtil.get(HttpServletRequest contextRequest, String serviceName, String path, Map params, Class responseType) ServiceUtil.get(String url, Map params, Map headers, Class responseType)
跨租户调用
新建特殊用户,生成长期token,对外提供需要的API
服务元数据
xxx/serviceMetaInfo(启动中的应用/服务)
路径
前边需要加 /项目标识,比如:/order/main/order/getreplyexecutorscode
读取本地文件
在resources下只有.xml或者.properties才会编译到classes。可以把配置文件名改成这2个后缀,读取方式不变。
找到target/classes目录看看,放的本地文件有没有编译过去,没编译过去就读取不了
pom.xml添加配置
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <resource> <directory>src/main/gen-java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources>
读取代码
InputStream in = this.getClass().getResourceAsStream("/db.xml"); Properties properties = new Properties(); try { properties.load(in); } catch (IOException e) { e.printStackTrace(); } return properties;
流程
主要流程
流程定义(sa_process表)->流程实例(sa_task表)->待办任务(环节)(sa_task表)
1个表单对应多个流程
根据process参数使用不同的流程
表单字段权限
环节->表单权限
流程变量
作用范围
流程:全局变量,整个流程起作用
任务:只在单个任务起作用
页面中的必填、只读等权限控制,可以先设置流程中的变量,后边引用变量来判断
设置
先在整个流程的高级设置中设置变量名称
再在每个环节的高级设置中对这个变量赋值
API
ProcessUtil工具类(开发手册高级篇)
操作权限
主表的必填、只读、隐藏可以在流程页面中设置
自动/机器人环节
可以自动调用服务来处理逻辑,比如在代码中新开新的流程
[{ "method": "GET", "url": "/order/main/autotask/sendtosap?dataID=${sData1}", "headers": { "Accept": "application/json", "Content-Type": "application/json" }, "body": {} }]
注意:url要区分大小写,否则调用不了
环节处理人
主管
直接主管(一般为部门主管,也就是发起人的1级主管)
公司主管(一般为部门主管的上级主管,也就是发起人的2级主管)
财务
查看发起人所属的财务:组织角色管理->职务->财务
如何配置:处理人->组织角色->职务->财务
流程标题
高级设置->更多设置->启动规则->流程标题:concat(fieldValue('sales'), '的订单,金额为:', toString(fieldValue('money')))
字符串用单引号
通知人
门户首页需要添加“待阅”/“已阅”来查看通知
修改页面为流程页面
刚开始如果建的是普通页面,想加入流程功能,点击页面的“配置”,菜单显示类型修改为“流程”
否则点击流程设计会提示:“非流程页面不能打开流程设计”
流程事件
环节流转后和事件结束后的事件会冲突
环节一般使用流转“前”进行处理
生效条件
fieldValue('reviewComments')='通过'
流程调用服务
流程调用的服务,需要设置为post请求
桌面端和移动端共用流程
两者页面名称相同的话,会自动共用1个流程
规则设置
流程
启动规则
设置流程标题
concat(dateFormat(toDateTime(fieldValue('createTime')), 'yyyy-MM-dd HH:mm:ss'), '的事件告警处理')
通知规则
环节
错误
需要传task,而不是sData1,报错:{"message":"流转出错,原因:流程任务\",CA0CEB2E77A0000113D3124611901187\"必须有sProcess和sActivity属性","url":"/main/flow/advance","status":500}
当前环境不支持流程操作
可能是没更新到页面对应的流程内容,退出用户再进行登录,可以多试几次
流程图没有画?
门户运行打开页面提示:流程"/SA/wf/default/flowseniorcase_liuzhuaicj"没有定义
一般情况下,应用发布后会同步进行流程的上线发布
在流程定义中,需要该流程发布,如果只是草稿状态,会提示找不到流程,可以手动发布一下
任务不允许为空
如果参数sData1有值,但流程任务数据库没有这个sData1,会提示这个错误
一般来说,新建一个流程,流程组件绑定的那个数据,不要去修改它的id。即使后边对这个id设置为空值,也会提示这个错误。
单独对接平台的工作流
如何实现?
前端获取下一个流程节点的id
在工作流组件的流转成功事件中,event里面有processControl
流程导入
新建的微服务应用的标识要和之前一致,这样才能找到对应的流程图
constructionplatform_renyunrcbs
根据微服务应用的标识来获取的
工作流升级
需要同步升级门户
如果不升级,数据集相关的操作会报错(路径找不对)
http://overallGoal?fid=eq.CA457A3F9880000120C756C01EDE1C40
java.net.UnknownHostException: overallGoal: Name does not resolve
应用
门户
账号
默认密码:123456
后台
租户
配置租户私有kube集群
参考redis配置
集群URL配置为:local
镜像仓库地址:hub.newdao.com
查看是否勾选https
镜像仓库登录用户名:admin
镜像仓库登录密码:Local#Repo1@Nexus
镜像拉取密钥:hub.newdao.com
应用/服务管理
从这里新建的应用,如果需要打开,需要点击“更多”->“定制管理”->“开启定制”
创建应用,注意不要选择“定时”这个集群,要使用“共享企业集群”
创建应用创建不了
1、运维管理的kube控制面板
2、在 newdao-console 命名空间,找到 console-deploy-xxx 这个 pod,查看日志是否有异常,比如出现 module 'uaa' load failed
3、对 console-deploy-xxx 这个 pod 进行删除(也就是重启它),等待启动后查看是否正常
导入第三方应用
点击配置菜单,提示:查询外部应用模块数据库信息错误
在架构菜单,点击更新组件
如果发现页面不是最新的,同样也是先更新组件
springboot的jar应用
现版本会自动添加 /服务模块 路径,造成访问不了
应用升级
门户
其他应用
设置为自动升级,重启应用后自动升级,设置为手工升级,在版本管理中选择版本,然后重启
门户
常用接口
获取当前用户的授权角色
/authorize/currentUserRoles
获取当前用户的用户信息
/uaa/userinfo
获取当前用户的token
/uaa/userinfo?type=token
获取当前用户访问的菜单树
/entry/manager/authorized/menus?types=pc&types=func&context=pc&modified=true
需要设置cookie
user_session=xxx
接口匿名访问
在开发阶段,添加匿名用户角色,并选择该接口
角色标识:anonymous,角色名称:匿名用户
需要在登录过账号的门户的浏览器上,执行清除缓存:https://entryanli4-vip4572fc12.e.newdao.top/entry/authorize/clear/cacheClear
再访问接口:https://entryanli4-vip4572fc12.e.newdao.top/frontcase/main/product/list
如果还是访问提示无权限,重新取消、再勾选一下匿名用户关联的服务接口,再进行清除缓存等操作
禁用掉某个应用的域名访问
应用->配置->默认域名,反勾选
这样应用都需要通过门户的域名来访问
发布
租户管理员发布
直接以现在云环境的代码进行发布
成员发布
以租户管理员身份,从git拉取代码进行发布
租户管理员使用本地IDE模式打开
此时其他成员发布应用会发布不了
tomcat项目
1、点击发布一键式编译、部署、运行; 2、tomcat项目:在tomcat容器;打包后的编译文件在:/dist/tomcat/dist 3、前端代码:/usr/local/tomcat/webapps; 4、后端代码:配置文件/usr/local/tomcat/conf/Catalina/localhost/ROOT.xml,指向/usr/local/tomcat/webapps-system/ROOT,是一个 java web 项目,里边有业务代码会加载 work\jarslink 里边的 jar,从而运行相关服务模块,包括项目的main
发布问题
一直卡在:调用node容器: /usr/local/x5/tools/uix-web/release.sh
重启应用,重新打开后再进行发布
重启发布池
发布->查看发布结果->重启发布池
配置
默认角色分配
在门户调试,需要先配置页面可以被哪些角色看到,否则默认其他角色看不到
菜单显示类型
勾选“PC首页内容块”,首页widget可以显示出来
代码
左侧代码目录树没有显示出来
1、换个浏览器试试
2、把浏览器地址栏中的url复制到无痕浏览器中使用
git开发协作
平台动态数据集建的表
A提交git后,B更新,物理数据库的表会自动同步
A在数据库自建表,动态数据集再引入
这种情况,即使git提交后,物理数据库的表不会自动同步,需要B手动执行一下建表sql
资源更新出错!
git更新有冲突。 1、你可以点击“提交并更新”看看是哪个文件冲突,可以手动处理解决冲突; 2、如果冲突不重要,可以“强制覆盖本地”直接使用git覆盖你那边的代码;
组织、用户、权限
角色
门户要展示“任务管理”的”任务中心”,需要授权“流程用户”角色
一人多岗
一个人员可以在多个部门任职,在页面中可切换这个人的部门。API获取这个人的部门时,可通过“获取当前部门名称()”和“获取当前主部门名称()”来区分
组织、用户四级结构
ogn-机构、dpt-部门、pos-岗位、psm-人员成员
组织和用户扩展
权限
权限项
页面权限 按钮权限 API权限 数据权限
应用角色
一个应用角色可以包含多个权限项
业务角色
一个业务角色可以包含多个应用角色(比如部门经理、项目经理)
界面权限
需要设置界面权限页面需要同时引入界面权限组件、用户组件、上下文组件
委托代理设置
受托人访问委托人的权限
外部注册的账号
访问这里https://www.i.newdao.top/的“免费注册”可以注册账号,但没有通过system验证不能进行访问
系统管理员给用户重置密码
数据权限
插入/修改/删除设置的允许值,字符串直接写,不需要加''
外部用户管理
设置角色方式
1、点击某个用户(出现灰色底),点击分配角色;
2、勾选用户前边的方块,可以多选用户,再点击分配角色;
清理授权缓存
https://entrytrain5-vip791bb669.wasionit.com/entry/authorize/clear/debug
多组织
https://docs.i.newdao.top/mp/mleve-org.html
运行门户的权限不生效
注意服务注册有没有注册成功
用户excel批量导入
注意:手机号不能为空,且不能重复,重复就会覆盖修改
从界面中导出的excel原有数据案例,可能存在很多手机号为空的记录
手机号为空,会找到原来某条手机号为空的记录去修改,比如system账号,造成该账号会被修改很多次,改地面目全非
菜单访问第三方页面
在权限管理中“添加菜单”,比如新浪
类型:新页打开
访问地址:https://www.sina.com.cn
system可直接访问页面;普通用户需要新建角色,关联该权限,再授权用户才能访问;
这个请求怎么做权限控制,设定某个附件允许被哪些用户下载? /storage/getObject?storeFileName=XXXX
那个应用中的附件,到应用资源管理功能中添加API设置url
后端开发
常用API
ServiceUtil
本地IDE
更新代码后,需要在页面上显示最新效果,需要重新 Build Project
右键项目,选择属性,点击 Builders 选项,new 1个 ant builder
编译脚本配置:${workspace_loc}\..\tools\compile\ant_compile_service.xml
访问 resourceService.j 出现 504 错误的问题
1、先打开本地ide连接云端,下载代码资源 2、修改newdao-ide-windows\model\.git\config文件的url: 在url中新增git的用户名:密码(在应用的团队查看git账号中获取) 如:url = https://用户名:密码@git.e.newdao.top:443/xxx/xxx.git 3、再重新连接本地ide
应用初始化失败,错误编码:1
首先看看logs下有没有错误日志
如果没有错误日志,则使用win的命令查看 9001 端口是否被占用
netstat -aon|findstr 9001(查看进程号是多少)
taskkill /F /PID [pid]
如果被占用,杀死该进程
修改9001端口的处理
https://docs.i.newdao.top/devadv/error-handle/local-ide-9001.html
1000x:10003、10009错误
重启应用试试
使用idea
参考材料
本地ide包下的doc/FAQ.pdf相关章节
idea
放入idea,重命名为ideaIU
修改bin\idea.properties
maven配置
User settings file
设置为:tools/mavan/conf/settings.xml
Local repository
设置为:tools/maven/repo
不设置这里的话,会找不到pom依赖那些jar
ant配置
view->Tools Windows,勾选ant
编译日志:在Messages窗口
tomcat配置
要引入ROOT和x5
使用debug模式启动,可进入断点
jdk配置
使用java\jdk8
如果代码正常但编辑器提示找不到类
写新代码后重新编译
事务
分布式事务
帮助文档:https://docs.i.newdao.top/default.html?token=eyJ0b2tlbiI6IjE1MzYxNTYzMDQyMzQxOTY5OTQiLCJobWFjIjoi01x1MDAxZkRzXHUwMDdm1Fx1MDAxYoR3%2BqcmXHUwMDEyWaW%2BOXk3ziIsInVzZXJuYW1lIjoidDE4MTg3NTE4MjY4IiwiZXhwaXJlc19pbiI6MzMxMDIwOTU1NSwidXNlcmlkIjoiblFGSjlYVzMzN1d3Qm4wNHQ1OSIsImV4cGlyZSI6MTY1NTEyNjM3OH0%3D
前端批请求
把多个请求包装成1个请求进行处理,事务一定是在1个请求中来保证的
跨租户
数据集查询
高级->资源管理->租户内跨应用调服务、数据,进行设置需要关联的其他应用的数据集
页面上放置多个数据集之后,原表的“表”设置“数据集参数”,添加“输出数据集”
门户
定制门户
登录页
登录页:model\UI2\pc\userDialog\login.w(可定制的继承子页面) 旧版门户 UI2/system/components/justep/user/userDialog/login.w 新版门户 UI2/system/components/justep/user/userDialog/login2.w
首页
门户首页:model\UI2\pc\index.w(可定制的继承子页面) 旧版门户 UI2/pc/base/baseIndex.w 新版门户 UI2/pc/base/baseIndex2.w
功能树配置
注册的新服务的功能菜单显示在门户菜单上:如果修改过配置,后边注册的服务,需要手动添加到功能树当中
恢复原来自动添加菜单树的功能
门户数据库,找到 manager_caidangl 表,删除里边的那条记录
widget添加要放置的页面
页面的配置,勾选“PC首页内容块”
如果需要去除首页上的某个widget,点击右上角登录用户名字,选择“首页定制”,再在某个widget点击x
门户地址
桌面端: https://entrygznftz6-vip.e.newdao.top/entry/pcapp 移动端: https://entrygznftz6-vip.e.newdao.top/entry/mobileapp
问题
获取注册密码失败
刷新一下页面再获取
菜单使用新页打开
报编译错误之类的问题
1、强刷页面;
2、更新应用的组件重新发布一下;
获取当前登录能访问的菜单树
https://门户域名/entry/manager/authorized/menus?types=pc&types=func&context=pc&modified=true
报表
帮助文档
低代码PaaS平台用户开发手册-报表专题.pdf
在线手册:“中台服务”
先在租户中添加“企业报表”和“报表案例”2个应用,再在门户进行服务注册
组件市场下载“PCX报表设计组件”/“报表设计组件”
PCX报表:新建页面要使用“空白页面-uix“模板页面来做
报表设计使用虚机访问,否则比较卡
group/select
分组使用group,后接的字段需要先用1个select,再后边的字段就不需要写select
主从报表
帮助手册:https://docs.i.newdao.top/devreport/report-demo.html
注意事项
删除数据集的主从设置
合并单元格,需要设置行列设置的“折叠 collapse”为true
从表的过滤条件,子表的外键需要加ID字符串
订单从表.订单主表ID=订单主表.主键
$PRxCx:第几行第几列,如第4行第5列位 $PR4C5
消息中心
消息通知
需要添加“消息中心”、“事件中心”这2个应用,事件中心添加时需要注意是否有redis实例,没有的话新建几个redis实例进行使用。事件中心添加应用后,需要先绑定某个redis实例,才能在服务注册中注册上去(如果绑定redis不成功,则服务注册不上)。
模板要选择 redis 模板
新建时租户选择 redis
事件中心可以不使用kube部署
事件中心注册后,需要重启应用
配置
邮箱
SMTP服务地址:
SMTP服务端口:
SMTP登录用户:
SMTP登录密码:
是否使用SSL
测试发送消息
邮件
消息参数:{"title":"测试邮件"}
接收者:选择一个设置了邮箱的门户用户
发送方式:邮件
消息模板:可以选择默认的“任务管理”(只有一个参数 title)
消息类型
portal
dingtalk
wx
sms
js代码设置全局变量
流程启动前: onWfmuiStartBefore(event/*{{{*/=this._e.wfmui_startBefore/*}}}*/){ event.options.vars.messageChannel = this.comp("mainData").getValue("noticeType"); }
备份代码【不生效】: // 流程启动后,设置消息通道全局变量 // let wfComp = this.comp("wfmui"); // let taskId = wfComp.getTask(); // let vars = { // "messageChannel": this.comp("mainData").getValue("noticeType") // } // wfComp.updateFlowVars(taskId, vars);
注意:某个环节中的变量“消息发送方式”不要有值,否则会被覆盖
流程环节的流转发送消息
参考:https://docs.i.newdao.top/devflow/design-flow/designprocessmsg.html
流程的高级设置
可配置消息模板,默认不配置使用 TASK_MANAGE
环节的高级设置
设置“消息发送方式”
环节处理人在钉钉、企业微信、短信、邮箱的工作通知中接收到消息提示,点击消息可以进入查看和处理功能
问题
阿里云提示:Specified signature is not matched with our calculation
检查Access Key Secret是否正确?
其他问题:
https://help.aliyun.com/document_detail/39992.html
本地系统时钟是否正确,因为签名的计算会带时间戳,如果时钟不对可能会导致签名失败 。
Timestamp=2022-11-16T02%3A58%3A22,真实时间是10:58:22,晚了8个小时
短信发送失败
提示:错误:该账号下找不到对应模板,错误编码:isv.SMS_TEMPLATE_ILLEGAL
消息模板中要设置“短信模板”为 TASK_MESSAGE
工作流没有发送消息
查看工作流日志中是否有sendmessage日志?如果没有,重启工作流
发送消息失败
事件中心这个应用是后加的,加了之后工作流应用没有重启导致工作流应用中没有找到事件中心
com.justep.cloud.event.client.EventBridgeApiException: Server returned HTTP response code: 502 for URL: http://eventing.newdao-tenant-sdyd/eventBridge/sendText
在事件中心的 java-runtime 容器里执行:curl http://eventing.newdao-tenant-sdyd/eventBridge/sendText
如果提示未响应,说明 java 的服务不在,可以 netstat -ntlp 看看 8081 端口在不在,不在的话,说明服务没启动
问题:可能连接数据库失败造成的启动异常 解决:重启事件中心
如果平台自动分配不了redis实例,可以手动修改事件中心的“环境设置”,手动配置redis的连接
redis的连接,可以在平台的中间件管理redis中随便找一个别人redis的连接
比如: host:redissvcyrykk23-simpleredis-service.newdao-tenant-redis port:6379 密码:!Mg5anxB
移动端
优先级
如果出现按钮浮在其他组件上边的情况,可以设置组件的优先级为1,让组件的优先级大于按钮的优先级,就可以挡住按钮
架构
添加新的模块
架构->市场添加“服务模板”(比如取名叫mainx)->拖到架构图中->返回高级菜单->多模块多端配置->新增子项目,服务标识比如叫mainx
左上角有个按钮可以更新组件
市场
应用市场
运行模板(含运行文件、代码资源、流程定义)
deploy:运行文件
jarslink:main目录打包成main.jar
ide:代码资源
opencart:市场属性配置
模板市场
开发模板(只含代码资源)
Model目录
某些微服务看不到
先去system更新审核那边看看有没有正在审核的
微服务治理
两层架构
外部:服务网关(Kong API Gateway)
安全验证、流量限制、黑白名单配置
内部:代理网关(Kong)
网关设置
企业应用->xx应用->更多->网关
门户session有效期设置
企业门户->更多->网关->权限验证->设置插件参数->有效期
运维
Kube控制面板
命名空间
newdao-console
console-cleaner可以手动触发执行,避免删除应用后,同一个标识在10分钟之内不能重复新建的问题
newdao-tenant-客户名字
Cron Jobs
这里可以看到该客户下的所有cron job
app-init
查看pod的日志
忽略错误继续执行 服务初始化执行异常 ****ERROR****: 初始化通知执行异常 初始化执行异常,容器重启... ****ERROR****: 1
查看pod的描述
kubectl describe pod fileviewdevelop7-deployment-6649c98796-vtdkn -n newdao-tenant-develop
app-init 显示 Restart Count: 3
app-init 老是重启,可能有 bug,需要更新 app-init。
平台访问不了
查看pool等节点是否有异常
平台访问不了,可以使用老控制台访问,console.xxx
如果pool节点只有一台,卡住了,其他pool节点恢复后,可以进行智能重建,让pod飘到其他pool节点上
在开发应用里边,组件下载一直转圈,下载不了
newdao-console查看cnpm服务的日志是否正常?
删除这个pod,让它重启
重启那个应用进来再试一下
用户使用日志
1、设置门户的网关插件
企业门户->更多->网关
选择“所有应用/服务”
access_log 开启
日志接收服务地址:http://entry.newdao-tenant-xxxx/logging/fangwenrz/jieshousj
xxxx 修改为租户标识,比如 dfgx
回到服务列表,点击“更新网关插件”
2、门户的“使用用户情况”查看日志
修改Tomcat中日志的等级
修改entry的java-runtime的日志输出级别 vi /dist/java-runtime/dist/comp.DBProxy/conf/logback.xml 把warn改为info,然后30秒后起作用
本地ide编译
页面制作工作台
使用 apache-tomcat-8.5\webapps-system\x5 这个应用来开发
前端页面访问
页面预览的访问流程
https://entryshkc4-vip26064513.e.newdao.top/entry/pcapp/v_/pc/index.w#!(/poccase/mobileapp/mobile/geren_zxbg.w)
实际请求: https://entryshkc4-vip26064513.e.newdao.top/poccase/pcxapp/pages/__pages_pcx_geren_zxbg_component_js.js?modelId=./pages/pcx/geren_zxbg.component.js&modelName=__pages_pcx_geren_zxbg_component_js
pcxapp意思是访问pcx端
访问的页面地址为:modelId=./pages/pcx/geren_zxbg.component.js
geren_zxbg.component.js 对应 geren_zxbg.w 编译后的 react 文件(第一次编译)
使用 esbuild bundle 对 .w react 文件和其对应的 .js/.css 再次编译打包(第二次编译)成浏览器能识别的 js 文件(文件保存在缓存中,没有生成物理文件),返回给浏览器进行显示
如果使用发布打包,会将.w/.js/.css 打包成1个类似 __pages_pcx_geren_zxbg_component_js_354f02aedda0a718e7c0.js 文件
后端服务访问
模块编译后模块下的 target 目录下,比如 main.jar(同时 work\jarslink 目录中有相应的软链接,比如 main\main.jar)
apache-tomcat-8.5 上下文配置指向 apache-tomcat-8.5\conf\Catalina\localhost
ROOT.xml
eclipse-workspace-template\ROOT 是一个 java web 项目,里边有业务代码会加载 work\jarslink 里边的 jar,从而运行相关服务模块
前端编译
.html文件会被编译,编译出错会过不去。所以一般html不会编译复制过去。
把文件修改为.htm结尾,绕过这个编译
发送消息提醒
门户收到消息提醒
帮助手册:开发手册->基础篇->接收通知
发送消息接口
帮助手册:开发手册->高级篇->消息发送接口
第三方插件
数据同步
应用添加“数据同步平台”
DataX Web
1、配置数据源
2、DataX任务模板,设置同步周期
3、项目管理
4、任务构建
5、任务管理
数据可视化
应用添加“数据可视化部署”
Davinci
使用顺序:数据源(Source)——>数据视图(View)——>可视化组件(Widget)——>仪表板(Dashboard)
配置数据源
可手工配置,或者从门户同步设置过来(注意要使用对的数据源(租户会数据隔离))
分享链接
需要使用门户访问(可能存在访问权限问题)
页面代码:
js代码:onPageLoaded(event/*{{{*/=this._e.page_loaded/*}}}*/){ let url = "/davinci/davinci/share_eNoNzbcNwEAMwMCVFF6pVNx_JLslDqBMpXmiLRdzvITotFIIXJl9xcgNicqy6ujqtiKIKMGVHGlAv1lMpxsF09Zhq34jRCZ_9aHHwZvVOaeIkKW3XnO1zm3YcQm1sryiywGWE8ZBnLf0_-9ebbBSdv-qtEkIeug-W_grxQ.html?placeholder=value#/share/dashboard"; let iframe = this.owner.reactRefs["iframe-page1"].current; iframe.src = url; }
定时任务
需要调用的服务必须先进行应用发布,否则看不到该服务
添加kube集群
使用system登录后台,找到相应租户,点击“维护部署集群”->点击“添加租户私有kube集群”->配置参考redis租户的redis集群配置->名称设置为“定时”
参考redis配置
集群URL配置为:local
镜像仓库地址:hub.newdao.com,勾选https
镜像仓库登录用户名:admin
镜像仓库登录密码:Local#Repo1@Nexus(原admin123)
镜像拉取密钥:hub.newdao.com
添加应用
使用租户管理员登录后台->应用/服务管理->添加应用->添加“定时管理”(使用共享企业集群)和“定时任务”(使用定时集群)两个应用->门户服务注册
使用
访问正式门户,点击“定时管理”->“定时任务列表”->点击默认模板的“新建”操作->配置登录方式(选择token登录或者用户名密码登录),token获取方式:用system登录正式门户后,执行https://xxx/entry/uaa/userinfo?type=token
可以测试 entry 的 hello 接口
定时任务调用控制台日志查看
system登录后台->资源管理->池管理->生产池->WEX5_PROD详情->找到我们应用名称的池,点击详细->进入pods后,再点击详细->在进入的k8s页面,查看tomcat容器的日志
错误
查看某个应用的服务接口一直请求不成功
先看这个应用是否发布成功?
调用的是这个接口,是否正常?https://entryfxfdev6-vip.e.newdao.top/basiccasetest/meta/all?rest=true
2023-01-12 09:49:11.464 WARN [ catalina-exec-9]: Sysadmin kube api 检查错误 main.cronjob.CronjobServiceFactory java.lang.RuntimeException: 未定义环境变量: NAMESPACE at main.cronjob.SysadminCronjobService.getNamespaceAndHost(SysadminCronjobService.java:27)
Failed to pull image "hub.newdao.local:8082/justep/java-runtime:8-jre": rpc error: code = Unknown desc = Error response from daemon: manifest for hub.newdao.local:8082/justep/java-runtime:8-jre not found: manifest unknown: manifest unknown
找袁云昌处理
echart图表
先添加echart图表组件
数据集只能使用动态数据集,自定义和静态数据集使用有问题
隐藏后恢复显示尺寸不对的问题
onSelect0Valuechange(event/*{{{*/=this._e.Select_valuechange/*}}}*/){ this.allChartResize(); } allChartResize() { let self = this; let chartIds = ["chart0", "chart1", "chart2", "chart3"]; chartIds.forEach(function (id) { self.chartResize(id); }); } chartResize(chartId) { let chartComp = this.comp(chartId); if (chartComp) { setTimeout(function() { chartComp.echartsInstance.resize(); }, 10); } }
图表上下空白太多
"grid": { "x": 50, "y": 25, "x2": 30, "y2": 35 }
显示图片下载
"toolbox": { "show": true, "feature": { "saveAsImage": {} } }
折线/柱状切换
https://blog.csdn.net/weixin_42870683/article/details/103527376
"toolbox": { "show": true, "feature": { "magicType": { "show": true, "type": [ "line", "bar" ], "title": { "line": "折线图", "bar": "柱状图" } } } }
图例位置
legend: { orient: 'vertical',//可设定图例水平(horizontal)排列还是竖直排列 x:'right', //可设定图例在左、右、居中 y:'center', //可设定图例在上、下、居中 padding:[0,50,0,0], //可设定图例[距上方距离,距右方距离,距下方距离,距左方距离] data: ['',','','',''] }
图表
图表的配置可参考官网的选项进行配置
https://echarts.apache.org/zh/option.html
图表设置->option->放json
应用初始化
分配新的开发者(外部人员)
添加用户:system账号登录->系统管理->组织权限管理->外部用户管理->添加成员->输入真实手机号,用户名自动生成t+手机号->使用用户名或手机号登录
团队加入:租户账号登录->我的团队->管理->输入用户名,邀请成员
应用加入:租户账号登录->我的开发->企业应用->选中其中1个应用,鼠标悬浮选中“团队”->添加成员,选择新建的那个用户
新开发者的git账号:新开发者账号登录->集成工具->账号配置->Git账号(显示密码);集成工具->Git(访问gitlab后台)
使用某个租户组织下的用户作为开发者
https://docs.i.newdao.top/tenantdev/addeveloper.html
手机验证码那块随便添一个
这种方式添加的开发者
外部用户那边会自动同步一个手机号的开发者,需要后续用那个手机号进行登录
开发者默认会进入到当前租户组织,当前没有开发权限,需要使用租户管理员,在我的团队里边设置一下这个开发者为租户管理员,再切换设置为开发者
多端切换
新移动端
高级->多模块多端配置
添加子项目
界面端标识输入:xxx-mobile
设备类型选择:移动
组件市场添加vantui库:添加后,可能在页面左侧还看不到基本的一些组件,需要添加vantui组件
小程序端
界面端标识输入:wx
设备类型选择:小程序
服务注册
外部服务注册
其他租户的门户服务注册会失败?
可以注册其他租户的某个微服务
服务注册失败,新菜单显示不出来
应用发布后,可能会出现服务注册失败的异常
可以在门户的服务注册中,找到那个应用,先删除这次的服务注册,重新注册。此时注意看提示是否这个应用注册失败
服务注册失败的具体日志,可以在门户的“监控”->tomcat容器->查看日志
服务注册失败较多的问题为:xxx 权限未定义
原因:可能是菜单权限之类的被修改过,但角色还是关联之前的旧权限,造成权限找不到
解决方案:
1、在应用开发那里的角色权限,点开每个角色,先取消相关联的权限,点击确定;再重新进入,关联权限,再点击确定;让角色重新绑定最新权限;
2、修改后,再次进行应用的发布;再在门户的服务注册查看是否服务注册失败。
访问第三方网站(比如 sina)
测试:https://frontcaseanli4-anli-ide.e.newdao.top/sina
参考材料:https://docs.i.newdao.top/devsvc/reggateway.html
在应用的 model/service 下新建一个文件夹(名称随意)
新建一个 app.m
<?xml version="1.0" encoding="UTF-8" ?> <service> <name>sina</name> <request_path>/sina</request_path> <preserve_host>false</preserve_host> <strip_request_path>true</strip_request_path> <upstream_url>https://www.sina.com.cn/ </upstream_url> </service>
注意: <preserve_host>false</preserve_host>,否则会出现 403 异常
重启应用
访问路径:https://xxx/sina
POC
新建租户
分配客户相关的机构、部门、岗位和人员等基础信息
问题bug
流程
更多->流程记录->标题错误“流程刻录”
疑问
数据库
如何用本地数据库客户端连接项目的数据库?
应用/服务管理->资源(内网地址)
PCX报表组件
预览会一直显示加载中,显示不了?
新建页面要使用uix模板页面来做
本地IDE
点击“云端连接”会提示连接异常
可能是网络连接问题,使用内网的虚拟机解决
级联选择
如何配置?
数据同步
应用角色配置了权限,但是用户还是不显示该菜单
数据同步不成功
要选对对应的用户,不同用户的数据内容不一样
数据可视化
应用角色配置了权限,但是用户还是不显示该菜单
自定义数据
流程
审批签字在哪里查看?
系统异常
请求url出现503错误
使用system登录->资源管理->池管理->找到WEX5_IDE,点击”详细“->找到自己的应用->点击”解绑“->等待一会,该资源会被释放->再回去应用,打开应用重新申请新的资源
开发者加入应用后,打开应用提示406/501配置错误
开发者账号不能使用大写字母
开发者账号不能使用中文
数据加载失败,Cannot get database connection info
model\service\main目录下多了一个bin目录(不清楚是不是您那边eclipse编译环境生成的?),这个目录是不需要的,在本地删除后就正常了
数据加载失败,Table xxx doesn't exist
1、一般是由于先有数据库的表,再反向生成数据模型,然后修改过一些配置造成同步物理数据库异常造成的
2、可能是由于多个开发者,使用不同的数据库造成的(平台做了资源隔离,同一个应用,不同开发者使用的是不一样的数据库)
如果开发者A在自己数据库导入了一些表,反向生成了数据模型;开发者B的数据库因为没有这些表,会造成访问不到表的异常;
解决方式:1、开发者B把sql也导入进来;2、应用的数据库连接,修改指向外部的同一个第三方数据库,或者开发者A的数据库;
pod绑定不了
查看开发或者运行池是否满了
开发池:在redis中查看是否有该条记录,比如要打开的应用为flowseniorcaseanli4-anli-ide.e.newdao.top;如果存在且值为1,先删除该条记录,再重新绑定试试。
问题处理:https://docs.i.newdao.top/devadv/error-handle/ide-not-open.html
方式三: 进入redis,删除redis记录信息
pod启动不了,一直在绑定下一个pod
查看pod各个容器是否有报错
migration容器报错
Caused by: java.sql.BatchUpdateException: Duplicate entry 'CA15F0900B40000166E31F701DE0AD20\1' for key 'PRIMARY'
创建orgs表失败 java.lang.RuntimeException: java.sql.SQLException: 8
使用root账号的问题,使用普通账号
create user 'uhpc66np_586'@'%' identified by 'uhpc7711_585'; grant all privileges on 20230223131103w26gfmnm.* to 'uhpc66np_586'@'%'; FLUSH PRIVILEGES;
kong112/mb问题
使用开发者发布应用,发布的应用名称会固定取模板的名字,造成发布的名称和原应用名称不一致,导致发布后访问不了
找控制台数据库
全部命名空间->console deploy->pod
找到tenant表
正在保存中,请稍等...
先等待一下(1-2分钟),如果还未保存成功,重启应用
创建门户应用没反应
刷新一下页面再重新试一下
MySQL
关键词
leave
device
alert
index
遇到关键词的时候,在单词后边加1个s
异常
is blocked because of many connection errors; unblock with 'mysqladmin flush-ho
max_connect_errors参数: https://developer.aliyun.com/article/758964
【数据库----MySQL】连接错误过多: https://blog.csdn.net/ningjiebing/article/details/102408136
数据库
SQL Server
uniqueidentifier 必须为 36 位
MySQL
关键词
leave
device
alert
遇到关键词的时候,在单词后边加1个s
App打包
安卓apk打包
打包后会放在代码的Native目录下(Native->mobileapp->dist->app.apk)
找到apk,复制一下到UI2某个目录下
切换本地ide,把apk文件下载下来
引入第三方库
问题
The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script
import Highcharts from 'https://code.highcharts.com/es-modules/masters/highcharts.src.js';
引入module
js引入: import '$UI/pcx/lib/__module'; __module.js文件的内容: export default {};
引入json
import hunanData from '../json/hunan.json';
import引用模块
先定义模块
utils.js
export函数
export function packageVal(content) {}
使用方import模块
import * as utils from "../utils";
调用函数
utils.packageVal(xxx)
license
过期
打开应用会打不开,提示:/x5/UI2/v_23787l_zh_CNs_newdaod_pc/system/designer/webIde/service/IDEService.j?action=dataModelCheck&name=c1 HTTP status: 502
跟进问题
1、应用的pod启动正常
2、打开pod的tomcat容器,会提示:uixweb: failed [-32500: Application Error: fail to find process uixweb]
3、打开http://console.xxx.xxx,登录账号是system,找到系统设置->license注册,查看是否到期
license更新
要更新2个license
更新后,找到开发池和生产池,分别点击“智能重建”按钮
永久模式
licenseserver永久模式就是这样的,会自动一直续期的,上面提示的可在licenseserver机器上查看 cd /usr/local/bin/license-server/license/bin ./view.sh 可查看当前注册信息
Spring Boot 应用
结构
前端
静态文件路径:/dist/comp.nginx-runtime/dist/pcxapp
nginx 配置文件:/etc/nginx/conf.d/modules/pcxapp.module.conf
location /pcxapp { absolute_redirect off; alias /dist/comp.nginx-runtime/dist/pcxapp/; index index.html index.htm; try_files $uri $uri/ /pcxapp/index.html; }
后端
java -Dfile.encoding=UTF-8 -Dserver.port=8081 -Dloader.path=/dist/java-runtime/dist/main/lib,/usr/local/x5/lib -jar /dist/java-runtime/dist/main/main.jar
本地ide调试
需要找到 MainSpringBootApplication 类,debug 模式运行 main 方法,才能进入断点
页面访问
脱离门户访问
没有菜单
需要自己做一个菜单页面
openUrl(wpath) { let url = this.getUIUrl(wpath); url = url.replace("pcx/", "#/pcx/"); console.log(url); if (!url.includes("pcxapp")) { url = "/pcxapp" + url; console.log(url); } window.open(url, "_blank"); } onButton0Click(event/*{{{*/=this._e.Button_onClick/*}}}*/){ this.openUrl("$UI/pcx/shebei_jk.w"); }
访问链接样式:https://springbootcaseanli4-vip.e.newdao.top/pcxapp/#/pcx/kehu_gl
需要依赖dbrest服务
否则数据库操作执行不了
环境变量设置
env.sh
dbrest 服务
数据库设置:export DB_CONN_URL_main=修改为实际的
main 服务
数据库设置
行 64: export MAIN_DBPROPERTIES='' 行 89: export MAIN_DBUSER='root' 行 105: export MAIN_DBSCHEMA='smartelectricroom' 行 130: export MAIN_DBHOST='localhost' 行 196: export MAIN_DBTYPE='mysql' 行 243: export MAIN_DBNAME='smartelectricroom' 行 250: export MAIN_DBPASSWD='abc@123' 行 252: export MAIN_DBPORT='3306'
源代码路径
需要定位 data.m 文件
export JUSTEP_HOME='D:\demo\DSADemo'
nginx 配置
location /pcxapp { absolute_redirect off; alias pcxapp/; index index.html index.htm; try_files $uri $uri/ /pcxapp/index.html; } location /main/dbrest { proxy_pass http://localhost:8081/dbrest; proxy_set_header X-MODULE main; } location ^~ /main/ { proxy_pass http://localhost:8081/main/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass_header Server; proxy_set_header Host $host; }
ftp 从 pod 下载依赖包
2块依赖包:1、x5 lib;2、应用的 lib;
参考 pod 执行命令:java -Dfile.encoding=UTF-8 -Dserver.port=8081 -Dloader.path=/dist/java-runtime/dist/main/lib,/usr/local/x5/lib -jar /dist/java-runtime/dist/main/main.jar
下载命令
tar -zcf lib.tar.gz lib
curl -T lib.tar.gz ftp://x5:x54321@192.168.0.3/temp/fxf/
启动
source env.sh java -Dfile.encoding=UTF-8 -Dserver.port=8081 -Dloader.path=lib,x5lib -jar main.jar
nexus下载发布后的包
https://nexus.i.newdao.top/
Browse -> maven releases -> 找租户,再找项目。项目里边 main 是服务端的包,pcxapp 是前端页面的包 -> 点击要下载的包,右侧弹出下载地址
spring迁移springboot项目
前端
页面的.w/.js/.css都复制过去
后端
数据模型data.m和服务模型service.m复制过去
点开每个数据模型,“重新生成”物理数据库表
导入原来数据库的sql(含数据)
点击每个服务模型,重新生成服务端代码
把原来接口代码复制过去
把原来的mapperPlus改成项目自动生成的mapper(变成mapplerPlus了)
编译操作
前端编译
编译脚本:newdao-ide-windows\tools\uix-web\scripts\ExportServer.js
需要在trunk2环境,39版本的top环境没有这个功能
node 版本要求:v12.xx
1、设置源码路径:UI2/pcx/config/application.xml
在app节点下添加配置: <export-path>../src</export-path>
2、生成源码
刷新ide页面,在设计器工具栏上点击“生成页面源码”按钮(默认不出现,设置配置后出现)生成页面源码,pcx目录下看到src目录
1和2步骤,在40版本的springboot模板已经自动配置了,不需要手动配置
3、源码提交git
4、执行构建
先设置 JUSTEP_HOME 环境变量
export JUSTEP_HOME='D:/demo/DSADemo/newdao-ide-windows'
执行脚本
进入 $JUSTEP_HOME/tools/uix-web/ 目录: cd $JUSTEP_HOME/tools/uix-web/
【如果没有 node_modules】下载 node_modules: npm --registry https://registry.npm.taobao.org install
进入 $JUSTEP_HOME/tools/uix-web/scripts/ 目录: cd $JUSTEP_HOME/tools/uix-web/scripts/
不进入会提示 main-ent.js 找不到
node $JUSTEP_HOME/tools/uix-web/scripts/ExportServer.js pcx release --release
其中pcx是端的名字,即UI2下的pcx目录名字
执行后 src/public 目录下的文件即为所有前端发布资源
5、中间件运行
nginx
放到 nginx 根目录下,把 public 文件夹修改名称为 pcxapp
配置: location /pcxapp { absolute_redirect off; alias pcxapp/; index index.html index.htm; try_files $uri $uri/ /pcxapp/index.html; }
tomcat
打 war 包
cd public jar -cvf pcxapp.war .
把 war 包放到 webapps 下
注意:如果前端依赖 dbrest 和自己的服务接口,还需要进行转发配置,建议使用 nginx
问题
40版本已解决
src 下的忽略文件 .gitignore
需要去掉 components 和 routes.js
原始文件:tools\uix-web\scripts\exportConfig\.gitignore
src 下的忽略文件 .gitignore
需要去掉 node_modules 和 package.json
后端编译
源码部分
40版本的模板已解决
引用 mavenInstall 组件
去除 gen-java 的忽略
model 目录打开 .gitignore,删除 **/gen-java/
去除 gen-java 的忽略
model 目录打开 .gitignore,删除
/service/*/openapi/ /service/comp/*/openapi/
前提
jdk 使用 1.8 版本
mvn 能正常运行。可以使用编译工作环境自带的 maven
需配置到系统的环境变量,后续需使用命令mvn
导入mysql数据库sql(创建数据库名smartelectricroom,并导入表结构和表数据)
要去对应分支环境的本地ide下载最新的4个zip包
比如:\\192.168.0.3\产品发布\Newdao\branchG\local-ide
maven-justep.zip
少了kingbase8-8.6.0.jar,从本地ide的tools复制过去
model-system.service.zip
meta目录少了一个meta.jar(meta/assembly/lib),从本地ide的lib复制过去
dbrest目录少了一个dbrest.jar(dbrest/assembly/lib),从本地ide的lib复制过去
excel目录少了一个excel.jar(excel/assembly/lib),从本地ide的lib复制过去
storage目录少了一个storage.jar(storage/assembly/lib),从本地ide的lib复制过去
lib-default.zip
这2个包解压到 x5/lib 下,先复制default,再复制system
lib-system.zip
编译过程
40版本需要调整
修改 mvn 配置文件
<localRepository>D:/demo/DSADemo/server-build/maven/apache-maven-3.8.7/repo</localRepository>
export COMPILE_HOME=D:/demo/DSADemo/server-build export JUSTEP_HOME=$COMPILE_HOME/x5 export MVN_HOME=$COMPILE_HOME/maven/apache-maven-3.8.7 export PATH=$MVN_HOME/bin:$PATH
mkdir -p $MVN_HOME/repo cp $COMPILE_HOME/resource/maven-justep.zip $MVN_HOME/repo cd $MVN_HOME/repo && unzip maven-justep.zip && rm -f maven-justep.zip
cp $COMPILE_HOME/resource/smartelectricroom.zip $JUSTEP_HOME/model cd $JUSTEP_HOME/model && unzip smartelectricroom.zip && rm -f smartelectricroom.zip
cp $COMPILE_HOME/resource/model-system.service.zip $JUSTEP_HOME/model/service cd $JUSTEP_HOME/model/service && unzip model-system.service.zip && rm -f model-system.service.zip
bash $JUSTEP_HOME/model/service/comp/mavenInstall/deploy/install_local.sh
cd $JUSTEP_HOME/model/service/main mvn clean package
运行
40版本需要调整
export COMPILE_HOME=D:/demo/DSADemo/server-build export JUSTEP_HOME=$COMPILE_HOME/x5 export loaderPath=$JUSTEP_HOME/model/service/main/target/lib export loaderSysPath=$JUSTEP_HOME/lib export MAIN_DBPROPERTIES='' export MAIN_DBUSER='root' export MAIN_DBSCHEMA='smartelectricroom' export MAIN_DBHOST='localhost' export MAIN_DBTYPE='mysql' export MAIN_DBNAME='smartelectricroom' export MAIN_DBPASSWD='abc@123' export MAIN_DBPORT='3306' export DB_CONN_URL_main='jdbc:mysql://localhost:3306/smartelectricroom?user=root&useInformationSchema=true&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8'
java -Dfile.encoding=UTF-8 -Dserver.port=8081 -Dloader.path=$loaderPath,$loaderSysPath -jar $JUSTEP_HOME/model/service/main/target/main.jar
测试接口
curl -i http://localhost:8081/main/alert/collectdataalert curl -i -H "X-MODULE: main" -H "dbrest-resource: class" http://localhost:8081/dbrest/alertType?limit=20
问题
2023-01-10 10:42:35.404 http-nio-8081-exec-1 ERROR druid.sql.Statement Line:149 {conn-110001, pstmt-120000} execute error. SELECT COUNT(*) AS CNT FROM devices 2023-01-10T10:42:35.406040130Z java.sql.SQLSyntaxErrorException: Table 'smartelectricroom.devices' doesn't exist
需要找data.m文件,不能删除源码文件
java.lang.NoClassDefFoundError: com/justep/util/db/JDBCUrl
server-build\x5\lib需要放置一个最新的utils-1.0.1.jar
自定义域名
帮助手册:https://docs.i.newdao.top/tenantdev/cusdomainaccess.html
平台功能开发
数据模型引用
设计时
运行时
数据相关meta
https://rulemodelcaseanli4-anli-ide.e.newdao.top/meta/data
所有meta
https://rulemodelcaseanli4-anli-ide.e.newdao.top/meta/all
访问门户上的应用
https://entryanli4-vip.e.newdao.top/flowseniorcase/meta/data
注册在门户的微服务列表
https://entryanli4-vip.e.newdao.top/entry/manager/services/route
git
配置外部git
http://docs.trunk2.xcaas.com/devbase/common-func/external-git.html
修改clone的域名地址
newdao-console->Deployments->gitlab-deploy->修改YAML->修改gitlab-svc.newdao-console
修改后,将gitlab-deploy缩放为0,再缩放为1
应用创建后的git地址
https://anli:sbs-8yxVoNSzKxq1Le8b@git.e.newdao.top:443/anlizhizuozuhuzuzhi/pluginpublishanli4.git
https://plugin:dNzjaa8tX921nq8CL5x_@git.e.newdao.top:443/chajianzuhuzuzhi/entryplugin6.git
那串乱码为git账号的token
地图
id冲突
地图div的id不要使用container
不使用门户预览的时候,会出现id冲突的问题
高德地图
引入 1.4.x 版本
let url = 'https://webapi.amap.com/maps?v=1.4.15&key=2a25c002bb67874654f9d77587a5e168&callback=onLoad'; let jsapi = document.createElement('script'); jsapi.charset = 'utf-8'; jsapi.src = url; document.head.appendChild(jsapi);
切换普通地图和卫星图
map.setLayers([new AMap.TileLayer.Satellite(), new AMap.TileLayer.RoadNet()]);
map.setLayers([new AMap.TileLayer()]);
根据地址获取经纬度
https://restapi.amap.com/v3/geocode/geo?address=%E5%9B%BD%E7%BD%91%E8%8D%86%E5%B7%9E%E4%BE%9B%E7%94%B5%E5%85%AC%E5%8F%B8&key=53a5622536c2b170b00b98468650af3d
key需要单独新建应用
从起点到终点导航
// callnative=1表示自动调起本地app进行导航 https://uri.amap.com/navigation?from=&to=112.297718,30.294875,湖北省荆州市沙市区荆州供电公司&callnative=1
第三方图表
highcharts
引入其他modules
import Highcharts from './lib/highcharts'; import HighchartsBullet from './lib/bullet'; HighchartsBullet(Highcharts);
yAxis样式
Highcharts.chart('maplegend', { yAxis: { plotBands: plotBands, labels: { style: { color: '#000' } }, title: null, tickPositions: tickPositions, tickColor: '#FFFFFF', height: "12px" }, series: [{ data: [{ y: 0, target: tickPositions[tickPositions.length - 1] }] }] });
g2plot
import xxx from "../lib/g2plot"
更新数据:barPlot.changeData(barData);
迷你面积图配置
https://g2plot.antv.antgroup.com/api/plots/tiny-area
曲线颜色: line: { "color": "white" }
迷你圆环图配置
const ringProgress = new RingProgress('ringProgressDiv', { autoFit: true, percent: percent, color: ['#6bf6ba', '#E8EDF3'], innerRadius: 0.85, radius: 0.98, statistic: { title: { style: { color: '#6bf6ba', fontSize: '0.7vw' }, formatter: () => '在线率', }, content: { style: { color: '#6bf6ba', fontSize: '0.7vw', fontStyle: 'italic', fontWeight: 'bold' }, } }, }); ringProgress.render();
配置圆环大小:innerRadius: 0.5
echarts
参考
https://www.isqqw.com/ref/docs/echarts.html
引入
import * as echarts from '../lib/echarts';
点击事件
// 点击事件 myChart.on('click', function (params) { console.log(params); // 打开对话框页面 self.comp("projectdialog").open({ "area": params.name }); });
样式
{ "xAxis": { "type": "category", "splitLine": { "show": false }, "axisTick": { "show": false }, "axisLine": { "show": false } }, "legend": { "show": false }, "tooltip": {}, "yAxis": { "type": "value", "axisLabel": { "textStyle": { "color": "#666" } }, "nameTextStyle": { "color": "#666", "fontSize": 12, "lineHeight": 40 }, "splitLine": { "lineStyle": { "type": "dashed", "color": "#E9E9E9" } }, "axisLine": { "show": false }, "axisTick": { "show": false } }, "series": [ { "type": "line", "smooth": true, "symbolSize": 8, "zlevel": 3, "lineStyle": { "normal": { "color": "#0090FF", "shadowBlur": 3, "shadowColor": "#0090FF", "shadowOffsetY": 8 } }, "areaStyle": { "normal": { "color": "rgba(220,241,255, 0.3)", "shadowColor": "#0090FF", "shadowBlur": 10 } } } ], "grid": { "x": 50, "y": 25, "x2": 30, "y2": 35 } }
data.m
主键只能一个(不能多主键),并且不能没有主键
设置一个字段:primary="true"
多主键或者没主键的提示: [ PROCESS OUT] The following has evaluated to null or missing: [ PROCESS OUT] ==> data.getServiceData().getPrimaryKeyField() [in template "014f73e47cca4002a84b1fae58296bea" at line 40, column 25]
runtime模式
只有运行环境,没有开发环境
apps命名空间下新建
kind: Secret apiVersion: v1 metadata: name: uaa-credential-token-secret namespace: apps data: CREDENTIAL_TOKEN: TURkbU5EQmlPVEZpTmpGa1pXRTJaVEZqWkRjeVpU type: Opaque
否则应用pod初始化会报:Error: secret "uaa-credential-token-secret" not found
门户
访问门户
Services需要设置NodePort,暴露访问端口
spec: type: NodePort
会自动暴露出随机端口
账号:system,初始密码:salt@121P
查看密码:cat /usr/local/x5/conf/env.sh|grep API
API_SECRET变量
查看门户的数据库
进入门户的tomcat容器
cat /usr/local/x5/conf/env.sh|grep MAIN_DB
export RES_MAIN_READONLY='false' export DOMAIN_PREFIX='entryapps4' export MAIN_DBPROPERTIES='' export MAIN_DBUSER='fmhnrl0z_320' export MAIN_DBSCHEMA='20230322145713fmhnrl0z' export MAIN_DBPASSWD='FjLt_5384291' export MAIN_DBPORT='3306' export MAIN_DBHOST='db-mysql-svc.apps' export MAIN_DBTYPE='mysql' export MAIN_DBNAME='20230322145713fmhnrl0z' export MAIN_SERVICEADDRESS='localhost' export MAIN_PORT='8080'
服务注册
手工注册
要设置为“外部系统”,secret随便填,比如123
注册工作流报 502 错误
查看工作流pod启动是否正常?
如果没有license,会启动报错,提示没有找到license
门户菜单只显示“服务注册”,其他不显示
需要点击一下门户在服务注册右侧的刷新按钮
如果访问不了,重启 pod 试试
比如出现 503 错误
工作流
流程定义需要手动导入进去?
不需要,先要安装工作流以及服务注册
普通应用
如果页面访问不了,可能 nginx 配置丢失了,重启一下 pod
存储过程之类的需要手动导入进去
删除
删除某个应用
helm list -n apps helm uninstall 名字 -n apps
删除平台
bash /store/newdao-installer/cloud/install/uninstall.sh
命名空间只留这3项: namespacePrefix: 'newdao-' consoleNamespace: 'console' commonNamespace: 'common'
删除k8s
bash /store/newdao-installer/kubernetes/clean-host.sh 127.0.0.1
安装
必须使用root账号
sudo su 切换 root 账号(需要和root同组)
门户数据导入
原门户数据库的组织、部门、用户、角色、授权等信息导出
users、orgs、role、manage_orgs、authorize
role 只导出自己新建的角色和org_user,其他系统默认角色不用导出
manage_orgs 是部门的主管设置表
authorize 只导出自己新建的授权和根组织的,原来 system 的授权不用导出
注意不要导出 system 账号相关的数据
导入到新门户
问题
helm导出某个应用,不显示版本号,造成导出不了
上传到市场后,需要system进行审核
pod 一直 pending:nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }
可能磁盘空间不够,可以去 /store 删除那些带日期的备份文件夹
修改INGRESS_PORT=80的问题
kube控制台左侧菜单,config_map那边,有个basic.conf,找到INGRESS_PORT。修改后再重启那个应用的pod
浏览器问题
部分浏览器不能预览pdf(体现为下载):搜狗
页面大白页
内核版本低的浏览器
单点登录
注册影子账号 registerShadowUser
门户用户表 users,建2个账号
1、影子账号
2、真实账号
OpenAPI
规范
OpenAPI 规范 (中文版) https://openapi.apifox.cn/
例子
Swagger Editor https://editor.swagger.io/
petstore3
https://petstore3.swagger.io/
https://petstore3.swagger.io/api/v3/openapi.json
第三方集成
租户添加“企业集成”微服务应用
如果不添加,访问的时候会提示:未登录 uaa.common.config.MyDispatcher
企业微信
可信ip
top环境【会变化】:114.254.1.163;114.254.2.210
如果未配置成功,门户的tomcat日志会提示类似的错误:
{"errcode":60020,"errmsg":"not allow to access from your ip, hint: [1682684459303760367244107], from ip: 114.254.1.163, more info at https://open.work.weixin.qq.com/devtool/query?e=60020"}
前台访问页面会提示:
无法访问该页面
错误码:HTTP ERROR 500
统一通用配置可开启“用户自动映射=用户ID”选项
门户中的用户的用户名设置为企业微信的用户账号,就可以自动进行映射
企业微信账号:FengXueFeng
门户中的用户用户名:FengXueFeng
扫码登录
注意:统一通用配置中的门户配置,拉到下边需要先打开”开启企业微信扫码登录“配置项,才能在登录页面显示微信扫码登录入口。
皮肤
主题色这块,大概有这2种方式: 1、灵活动态设置皮肤样式 import { ConfigProvider } from 'antd'; ConfigProvider.config({ theme: { primaryColor: '#25b864', }, }); 2、整个应用固定某种皮肤样式 https://docs.i.newdao.top/devbase/pc-dev-antd/style/set-theme.html
bug
页面中的div显示大白页
看页面源码是否有:style="",有则删除
常用API
JS
提示
非门户API提示: wx.showToast({ "title": "保存成功!" });
门户API提示:justep.Util.hint("请输入采购订单号");
获取页面url:let url = this.getUIUrl("$UI/pcx/liebiao_xq.w");
获取其他资源url:this.getUIUrl("$UI/pcx/lib/luckysheet/luckysheet.umd.js")
获得组件:this.comp("mainData");
获得组件数值:data.getValue("orderNo");
生成UUID: js:justep.UUID.createUUID();【需要在门户调试运行,直接预览使用不了】 java:RandomUtil.uuid();
服务调用: var serviceGetConsumer = this.comp("serviceGetConsumer"); serviceGetConsumer.send({ "code": code }).then(function(res) { if (res.data) { data.setValue("customer", res.data.name); data.setValue("customerNo", res.data.fid); } });
表格插入数据:materialData.newData({ "defaultValues": [{ "no": item.matnr, "spec": item.matxt, "org": item.matkl }] })
封装流程列表的分页数量,供自定义数据集分页使用: let total = data.userdata['sys.count']; if (total === null || total === undefined) { total = self.comp(dataID).getTotal(); //分页,只有首页会有sys.count, 后续页的请求没有, 所以使用第一次的 } total = total || 0; self.comp(dataID).setTotal(total);
数据集的数据改变事件
if (event.col == "groupID") {}
获取页面参数
this.params
打开新页面(面包屑改变)
let url = this.getUIUrl("$UI/pcx/liebiao_xq.w"); justep.Shell.showPage({url: url, operate: "new"}); justep.Shell.showPage({url: url, operate: "edit", rowid: event.data.rowID});
event.context.$item.fid
跳转新页面(面包屑没有改变)
let url = "$UI/pcx/page_reuse/demo_page.w" this.navigateTo({ "url": url, "openType": "dialog",// page "modal": { "width": "50%", "title": "aaaa" }, "params": { "param0": "代码打开对话框的参数0", "param1": "代码打开对话框的参数1" }, "onClose": function(res) { debugger; } })
打开对话框
this.comp("dialog0").open({ "src": url, "oper": "new" });
let dialogModel = { "title": "新增" } this.comp("detailDialog").open({ "src": this.getUIUrl(pageUrl+"?operate=new") }, dialogModel)
操作扩展(CommonOperation )
关闭当前页面
this.comp("commonOperation").close();
确定返回
this.comp("commonOperation").okclose("selectData");
var dialogData = this.comp("dialogData"); var selectData = this.comp("selectData"); selectData.clear(); selectData.newData(); var oldrow = dialogData.getCurrentRow(); var newRow = selectData.getCurrentRow(); Object.assign(newRow,oldrow); this.comp("commonOperation").okclose("selectData");
代码调用高级请求组件
this.comp("getAreaRequest").send();
http://docs.newdao.net/xiao-cheng-xu-gao-ji-zu-jian-bu-chong/wang-luo-qing-qiu.html
动态设置排序条件
public void setOrderBy (String relation, integer type) String relation [required]关系名 integer type OrderBy的类型0:DESC/1:ASC,为null时清空对应关系的排序
利用async和await以同步代码方式调用数据组件的api
let self = this; async function doit() { let data0 = self.comp("restData0"); let data1 = self.comp("restData1"); let count = 0; await data0.refreshData(); // 第一个数据刷新后 console.log("data0.getCount():" + data0.getCount()); count += data0.getCount(); await data1.refreshData(); console.log("data1.getCount():" + data1.getCount()); // 第二个数据刷新后 count += data1.getCount(); console.log("total count:" + count); } doit();
流程
js启动流程: Model.prototype.onButton1Click=function(event){ var processData = this.comp("mainData") var processCode = 'liuchengqdcs';//要启动的流程编码 this.comp("wfui").start(processCode, "js启动流程", processData.getCurrentRowID(), null, null);//js启动流程是流程标题 }
几秒后执行
#/
开关值变化事件
onSwitch1Valuechange(event/*{{{*/=this._e.Switch_valuechange/*}}}*/){ let row = event.context.table0item; let svg = this.owner.reactRefs["svg-test"].current.getSVGDocument(); this.changeStatus(event.value, row.no, svg); }
遍历数据集
let data = this.comp("restData0"); data.each(function(item) { let index = item.index; let row = item.row; let rowId = data.getRowID(); let getRow = data.getRowByID(rowId); data.setValue("no", "aaaaaaaa" + (index++), row); let money = data.getValue("money", row); }); data.loadData([{"no":"1"},{"no":"2"}], true);
保存数据
this.comp("restData").saveData();
判断数据是否修改
if (row._recoredState != "none") { }
_recoredState值: none edit new 空字符串
新窗口打开页面
// 获取域名 let domain = window.location.host; // 获取微服务名 let serviceName = event.context.$page.basePath; serviceName = serviceName ? "/" + serviceName : ""; let orderID = event.context.$item.fid; let url = window.location.protocol + "//" + domain + serviceName + "/main/dbrest/salesOrder?$get=files.stream(0)&fid=eq." + orderID; // 新窗口打开 window.open(url, "_blank");
获取服务url前缀
getUrlPrefix(event) { // 获取域名 let domain = window.location.host; // 获取微服务名 let serviceName = event.context.$page.basePath; serviceName = serviceName ? "/" + serviceName : ""; return window.location.protocol + "//" + domain + serviceName; }
ajax请求
this.request({ method: "POST", dataType: "json", header: { "Accept": "application/json" }, data: param, url: url }).then(function(ret) { }, function(error) { });
this.request({ method : "get", url : "接口url", header : { "accept" : "application/json", // 要使用这个类型请求 "content-type" : "application/json" }, data : {"a":1,"b":2} })
数据集根据某字段内容查找
let rows = this.comp("restData").find(["check"], [1]);
重写过滤条件查询数据
loadMainData.filters.clear(); let filter = [{op:"LBRAC"}, {op:"eq", name:"fid", value:params.id}, {op:"RBRAC"}]; loadMainData.setFilter("eqfilter", filter);
从其他数据集加载数据,并赋值给主数据
async function packageData() { // 处理主数据 loadMainData.filters.clear(); let filter = [{op:"LBRAC"}, {op:"eq", name:"fid", value:params.id}, {op:"RBRAC"}]; loadMainData.setFilter("eqfilter", filter); // 异步需要等待 await loadMainData.refreshData(); // 加载数据 let loadMain = loadMainData.getCurrentRow(); mainData.setValue("type", loadMain.type); mainData.setValue("groupID", loadMain.groupID); } packageData();
从表格的操作按钮点击事件中获取行主键
event.context.$item.fid
强制把流程页面中的主数据替换
// 手动复制 if (params.oper == "batchEdit") { // 要使用这种方式赋值 Object.assign(mainData.getCurrentRow(), loadMainData.getCurrentRow()); }
访问页面使用只读模式
let url = this.getUIUrl("$UI/pcx/shijian_zx/shijian_clxq.w?_pagePattern=readonly"); justep.Shell.showPage({url: url, id: event.context.$item.id});
移动端选择数据
保存按钮事件: // 写入本地缓存 var rows = this.comp("restData0").find(["check"], [1]); wx.setStorageSync("selectProduct", rows); // 移动端关闭页面 this.comp("commonOperation").close(); 流程表单的页面显示事件: // 读取本地缓存 var rows = wx.getStorageSync("selectProduct"); if(rows){ rows.forEach((row,i)=>{ this.comp("restData1").newData({ defaultValues : [{ productID : row.fid, product_name : row.name, product_images : row.images, product_price : row.price, num : 1 }] }) }); wx.removeStorageSync("selectProduct"); }
获取当前登录人员的名称
this.comp("wxContext").getCurrentPersonMemberName();
格式化日期
wx.Date.toString(wx.Date.now(), "yyyy-MM");
流程流转成功后通过js回写数据
onWfmui1AdvanceSuccess = (event) => { let mainData = this.comp("masterData"); let processControl = event.processControl; let postscript = processControl.object.postscript; let author = this.comp("wxContext").getCurrentPersonMemberName(); let date = wx.Date.toString(wx.Date.now(), "yyyy-MM-dd HH:mm:ss"); // 获取当前环节 let activity = this.params.activity; // 部门经理审批意见 if (activity == "businessActivity2") { mainData.setValue("depOpinion", this.packageOpinion(author, date, postscript)); } // 总经理审批意见 else if (activity == "businessActivity3") { mainData.setValue("managerOpinion", this.packageOpinion(author, date, postscript)); } // 保存下一环节信息 let activityName = processControl.object.to[0]["task-relation-value"].sActivityName; if (activityName == "end1") { activityName = "审批通过"; } mainData.setValue("currentProcess", activityName); mainData.setValue("preHandler", author); mainData.setValue("status", activityName); // 保存 mainData.saveData(); } packageOpinion(author, date, postscript) { return "审批人:" + author + ",审批时间:" + date + ",意见:" + postscript; }
表格获取选中的多行(行选择)
table0为表格的id,不是数据集的id: this.comp("table0").getSelectedRowIds();
批量删除
var mainTable = this.comp("mainTable"); var mainData = this.comp("mainData"); var delArr = []; var checkids = mainTable.getSelectedRowIds(); if(checkids.length>0){ for(var i=0;i<checkids.length;i++){ delArr.push(mainData.getRowByID(checkids[i])); } mainData.deleteData(delArr); }else{ this.hint("请选择要删除的行"); }
设置表格选中的行
table0是表格组件的id: this.comp("table0").setSelectedRowIds(["19C4752AA83249E8B41DD24DCD93993E", "123"]);
根据选中的行,写到其他数据集中
let mainData = this.comp("mainData"); let selectData = this.comp("restData0"); let selectRowIds = this.comp("list").getSelectedRowIds(); let list = []; selectRowIds.forEach(function(id) { list.push(mainData.getRowByID(id)); }); selectData.loadData(list);
表格行选择事件
event.data.selectedRowKeys;
JSON对象转字符串
JSON.stringify(tableCustomData0.current.add)
遍历赋值
onPageLoaded(event/*{{{*/=this._e.page_loaded/*}}}*/){ let mainData = this.comp("mainData"); let loadMainData = this.comp("restData1"); let noProp = ["fid", "toJson", "_recoredState", "getState", "setState", "forceUpdate", "$initDefaultValue", "_$queryExtendProps"]; for (let x in loadMainData.getCurrentRow()) { if (noProp.indexOf(x) == -1) { mainData.setValue(x, loadMainData.getValue(x)); } } }
判断数据集是否通过校验
if (data.valid()) {}
使用图片素材
1、先上传图片到素材库;
2、this.getUIUrl('$UI/pcx/images/car1.png')
loadData加载数据
加载数据后,不会自动移动到当前行,需要手动 .first()
js操作时间
字符串转时间
wx.Date.fromString("2022-07-15 03:37:12", wx.Date.DEFAULT_FORMAT1)
时间转字符串
wx.Date.toString(date, "yyyy-MM-dd hh:mm:ss")
时间加减
wx.DateTimeUtilFn.plusSeconds(date, 5)
字符串时间戳转时间
let date = wx.DateTimeUtilFn.parse(parseFloat(travel.dateTimestamp))
显示数据集的全部数据
this.comp("restData1").toJson();
异步加载js和css
loadScript(url) { let js = document.createElement('script'); js.src = url; document.head.appendChild(js); } loadCss(url) { let css = document.createElement('link'); css.href = url; css.rel = 'stylesheet'; document.head.appendChild(css); }
流程任务列表打开表单详情
onButton0Click(event/*{{{*/=this._e.Button_onClick/*}}}*/){ debugger; // 当前登录用户 let loginUser = this.comp("wxContext0").getCurrentPersonMemberName(); let row = event.context.$item; let taskInfo = row.taskInfo;//获取任务信息 taskInfo = JSON.parse(taskInfo);//转JSON taskInfo = taskInfo[0];//示例代码,取第一条记录,实际中遍历任务信息,通过sExecutorFID找到当前人对应的记录 let url = "$UI/pcx/hetong_xq.w"; if (taskInfo) { // 任务执行人不包含当前登录用户,任务设置为只读 if (row.users.indexOf(loginUser) == -1) { url += "?_pagePattern=readonly"; } else { taskUtil.executeAndOpenTask(taskInfo);//打开流程任务页面 return; } } else { url += "?_pagePattern=readonly"; } justep.Shell.showPage({url: this.getUIUrl(url), sData1: row.fid}); }
js获取流程任务是否已结束
import taskUtil from "$UI/comp/wfmui/components/wfmui/js/taskUtil";
onPageLoaded(event/*{{{*/=this._e.page_loaded/*}}}*/){ this.isEnd(); } isEnd() { let self = this; let sData1 = this.params.sData1; taskUtil.queryFinishPIByData(sData1).then((result) => { if (result.length > 0) { let task = result[0]; if (task.sStatusName == "完成") { self.comp("tableCustomData0").setValue("isEnd", "已结束"); return; } } self.comp("tableCustomData0").setValue("isEnd", "处理中"); }); }
字符串分割和拼接
let strlist = str.split(",")
let str = strlist.join(",")
保存数据
保存当前行数据:saveData()
保存所有数据:saveAllData()
获取登录用户信息
https://xxx/uaa/userinfo
比如:https://entrylsd3-vip8e15e25a.e.newdao.top/uaa/userinfo
页面全屏显示
JS 全屏和退出全屏--requestFullScreen详解及兼容代码 https://blog.csdn.net/sadasda1/article/details/103922237
开始时间和结束时间的过滤
xxx 大于等于 查询条件.startDate
xxx 小于 加/减天(查询条件.endDate,1)
表格的按钮点击事件没有触发定位到当前行
行鼠标进入事件触发一下
this.comp("restData0").to(event.context.$item.fid);
Java
MyBaits Plus
从流程返回的主表ID获取对象:orderAssessMapperPlus.selectById(dataID);
查询:QueryWrapper<Material> detailWrapper = new QueryWrapper<>(); detailWrapper.eq("orderAssessId", dataID); List<Material> details = materialMapperPlus.selectList(detailWrapper);
修改:UpdateWrapper<OrderAssess> orderUpdateWrapper = new UpdateWrapper<OrderAssess>(); orderUpdateWrapper.set("isPriceFinish", needPrice ? 0 : 1).eq("fid", dataID); orderUpdateWrapper.setSql("version = version + 1"); orderAssessMapperPlus.update(null, orderUpdateWrapper);
流程
发起流程:// 发起流程 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); ProcessResult processResult = ProcessUtil.startProcess(request, "/SA/wf/default/orderassess_jiagelc", priceID, null); Task task = processResult.getActiveTasks().get(0); // 流转到第二个环节 ProcessUtil.advanceProcess(request, task.getId(), null);
要在流程中调用服务才能获取到如下内容(在页面中调用是获取不到的): 获取流程关联的表单内容: //获取request HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); //获取POST数据 InputStream is = request.getInputStream(); //转换为String String taskInfo = IOUtils.toString(is, "utf-8"); //转换为JSON JSONObject task = JSON.parseObject(taskInfo); //获取流程动作 String action = task.getString("action"); //获取流程变量 JSONObject vars = task.getJSONObject("vars"); //获取主表ID String sData1 = vars.getString("sData1");
终止流程
ProcessUtil.abortProcess(HttpServletRequest contextRequest, String task, ProcessControl control)
cookie
获取cookie: HttpServletRequest request = SpringWebUtil.getRequest(); Cookie[] cookies = request.getCookies(); for (Cookie cookie : cookies) { if (cookie.getName().equals(USER_SESSION_KEY)) { String val = cookie.getValue(); String location = link + "?" + USER_SESSION_KEY + "=" + val; return location; } }
uuid
RandomUtil.uuid()
基础 import
import org.springframework.beans.factory.annotation.Autowired;