Oinone平台可视化调试工具

为方便开发者定位问题,我们提供了可视化的调试工具。
该文档将介绍可视化调试工具的基本使用方法。

概述

调试工具分为两部分内容

  • 页面调试
  • 接口调试

PS:可视化调试工具仅能用于测试当前环境,无法跨环境测试。

页面调试概述

对当前页面的前端运行时上下文做了简单的解析,主要用于解决元数据权限视图等常见问题。

接口调试概述

对任何Oinone平台发起的标准请求,都可以使用该调试工具进行检查。主要用于解决异常堆栈权限SQL执行等相关问题的排查。

表述解释

为了方便表述,以下内容包含的后端模型字段/方法或GQL请求相关信息,其表述规则为:

{ClassSimpleName/GQLNamespace}#{field/method}

例如后端模型字段/方法:(该示例并不在平台代码中,仅作为展示)

public class ModuleDefinition {
    private String module;

    public void queryOne() {
        ...
    }
}

ClassSimpleNameJava类的类名,在上述例子中,ClassSimpleNameModuleDefinition
该Java类下的module字段可以表述为ModuleDefinition#module
该Java类下的queryOne方法可以表述为ModuleDefinition#queryOne

例如:

{
  viewActionQuery {
    load(
      ...
    ) {
      ...
    }
  }
}

GQLNamespace为GQL的首个字段在移除QueryMutation后缀后的结果,在上述例子中,GQLNamespaceviewAction
该GQL请求调用了load方法,可以将该请求简单表述为viewAction#load

PS:通常情况下,Java类名采用大驼峰表述,而GQL采用小驼峰表述。因此可以根据首字母为大写或小写区分其表述的具体内容。

以下所有内容表述均建立在此基础之上。

调试工具使用说明

进入调试工具页面

在需要调试的页面,通过修改浏览器URL的方式进入调试工具页面。如下图所示:

需要调试的页面

如需要调试的页面的URL如下所示:

http://127.0.0.1:9093/page;module=resource;viewType=TABLE;model=resource.ResourceCountryGroup;action=resource%23%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84;scene=resource%23%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84;target=OPEN_WINDOW;menu=%7B%22selectedKeys%22:%5B%22%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84%22%5D,%22openKeys%22:%5B%22%E5%9C%B0%E5%9D%80%E5%BA%93%22,%22%E5%9C%B0%E5%8C%BA%22%5D%7D

将page改为debug后即可进入该页面的调试页面,如下所示:

http://127.0.0.1:9093/debug;module=resource;viewType=TABLE;model=resource.ResourceCountryGroup;action=resource%23%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84;scene=resource%23%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84;target=OPEN_WINDOW;menu=%7B%22selectedKeys%22:%5B%22%E5%9B%BD%E5%AE%B6%E5%88%86%E7%BB%84%22%5D,%22openKeys%22:%5B%22%E5%9C%B0%E5%9D%80%E5%BA%93%22,%22%E5%9C%B0%E5%8C%BA%22%5D%7D

PS:通常我们会将新的URL改好后粘贴到新的浏览器标签页,以保留原页面可以继续查看相关信息。

调试工具页面

进入调试工具页面后,我们可以看到如下图所示的页面:

调试工具页面

调试页面信息概述

  • 下载全部调试数据:包括页面调试接口调试的全部数据。
    • 页面调试数据包含页面参数viewAction#load等页面数据。
    • 接口调试数据仅包含最近一次接口调试相关数据,未发起过请求将没有相关数据。

