4.2.4 框架之网络请求-HttpClient

oinone提供统一的网络请求底座,基于graphql二次封装

一、初始化

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setMiddleware() // 必须设置,请求回调。具体查看文章https://shushi.yuque.com/yqitvf/oinone/vwo80g
http.setBaseURL() // 必须设置,后端请求的路径

图4-2-4-1 初始化代码示例

二、HttpClient详细介绍

获取实例

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();

图4-2-4-2 获取实例

接口地址

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setBaseURL('接口地址');
http.getBaseURL(); // 获取接口地址

图4-2-4-3 接口地址

请求头

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setHeader({key: value});

图4-2-4-4 请求头

variables

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setExtendVariables((moduleName: string) => {
 return customFuntion();

});

图4-2-4-5 variables

回调

import { HttpClient } from '@kunlun/dependencies';
const http = HttpClient.getInstance();
http.setMiddleware([middleware]);

图4-2-4-6 回调

业务使用-query

private http = HttpClient.getInstance();
private getTestQuery = async () => {
 const query = `gql str`;
 const result = await this.http.query('module name', query);
 console.log(result)
 return result.data[`xx`]['xx']; // 返回的接口,打印出result对象层次返回
};

图4-2-4-7 业务使用-query

业务使用-mutate

private http = HttpClient.getInstance();

private getTestMutate = async () => {
  const mutation = `gql str`;

  const result = await this.http.mutate('module name', mutation);
    console.log(result)
  return result.data[`xx`]['xx']; // 返回的接口,打印出result对象层次返回
};

图4-2-4-8 业务使用-mutate

三、如何使用HttpClient

初始化

在项目目录src/main.ts下初始化httpClient

初始化必须要做的事:

  • 设置服务接口链接

  • 设置接口请求回调

业务实战

前文说到自定义新增宠物表单,让我们在这个基础上加入我们的httpClient;

第一步新增service.ts

image.png

图4-2-4-8 新增service.ts

service.ts

import { HttpClient } from '@kunlun/dependencies';

const addPetMutate = async (modelName, data) => {
    const http = HttpClient.getInstance();
    const mutateGql = `mutation{
    petMutation{
      addPet(data:${data})
       {
        id
      }
    }
  }`;

    const result = await http.mutate('pet', mutateGql);
    return (result as any).data['petMutation']['addPet'];
};

export { addPetMutate };

图4-2-4-9 service.ts

第二步业务中使用

import { constructOne, queryOne, SPI, ViewWidget, Widget, IModel, getModelByUrl, getModel, getIdByUrl, FormWidgetV3, CustomWidget, CallChaining } from '@kunlun/dependencies';
import PetFormView from './PetFormView.vue';
// 引入
import { addPetMutate } from './service';

@SPI.ClassFactory(CustomWidget.Token({ widget: 'PetForm' }))
export class PetFormViewWidget extends FormWidgetV3 {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(PetFormView);
    return this;
  }

  /**
   * 数据提交
   * @protected
   */
  @Widget.Reactive()
  @Widget.Inject()
  protected callChaining: CallChaining | undefined;

  private modelInstance!: IModel;

  /**
   * 重要!!!!
   * 当字段改变时修改formData
   * */
  @Widget.Method()
  public onFieldChange(fieldName: string, value) {
    this.setDataByKey(fieldName, value);
  }

  /**
   * 表单编辑时查询数据
   * */
  public async fetchData(content: Record<string, unknown>[] = [], options: Record<string, unknown> = {}, variables: Record<string, unknown> = {}) {
    this.setBusy(true);
    const context: typeof options = { sourceModel: this.modelInstance.model, ...options };
    const fields = this.modelInstance?.modelFields;
    try {
      const id = getIdByUrl();
      const data = (await queryOne(this.modelInstance.model, (content[0] || { id }) as Record<string, string>, fields, variables, context)) as Record<string, unknown>;

      this.loadData(data);
      this.setBusy(false);
      return data;
    } catch (e) {
      console.error(e);
    } finally {
      this.setBusy(false);
    }
  }

  /**
   * 新增数据时获取表单默认值
   * */
  @Widget.Method()
  public async constructData(content: Record<string, unknown>[] = [], options: Record<string, unknown> = {}, variables: Record<string, unknown> = {}) {
    this.setBusy(true);
    const context: typeof options = { sourceModel: this.modelInstance.model, ...options };
    const fields = this.modelInstance.modelFields;
    const reqData = content[0] || {};
    const data = await constructOne(this.modelInstance!.model, reqData, fields, variables, context);
    return data as Record<string, unknown>;
  }

  @Widget.Method()
  private async reloadData() {
    const data = await this.constructData();
    // 覆盖formData
    this.setData(data);
  }

  @Widget.Method()
  public onChange(name, value) {
    this.formData[name] = value;
  }

  protected async mounted() {
    super.mounted();
    const modelModel = getModelByUrl();
    this.modelInstance = await getModel(modelModel);
    this.fetchData();
    // 数据提交钩子函数!!!
    this.callChaining?.callBefore(() => {
      return this.formData;
    });
  }

  @Widget.Method()
  private async addPet() {
    // 调用
    const data = await addPetMutate('petModule', this.getData());
  }
}