页面调试信息概述

  • 页面参数:当前URL中所有参数。
    • module:模块名称。ModuleDefinition#name
    • viewType:视图类型。ViewAction#resView#viewType
    • model:当前跳转动作模型编码。ViewAction#model
    • action:当前跳转动作名称。ViewAction#name
  • 页面信息:ViewAction#load接口返回的基础信息。
    • id:当前跳转动作ID。
    • model:同URL参数model
    • name:同URL参数action
    • title:用于浏览器标题以及面包屑显示名称备选项。
    • displayName:用于浏览器标题以及面包屑显示名称备选项。
    • contextType:数据交互上下文类型。
    • target:后端配置路由类型。不同于URL参数中的target。
    • domain:用户可视过滤条件,会根据规则回填至搜索区域
    • filter:用户不可视过滤条件,通过后端DataFilterHook追加至查询条件中。
    • module:跳转动作加载模块编码。
    • moduleName:跳转动作加载模块名称。
    • resModule:目标视图模块编码。
    • resModuleName:目标视图模块名称,用于模块跳转。
    • resViewId:目标视图ID。即当前页面视图ID。
    • resViewModel:目标视图模型编码。即当前页面视图模型编码。
    • resViewName:目标视图名称。即当前页面视图名称。
    • resViewType:目标视图类型。即当前页面视图类型。
    • maskName:后端配置母版名称。
    • layoutName:后端配置布局名称。
  • DSL:当前页面返回的未经处理的全部元数据信息。
  • Layout:当前页面使用的布局数据,当layoutName属性不存在时,该数据来自于前端注册的Layout。
  • Mask:当前页面使用的母版数据。
  • 页面字段:当前页面的全部字段元数据信息。(不包含引用视图)
  • 页面动作:当前页面的全部动作元数据信息。(不包含引用视图)
  • 运行时视图:当前页面的视图元数据信息。
  • 运行时DSL:经过解析的DSL元数据信息。
  • 运行时Layout:经过解析的布局信息。
  • 运行时渲染模板:主视图区域渲染的完整模板,即合并Layout和DSL后的最终结果。
  • 完整上下文:运行时上下文中的全部内容。

接口调试信息概述

  • 接口调试:用于发起一个fetch格式的浏览器请求。
    • 日志级别:根据不同的日志级别返回或多或少的调试信息。(暂未支持)
    • 发起请求:在下方输入框中粘贴fetch格式请求后可以发起真实的接口调用。(生产环境使用时可能产生数据,请确保接口幂等性以及在允许产生测试数据的环境中使用)
    • 重置:还原接口调试页面所有内容。
  • 接口响应结果:完整的接口返回结果。
  • 请求信息:当前请求的基本信息以及性能信息。
    • URL:调试请求的URL。
    • 请求方式:调试请求的Http请求方式。GET/POST
    • 完整请求耗时:从调试请求发起到前端响应并解析完成的时间。
    • 连接耗时:Http请求连接建立的时间。
    • 请求耗时:从调试请求发起到浏览器响应的时间。
    • 响应耗时:从浏览器响应到解析完成的时间。
    • 异常编码:调试请求响应结果中的首个异常信息的错误编码。
    • 异常信息:调试请求响应结果中的首个异常信息的错误信息。
    • 请求头:调试请求的Http请求头信息。
  • GQL#{index}:一个请求中可能包含多个GQL同时发起并调用多个对应的后端函数,index表示其对应的序号。
    • GQL:GQL内容
    • Variables:GQL参数
    • 异常抛出栈:请求出现异常的首个栈,即异常发生地。(无异常不返回)
    • 业务堆栈:不包含Oinone堆栈的调用堆栈信息。
    • 业务与Oinone堆栈:包含Oinone堆栈的调用堆栈信息。
    • 全部堆栈:未经处理的全部堆栈信息。
    • SQL调试:在当前请求链路中用到的所有执行SQL。
    • 函数调用链追踪:在当前请求链路中执行的全部Oinone函数基本信息及耗时。
    • GQL上下文:当前GQL上下文摘要。
    • 会话上下文:当前请求链路到结束的全部PamirsSession上下文信息。
    • 函数信息:当前GQL调用函数信息。
    • 模型信息:当前GQL调用函数对应模型的摘要信息。
    • 环境配置信息:服务端环境配置信息。
    • {GQLNamespace}#{GQLName}:当前执行函数的响应结果。

发起一次接口调试

以下示例均在Chrome浏览器中进行演示,不同浏览器可能存在差异。

使用浏览器查看接口及查看接口异常

如下图所示,通过检查F12打开浏览器控制台,并查看所有接口请求:

无异常接口
无异常接口