图4-2-4-10 业务中使用

Oinone社区 作者:史, 昂原创文章,如若转载,请注明出处:https://doc.oinone.top/oio4/9305.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
史, 昂的头像史, 昂数式管理员
上一篇 2024年5月23日 am8:33
下一篇 2024年5月23日 am8:35

相关推荐

  • 3.4.3.3 SPI机制-扩展点

    扩展点结合拦截器的设计,oinone可以点、线、面一体化管理Function 扩展点用于扩展函数逻辑。扩展点类似于SPI机制(Service Provider Interface),是一种服务发现机制。这一机制为函数逻辑的扩展提供了可能。 一、构建第一个扩展点 自定义扩展点(举例) 在我们日常开发中,随着对业务理解的深入,往往还在一些逻辑中会预留扩展点,以便日后应对不同需求时可以灵活替换某一小块逻辑。 在3.3.4【模型的继承】一文中的PetCatItemQueryService,是独立新增函数只作公共逻辑单元。现在我们给它的实现类增加一个扩展点。在PetCatItemQueryServiceImpl的queryPage方法中原本会先查询PetCatType列表,我们这里假设这个逻辑随着业务发展未来会发生变化,我们可以预先预留【查询萌猫类型扩展点】 Step1 新增扩展点定义PetCatItemQueryCatTypeExtpoint 扩展点命名空间:在接口上用@Ext声明扩展点命名空间。会优先在本类查找@Ext,若为空则往接口向上做遍历查找,返回第一个查找到的@Ext.value注解值,使用该值再获取函数的命名空间;如果未找到,则返回扩展点全限定类名。所以我们这里扩展点命名空间为:pro.shushi.pamirs.demo.api.extpoint.PetCatItemQueryCatTypeExtpoint 扩展点技术名称:先取@ExtPoint.name,若为空则取扩展点接口方法名。所以我们这里技术名为queryCatType package pro.shushi.pamirs.demo.api.extpoint; import pro.shushi.pamirs.demo.api.model.PetCatType; import pro.shushi.pamirs.meta.annotation.Ext; import pro.shushi.pamirs.meta.annotation.ExtPoint; import java.util.List; @Ext public interface PetCatItemQueryCatTypeExtpoint { @ExtPoint(displayName = "查询萌猫类型扩展点") List<PetCatType> queryCatType(); } 图3-4-3-11 新增扩展点定义PetCatItemQueryCatTypeExtpoint Step2 修改PetCatItemQueryServiceImpl(用Ext.run模式调用) 修改queryPage,增加扩展点的使用代码。扩展点的使用有两种方式 方法一,使用命名空间和扩展点名称调用Ext.run(namespace, fun, 参数); 方法二,使用函数式接口调用Ext.run(函数式接口, 参数); 我们这里用了第二种方式 用PetCatItemQueryCatTypeExtpoint的全限定类名作为扩展点的命名空间(namespace) 用queryCatType的方法名作为扩展点的技术名称(name) 根据namespace+name去找到匹配扩展点实现,并根据规则是否匹配,以及优先级唯一确定一个扩展点实现去执行逻辑 package pro.shushi.pamirs.demo.core.service; ……省略依赖包 @Model.model(PetCatItem.MODEL_MODEL) @Component public class PetCatItemAction extends DataStatusBehavior<PetCatItem> { @Override protected PetCatItem fetchData(PetCatItem data) { return data.queryById(); } @Action(displayName = "启用") public PetCatItem dataStatusEnable(PetCatItem data){ data = super.dataStatusEnable(data); data.updateById(); return data; } @Function.Advanced(displayName = "查询模型数据的默认过滤条件", type = FunctionTypeEnum.QUERY, managed = true) @Function(openLevel = {LOCAL}) public String queryFilters() { StringBuilder sqlWhereCondition = new StringBuilder(); // List<PetCatType> typeList = new PetCatType().queryList(); List<PetCatType> typeList = Ext.run(PetCatItemQueryCatTypeExtpoint::queryCatType, new Object[]{}); if(!CollectionUtils.isEmpty(typeList)){ // sqlWhereCondition.append("type_id"); sqlWhereCondition.append(PStringUtils.fieldName2Column(LambdaUtil.fetchFieldName(PetCatItem::getTypeId))); sqlWhereCondition.append(StringUtils.SPACE).append(SqlConstants.IN).append(CharacterConstants.LEFT_BRACKET); for(PetCatType petCatType: typeList){ sqlWhereCondition.append(petCatType.getId()).append(CharacterConstants.SEPARATOR_COMMA); } sqlWhereCondition.deleteCharAt(sqlWhereCondition.lastIndexOf(CharacterConstants.SEPARATOR_COMMA)); sqlWhereCondition.append(StringUtils.SPACE).append(CharacterConstants.RIGHT_BRACKET); } return sqlWhereCondition.toString(); } ……省略其他函数 } 图3-4-3-12 修改PetCatItemQueryServiceImpl Step3 新增扩展点实现PetCatItemQueryCatTypeExtpointOne 扩展点命名空间要与扩展点定义一致,用@Ext(PetCatItemQueryCatTypeExtpoint.class) @ExtPoint.Implement声明这是在@Ext声明的命名空间下,且技术名为queryCatType的扩展点实现 package pro.shushi.pamirs.demo.core.extpoint; import pro.shushi.pamirs.demo.api.extpoint.PetCatItemQueryCatTypeExtpoint; import pro.shushi.pamirs.demo.api.model.PetCatType; import pro.shushi.pamirs.meta.annotation.Ext; import pro.shushi.pamirs.meta.annotation.ExtPoint; import pro.shushi.pamirs.meta.api.session.PamirsSession; import java.util.List; @Ext(PetCatItemQueryCatTypeExtpoint.class) public class PetCatItemQueryCatTypeExtpointOne implements PetCatItemQueryCatTypeExtpoint { @Override @ExtPoint.Implement(displayName = "查询萌猫类型扩展点的默认实现") public List<PetCatType> queryCatType() { PamirsSession.getMessageHub().info("走的是第一个扩展点"); List<PetCatType> typeList = new PetCatType().queryList(); return typeList; } } 图3-4-3-13 新增扩展点实现PetCatItemQueryCatTypeExtpointOne Step4…

    2024年5月23日
    1.3K00
  • 第1章 揭开面纱,理解Oinone

    本章旨在从以下几个维度逐步揭开Oinone的面纱,让大家了解Oinone的初心与愿景,以及它是如何站在软件领域的巨人肩膀上,结合企业数字化转型的深入,形成全新的理念,帮助企业完成数字化转型。 具体来说,本章会从以下四个方面逐一展开: Oinone的初心与愿景:结合中国软件行业的发展与自身职业发展经历,探讨Oinone为何诞生以及其愿景是什么。 Oinone致敬西方软件行业的新贵odoo:介绍Oinone的灵感来源,探究Oinone与odoo的异同,以及如何从odoo中汲取经验。 从企业转型困境,引出Oinone新的思路:通过剖析企业数字化转型的困境,引出Oinone提出的全新思路,以及如何应对企业数字化转型的挑战。 行业对比,让您从不同视角理解Oinone:通过与同行业产品进行对比,从不同的视角深入理解Oinone的特点和优势。

    Oinone 7天入门到精通 2024年5月23日
    2.6K00
  • 4.1.16 框架之网关协议-RQSL及扩展

    一、RSQL / FIQL parser RSQL是一种查询语言,用于对RESTful API中的条目进行参数化过滤。它基于FIQL(Feed Item Query Language)——一种URI友好的语法,用于跨Atom Feed中的条目表达过滤器。FIQL非常适合在URI中使用,没有不安全的字符,因此不需要URL编码。另一方面,FIQL的语法不太直观,URL编码也不总是那么重要,因此RSQL还为逻辑运算符和一些比较运算符提供了更友好的语法。 例如,您可以像这样查询资源:/movies?query=name=="Kill Bill";year=gt=2003 or /movies?query=director.lastName==Nolan and year>=2000。详见以下示例: 这是一个用JavaCC和Java编写的完整且经过彻底测试的RSQL解析器。因为RSQL是FIQL的超集,所以它也可以用于解析FIQL。 语法和语义 以下语法规范采用EBNF表示法(ISO 14977)编写。 RSQL表达式由一个或多个比较组成,通过逻辑运算符相互关联: Logical AND : ; or and Logical OR : , or or 默认情况下,AND运算符优先(即,在任何OR运算符之前对其求值)。但是,可以使用带括号的表达式来更改优先级,从而产生所包含表达式产生的任何结果。 input = or, EOF; or = and, { "," , and }; and = constraint, { ";" , constraint }; constraint= ( group | comparison ); group = "(", or, ")"; 比较由选择器、运算符和参数组成。 comparison=选择器、比较运算、参数; 选择器标识要筛选的资源表示形式的字段(或属性、元素…)。它可以是任何不包含保留字符的非空Unicode字符串(见下文)或空格。选择器的特定语法不由此解析器强制执行。 selector=未保留str; 比较运算符采用FIQL表示法,其中一些运算符还具有另一种语法: · Equal to : == · Not equal to : != · Less than : =lt= or < · Less than or equal to : =le= or <= · Greater than operator : =gt= or > · Greater than or equal to : =ge= or >= · In : =in= · Not in : =out= 您还可以使用自己的运算符简单地扩展此解析器(请参阅下一节)。 comparison-op = comp-fiql | comp-alt; comp-fiql = ( ( "=", { ALPHA } ) | "!" ), "="; comp-alt = ( ">" | "<" ), [ "=" ]; 参数可以是单个值,也可以是用逗号分隔的括号中的多个值。不包含任何保留字符或空格的值可以不加引号,其他参数必须用单引号或双引号括起来。 arguments = ( "(", value, { "," , value }, ")" ) | value; value = unreserved-str | double-quoted | single-quoted; unreserved-str = unreserved, {…

    Oinone 7天入门到精通 2024年5月23日
    1.1K00
  • 4.2.3 框架之SPI机制

    SPI(Service Provider Interface)服务提供接口,是一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件,简单来说就是用来解耦,实现组件的自由插拔,这样我们就能在平台提供的基础组件外扩展新组件或覆盖平台组件。 目前定义SPI组件 ViewWidget 视图组件 FieldWidget 字段组件 ActionWidget 动作组件 表4-2-3-1 目前定义SPI组件 前提知识点 使用 TypeScript 装饰器(注解)装饰你的代码 1. 通过注解定义一种SPI接口(Interface) @SPI.Base<IViewFilterOptions, IView>('View', ['id', 'name', 'type', 'model', 'widget']) export abstract class ViewWidget<ViewData = any> extends DslNodeWidget { } 图4-2-3-1 代码示意 2. 通过注解注册提供View类型接口的一个或多个实现 @SPI.Base<IViewFilterOptions, IView>('View', ['id', 'name', 'type', 'model', 'widget']) export abstract class ViewWidget<ViewData = any> extends DslNodeWidget { } 图4-2-3-2 代码示意 3. 视图的xml内通过配置来调用已定义的一种SPI组件 <view widget="form" model="demo.shop"> <field name="id" /> </view> 图4-2-3-3 代码示意 图4-2-3-4 组件继承示意图 当有多个服务提供方时,按以下规则匹配出最符合条件的服务提供方 SPI匹配规则 SPI组件没有严格的按匹配选项属性限定,而是一个匹配规则 按widget最优先匹配,配置了widget等于是指定了需要调用哪个widget,此时其他属性直接忽略 按最大匹配原则(匹配到的属性越多优先级越高) 按后注册优先原则

    2024年5月23日
    1.1K00

Leave a Reply

登录后才能评论