有异常接口

有异常接口

PS:一般情况下,所有Oinone请求的Http状态都为200,错误信息在errors数组中进行返回。

在浏览器控制台复制fetch格式请求

复制fetch格式请求

粘贴至接口调试输入框

粘贴至接口调试输入框

点击发起请求即可看到该接口的响应信息

点击发起请求

至此,我们已经完全介绍了现有调试工具的使用及页面展示内容的基本解释。未来我们还会根据需要调试的内容对该调试工具进行补充和完善,尽可能帮助开发者可以高效定位开发过程中遇到的常见问题。

下面,我们将提供几种查看调试信息的简单场景及步骤,帮助开发者可以快速上手并使用调试工具。

调试场景及检查步骤

通常情况下,Oinone平台遇到的问题都可以通过以下调试场景列举的检查步骤轻松定位问题。

当遇到无法通过调试工具定位问题时,可通过下载全部调试数据下载调试数据按钮,将下载的文件发送给Oinone售后服务工程师,并清楚描述遇到的问题,Oinone售后服务工程师会针对该问题提出解决方案或修复方案。

以下调试场景不区分使用页面调试接口调试,需要开发者根据遇到的问题自行判断该使用什么调试工具解决遇到的问题。

SQL示例解释

SQL示例中的表名可能与开发者调试的环境中的表名存在差异,需要开发者根据SQL示例找到对应的数据库及数据表并执行SQL。SQL示例中的参数需要根据开发者所遇到的问题进行调整。

SQL示例中并不包含租户隔离相关字段,请开发者根据运行环境自行补充查询条件。

{URL#model}表示使用URL参数中的model属性值进行替换,其他情况开发者可自行调整。

当页面中的字段/动作未正确显示时

检查当前用户是否具有该字段/动作的权限(超级管理员可跳过此步骤)

使用页面进行检查

步骤1:进入用户模块,查看该用户配置的角色列表,检查是否包含预期角色。
步骤2:进入权限模块,查看该用户所有角色的权限配置,检查是否包含字段的可见权限或动作的访问权限。

使用SQL进行检查

步骤1:根据当前登录用户获取用户ID(请开发者通过当前登录用户信息在user_pamirs_user表中自行查看)
步骤2:查看该用户配置的角色列表,检查是否包含预期角色。

-- 检查当前用户配置的角色列表
select id,name from auth_auth_role where id in (select role_id from auth_user_role_rel where user_id = {userId} and is_deleted = 0) and is_deleted = 0;

步骤3:根据角色列表分别查看字段和动作权限配置相关信息

检查当前跳转动作对应的视图是否为所需视图

步骤1:在页面调试DSL中搜索字段/动作相关信息,看看有没有正确返回。

如正确返回,可根据以下步骤进行检查:

  • 检查元数据是否补充完整。
  • 检查invisible属性是否按预期执行。

如未正确返回,可根据以下SQL示例在数据库中检查相关内容。

-- 检查ViewAction对应的视图是否为预期视图
select id,res_model,res_view_name from base_view_action where model = '{URL#model}' and name = '{URL#action}' and is_deleted = 0;

-- 检查视图的template是否存在字段/动作
select b.id,b.type,b.template from (select res_model,res_view_name from base_view_action where model = ''{URL#model}' and name = ''{URL#action}' and is_deleted = 0) a left join base_view b on a.res_model = b.model and a.res_view_name = b.name;

本文来自投稿,不代表Oinone社区立场,如若转载,请注明出处:https://doc.oinone.top/frontend/6669.html

(0)
张博昊的头像张博昊数式管理员
上一篇 2024年4月8日 pm10:15
下一篇 2024年4月18日 pm8:09

相关推荐

  • Oinone离线部署设计器JAR包

    概述 Oinone平台为合作伙伴提供了多种部署方式,这篇文章将介绍如何在私有云环境部署Oinone平台JAR包。 本文以5.2.6版本为例进行介绍。 部署环境要求 包含全部中间件及设计器服务的环境要求 CPU:8 vCPU 内存(RAM):16G以上 硬盘(HDD/SSD):60G以上 仅设计器服务的环境要求 CPU:8 vCPU 内存(RAM):8G以上 硬盘(HDD/SSD):40G以上 部署准备 在部署环境创建部署目录 mkdir -p /home/admin/oinone-designer PS:为方便管理,所有Oinone部署所需文件都应该在该目录下存放。 服务器需要安装的中间件 JDK:jdk_1.8_221版本以上 下载地址 MySQL:8.0.26版本以上 下载地址 Redis:5.0.2版本以上 下载地址 安装教程 Zookeeper:3.5.8版本以上 下载地址 安装教程 Nginx:任意版本(推荐使用源码编译安装方式,并开启rewrite、https等功能模块) Linux安装教程 下载地址 使用Docker启动所有中间件 点击下载一键部署所有中间件套件包 middleware-kits.zip 部署清单 下面列举了文章中在本地环境操作结束后的全部文件: 设计器JAR包:pamirs-designer-boot-v5.2-5.2.6.jar 离线部署结构包:oinone-designer-jar-offline.zip 第三方数据库驱动包(非MySQL数据库必须) PS:如需一次性拷贝所有部署文件到部署环境,可以将文档步骤在本地环境执行后,一次性将所有文件进行传输。 在本地环境准备部署文件 下载离线部署结构包 oinone-designer-jar-offline.zip 下载部署JAR包 5.2.6版本发布日志 查看更多版本 找到独立部署所有设计器JAR标题,下面有对应的JAR包提供下载。 例如:https://oinone-jar.oss-cn-zhangjiakou.aliyuncs.com/install/oinone-designer/pamirs-designer-boot-v5.2-5.2.6.jar 后端服务部署 将部署JAR包移动到backend目录下,并重命名为oinone-designer.jar mv pamirs-designer-boot-v5.2-5.2.6.jar backend/oinone-designer.jar PS:该名称为startup.sh脚本的默认值,可根据实际情况自行修改 将Pamirs许可证移动到backend/config目录下,并重命名为license.lic mv oinone-demo_1730163770607.lic backend/config/license.lic 加载非MySQL数据库驱动(按需) 将驱动jar文件移动到backend/lib目录下即可。 以KDB8数据库驱动kingbase8-8.6.0.jar为例 mv kingbase8-8.6.0.jar backend/lib/ PS:backend/lib目录为非设计器内置包的外部加载目录(外部库),可以添加任何jar包集成到设计器中。 修改backend/startup.sh脚本 IP:修改为可被外部访问的IP地址 DB_BASE_:base库相关数据库连接配置 DB_PAMIRS_:pamirs库相关数据库连接配置 REDIS_:Redis相关配置 MQ_NAME_SERVER:RocketMQ的name-server连接地址 ZOOKEEPER_:Zookeeper相关配置 PS:若需要配置方言或其他参数,可直接修改backend/config/application.yml配置文件,变量仅用于简单配置场景 执行startup.sh脚本启动 sh startup.sh 执行完成后会打印三个路径 后端路径:backend root path: /path/to/backend 前端路径:frontend root path: /path/to/frontend Nginx配置路径:nginx services path: /path/to/nginx Nginx配置 在本地nginx服务中找到nginx.conf,并添加Nginx配置路径为加载目录 http { … include /path/to/nginx/*.conf; } 修改结构包中的default.conf第7行root配置为前端路径到dist目录下 server { … root /path/to/frontend/dist; } 修改结构包中的oss.conf第30行alias配置为前端路径到static目录下 server { … location /static { … alias /path/to/frontend/static; } } 访问服务 使用http://127.0.0.1:9090访问服务

    2024年11月1日
    1.5K00
  • 前端元数据介绍

    模型 属性名 类型 描述 id string 模型id model string 模型编码 name string 技术名称 modelFields RuntimeModelField[] 模型字段 modelActions RuntimeAction[] 模型动作 type ModelType 模型类型 module string 模块编码 moduleName string 模块名称 moduleDefinition RuntimeModule 模块定义 pks string[] 主键 uniques string[][] 唯一键 indexes string[][] 索引 sorting string 排序 label string 显示标题 labelFields string[] 标题字段 模型字段 属性名 类型 描述 model string 模型编码 modelName string 模型名称 data string 属性名称 name string API名称 ttype ModelFieldType 字段业务类型 multi boolean (可选) 是否多值 store boolean 是否存储 displayName string (可选) 字段显示名称 label string (可选) 字段页面显示名称(优先于displayName) required boolean | string (可选) 必填规则 readonly boolean | string (可选) 只读规则 invisible boolean | string (可选) 隐藏规则 disabled boolean | string (可选) 禁用规则 字段业务类型 字段类型 值 描述 String ‘STRING’ 文本 Text ‘TEXT’ 多行文本 HTML ‘HTML’ 富文本 Phone ‘PHONE’ 手机 Email ‘EMAIL’ 邮箱 Integer ‘INTEGER’ 整数 Long ‘LONG’ 长整型 Float ‘FLOAT’ 浮点数 Currency ‘MONEY’ 金额 DateTime ‘DATETIME’ 时间日期 Date ‘DATE’ 日期 Time ‘TIME’ 时间 Year ‘YEAR’ 年份 Boolean ‘BOOLEAN’ 布尔型 Enum ‘ENUM’ 数据字典 Map ‘MAP’ 键值对 Related ‘RELATED’ 引用类型 OneToOne ‘O2O’ 一对一 OneToMany ‘O2M’ 一对多 ManyToOne ‘M2O’ 多对一 ManyToMany ‘M2M’ 多对多 模型动作 属性名 类型 描述 name string…

    2024年9月21日
    1.2K00
  • Oinone平台之Router扩展

    问题描述 在Oinone平台内置路由中,默认了三种路由 /login //默认登录页 /page //默认主逻辑页 / //根页面,会自动发起查询优先级最高的应用,并跳转 在实际的业务迭代中,我们通常有以下三种需求: 我要覆盖默认的登录页,页面我不喜欢,登录逻辑满足不了; 我要在平台上加个帮助中心; 这个路径不符合我司规范,我要自定义加前缀 接下来,我将在Oinone平台中满足以上场景 覆盖默认路径 以登录页为例 在项目目录src/main.ts下,添加自定义router import 'ant-design-vue/dist/antd.css'; import 'element-plus/dist/index.css'; import '@kunlun/vue-ui-antd/dist/kunlun-vue-ui-antd.css'; import '@kunlun/vue-ui-el/dist/kunlun-vue-ui-el.css'; import 'reflect-metadata'; import { VueOioProvider } from '@kunlun/dependencies'; import interceptor from './middleware/network-interceptor'; import './field'; import './view'; import './actions'; VueOioProvider( { http: { url: location.origin, callback: interceptor }, browser: { title: 'Oinone – 构你想象!', favicon: 'https://pamirs.oss-cn-hangzhou.aliyuncs.com/pamirs/image/default_favicon.ico' }, router: [{ path: '/login', widget: 'CustomLogin'}] // 用CustomLogin覆盖默认登录页 }, [] ); 定义CustomLogin, 定义方式同书籍中的自定义表单和自定义表格类似,精简版的代码为: import { RouterWidget, SPI } from "@kunlun/dependencies"; @SPI.ClassFactory(RouterWidget.Token({ widget: 'CustomLogin' })) // SPI注册,router得widget和此处的widgetshi对应的 export class CustomLogin extends RouterWidget { public initialize(props) { super.initialize(props); this.setComponent('定义的vue文件'); return this; } } 增加新的访问路径 同覆盖登录页 在router中增加路由 router: [{ path: '/login', widget: 'CustomLogin'}, { path: '/help', widget: 'Help'}] 定义Help,同覆盖登录页 定义个性化路径 需要再所有访问路径前统一加标识,比如添加Oinone;在项目目录下新建.env文件(若存在,可以复用),在env文件中添加: BASE_PATH=/Oinone 修改后重启工程即可,访问/Oinone/login即可 结语 以上就是Oinone平台路由的扩展能力,在Oinone平台中,通过自定义Router达到扩展路由的能力,并通过采用env等通用配置的能力,解决批量修改路由的目的。

    2023年11月1日
    60.2K00
  • 自定义组件之手动渲染基础(v4)

    阅读之前 你应该: 了解DSL相关内容。母版-布局-DSL 渲染基础(v4) 了解SPI机制相关内容。组件SPI机制(v4.3.0) 了解组件相关内容。 Class Component(ts)(v4) 自定义组件之自动渲染(组件插槽的使用)(v4) 为什么需要手动渲染 在自定义组件之自动渲染(组件插槽的使用)(v4)文章中,我们介绍了带有具名插槽的组件可以使用DSL模板进行自动化渲染,并且可以用相对简单的方式与元数据进行结合。 虽然自动化渲染在实现基本业务逻辑的情况下,有着良好的表现,但自动化渲染方式也有着不可避免的局限性。 比如:当需要多个视图在同一个位置进行切换。 在我们的平台中,界面设计器的设计页面,在任何一个组件在选中后,需要渲染对应的右侧属性面板。每个面板的视图信息是保存在对应的元件中的。根据元件的不同,找到对应的视图进行渲染。在单个视图中使用自动化渲染是无法处理这一问题的,我们需要一种可以局部渲染指定视图的方式,来解决这一问题。 获取一个视图 使用ViewCache获取视图 export class ViewCache { /** * 通过模型编码和名称获取视图 * @param model 模型编码 * @param name 名称 * @param force 强制查询 * @return 运行时视图 */ public static async get(model: string, name: string, force = false): Promise<RuntimeView | undefined> /** * 通过模型编码、自定义名称和模板获取编译后的视图(此视图非完整视图,仅用于自定义渲染使用) * @param model 模型编码 * @param name 名称(用作缓存key) * @param template 视图模板 * @param force 强制查询 * @return 运行时视图 */ public static async compile( model: string, name: string, template: string, force = false ): Promise<RuntimeView | undefined> } ViewCache#get:用于服务端定义视图,客户端直接获取完整视图信息。 ViewCache#compile:用于客户端定义视图,通过服务端编译填充元数据相关信息,但不包含视图其他信息。 自定义一个带有具名插槽的组件,并提供切换视图的相关按钮 以下是一个自定义组件的完整示例,其使用ViewCache#compile方法获取视图。 view.ts const template1 = `<view> <field data="id" invisible="true" /> <field data="code" label="编码" /> <field data="name" label="名称" /> </view>`; const template2 = `<view> <field data="id" invisible="true" /> <field data="name" label="名称" /> <field data="code" label="编码" /> </view>`; export const templates = { template1, template2 }; ManualDemoWidget.ts import { BaseElementWidget, createRuntimeContextForWidget, FormWidget, RuntimeView, SPI, ViewCache, ViewType, Widget } from '@kunlun/dependencies'; import ManualDemo from './ManualDemo.vue'; import { templates } from './view'; @SPI.ClassFactory(BaseElementWidget.Token({ widget: 'ManualDemo' })) export class ManualDemoWidget extends BaseElementWidget { private formWidget: FormWidget | undefined; public…

    2023年11月1日
    1.0K00
  • 组件生命周期(v4)

    阅读之前: 你应该: 了解DSL相关内容。母版-布局-DSL 渲染基础(v4) 对第三方框架的组件生命周期有所了解。如Vue组件生命周期 了解平台实现的Class Component(ts)相关内容。Class Component(ts)(v4) 组件生命周期 任何一个Widget其标准生命周期应当包括beforeCreated、created、beforeMount、mounted、beforeUnmount、unmounted这六个基本的生命周期函数、以及beforeUpdate和updated在响应式更新时会进行调用的生命周期函数。特别的,还有activated和deactivated在组件搭配keep-alive特性时使用的生命周期函数。 具体的生命周期执行过程在这里不再进行赘述,这里的基本逻辑与Vue组件生命周期基本完全一致,感兴趣的读者可以阅读Vue相关文档进行学习。

    2023年11月1日
    1.2K10

Leave a Reply

登录后才能评论