GQL GET 请求生成图片文件流 — 技术实现方案

GQL GET 请求生成图片文件流 — 技术实现方案

基于 Oinone/Pamirs GQL GET 文件流机制,参考 FileAction#downloadFormData(查询型)与 ExcelExportTaskAction#createExportTask(同步写流),实现「按业务 ID 动态生成图片并输出文件流」的通用指南。


1. 背景与目标

1.1 需求

在业务场景中,需要根据业务 ID(如订单 ID、模板 ID、单据 ID)在后端动态渲染图片(条码、标签、证书、预览图等),并将结果以文件流形式返回给前端。

1.2 约束

  • 复用 Oinone 既有鉴权、会话、模块路由体系,不新增独立 REST 下载接口
  • 与 Excel 同步导出保持一致的调用方式:通过 GET 访问 /pamirs/{module}?query=...&variables=...
  • 前端仅两种消费方式:
    • 页面预览<img :src="imageUrl" />
    • 触发下载window.open(imageUrl, '_blank')

2. 参考实现

2.1 查询型文件流(图片查看应对齐此模式)

图片查看属于只读查询,应使用 query + @Function(type = QUERY),与 CDN 文件下载一致:

// @oinone/kunlun-vue-ui-common/.../UploadService.ts
const gql = `query{resourceFileFormQuery{downloadFormData(resourceFileForm:{downloadUrl:"${url}"}){filename}}}`;
window.open(UrlHelper.appendBasePath(`/pamirs/file?query=${encodeURIComponent(gql)}`), '_blank');
// pamirs-core/pamirs-file2/.../FileAction.java
@Function.Advanced(displayName = "前端下载数据", type = FunctionTypeEnum.QUERY)
public ResourceFileForm downloadFormData(ResourceFileForm resourceFileForm) {
    // 直接写 HttpServletResponse 输出流
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", "attachment; filename=" + ...);
    IOUtils.copy(inputStream, response.getOutputStream());
    return new ResourceFileForm();
}

图片查看用 GQL.query,不用 GQL.mutation

2.2 同步写流机制(共用)

无论 query 还是 mutation,文件流输出的底层机制相同:在 Function/Action 执行过程中直接写 HttpServletResponse

2.2.1 HTTP 网关:RequestController

GET  /pamirs/{moduleName}?query={gql}&variables={json}
POST /pamirs/{moduleName}  body: { query, variables }

GET 与 POST 走同一执行链路

// pamirs-framework/pamirs-gateways-graph-java/.../RequestController.java
@RequestMapping(value = "/pamirs/{moduleName}", method = RequestMethod.GET)
public DeferredResult<String> pamirsGet(
    @PathVariable("moduleName") String moduleName,
    @RequestParam("query") String gql,
    @RequestParam(value = "variables", required = false) String variables,
    ...) {
    PamirsClientRequestParam gqlRequest = new PamirsClientRequestParam();
    gqlRequest.setQuery(gql);
    if (!StringUtils.isBlank(variables)) {
        gqlRequest.setVariables(JsonUtils.parseMap(variables));
    }
    return pamirsPost(moduleName, gqlRequest, request, response);
}

variables.pathRequestHelper.preparePamirsRequestParam 中经 SessionPrepareApi.prepare 注入会话上下文,与前端 getSessionPath() 对应。

2.2.2 Excel 导出对照:ExcelFileServiceImpl#doExportSync

Excel 同步导出使用 mutationcreateExportTask),因为会创建导出任务记录;图片查看无此副作用,故用 query

同步导出的关键:劫持 FileClient.upload,将字节直接写入当前 HTTP 响应:

// pamirs-core/pamirs-file2/.../ExcelFileServiceImpl.java
public void doExportSync(ExcelExportTask exportTask, ExcelDefinitionContext context) {
    FileClient fileClient = new FileClient() {
        @Override
        public CdnFile upload(String fileName, byte[] data) {
            HttpServletResponse response = ...; // 从 RequestContextHolder 获取
            response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(data.length));
            response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, UTF_8));
            ServletOutputStream sos = response.getOutputStream();
            sos.write(data);
            sos.flush();
            return internalFileClient.upload(fileName, data);
        }
    };
    doExport0(exportTask, context, fileClient);
}

核心模式:GQL Function 执行业务逻辑 → 生成 byte[] → 通过 HttpServletResponse.getOutputStream() 直接输出,不再返回 JSON

2.3 mutation vs query 选型

场景 GQL 类型 后端注解 原因
图片查看 / 下载 query @Function(type = QUERY) 只读,按 ID 渲染并输出流
Excel 同步导出 mutation @Action 创建导出任务记录,附带写流
CDN 文件下载 query @Function(type = QUERY) 只读,代理已有文件流

2.4 端到端时序

GQL GET 请求生成图片文件流 — 技术实现方案


3. 通用图片流方案

3.1 调用方式

图片生成通过 GQL query 发起,一次 GET 请求完成渲染并输出文件流。前端通过同一 URL,配合后端 Content-Disposition 区分两种用途:

前端用法 后端响应头 效果
<img :src="imageUrl" /> Content-Disposition: inline 页面内预览
window.open(imageUrl, '_blank') Content-Disposition: attachment 新标签触发下载

请求参数中增加 download 字段控制响应头(见 §4、§5)。

3.2 模块选择

moduleName 说明
file 走 file 子系统,与 Excel 导出同模块
业务模块(如 order Action 挂在业务模型上,适合强业务耦合的图片生成

4. 后端实现指南

4.1 数据模型

@Model.model("order.BusinessImageRequest")
@Model(displayName = "业务图片请求")
public class BusinessImageRequest extends IdModel {

    @Field.String
    @Field(displayName = "业务ID")
    private String businessId;

    @Field.String
    @Field(displayName = "图片类型", summary = "如 BARCODE / LABEL / CERTIFICATE")
    private String imageType;

    @Field.Boolean
    @Field(displayName = "下载模式", summary = "true=attachment 下载,false=inline 预览")
    private Boolean download;

    @Field.Integer
    @Field(displayName = "宽度")
    private Integer width;

    @Field.Integer
    @Field(displayName = "高度")
    private Integer height;
}

4.2 Function 实现(查询型)

@Component
@Model.model(BusinessImageRequest.MODEL_MODEL)
public class BusinessImageAction {

    @Autowired
    private BusinessImageService businessImageService;

    @Function.Advanced(displayName = "渲染业务图片", type = FunctionTypeEnum.QUERY)
    @Function(openLevel = {FunctionOpenEnum.API, FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE})
    public BusinessImageRequest renderBusinessImage(BusinessImageRequest businessImageRequest) {
        businessImageService.renderImage(businessImageRequest);
        return businessImageRequest;
    }
}

4.3 Service:写图片流

@Service
public class BusinessImageServiceImpl implements BusinessImageService {

    public void renderImage(BusinessImageRequest request) {
        byte[] imageBytes = generateImage(request);

        HttpServletResponse response = Optional.ofNullable(RequestContextHolder.getRequestAttributes())
            .map(a -> (ServletRequestAttributes) a)
            .map(ServletRequestAttributes::getResponse)
            .orElseThrow(() -> new RuntimeException("未获取到 Http 响应"));

        try {
            String fileName = buildFileName(request);
            boolean download = Boolean.TRUE.equals(request.getDownload());
            String disposition = download ? "attachment" : "inline";

            response.setContentType("image/png");
            response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(imageBytes.length));
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                disposition + ";filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));

            ServletOutputStream out = response.getOutputStream();
            out.write(imageBytes);
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private byte[] generateImage(BusinessImageRequest request) {
        // 1. 按 businessId 查业务数据
        // 2. 调用渲染引擎生成图片
        // 3. 返回 PNG/JPEG byte[]
        return ...;
    }
}

实现模式与 FileAction#downloadFormData 一致:在 GQL Query Function 调用链内直接写 HttpServletResponse,无需额外 Controller。


5. 前端实现指南

5.1 构造图片 URL(公共方法)

import { GQL, getSessionPath } from '@oinone/kunlun-request';
import { UrlHelper } from '@oinone/kunlun-shared';

interface BuildImageUrlOptions {
  moduleName: string;      // 如 'order'
  queryModel: string;      // 如 'businessImageRequest'(GQL 自动拼接为 businessImageRequestQuery)
  businessId: string;
  imageType: string;
  download?: boolean;      // false=预览(inline),true=下载(attachment)
}

async function buildImageUrl(options: BuildImageUrlOptions): Promise<string> {
  const { moduleName, queryModel, businessId, imageType, download = false } = options;

  const gql = await GQL.query(queryModel, 'renderBusinessImage')
    .buildRequest((builder) => {
      builder.buildObjectParameter('businessImageRequest', (b) => {
        b.stringParameter('businessId', businessId);
        b.stringParameter('imageType', imageType);
        b.booleanParameter('download', download);
      });
    })
    .buildResponse((b) => b.parameter('id'))
    .toString();

  const variables = { path: getSessionPath() };
  return UrlHelper.appendBasePath(
    `/pamirs/${moduleName}?query=${encodeURIComponent(gql)}&variables=${encodeURIComponent(
      JSON.stringify(variables)
    )}`
  );
}

5.2 方式一:<img src> 页面预览

<template>
  <img :src="imageUrl" alt="业务图片预览" />
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';

const props = defineProps<{ businessId: string; imageType: string }>();
const imageUrl = ref('');

watch(
  () => [props.businessId, props.imageType],
  async () => {
    imageUrl.value = await buildImageUrl({
      moduleName: 'order',
      queryModel: 'businessImageRequest',
      businessId: props.businessId,
      imageType: props.imageType,
      download: false   // inline,供 img 内联渲染
    });
  },
  { immediate: true }
);
</script>

5.3 方式二:window.open 下载图片

async function downloadBusinessImage(businessId: string, imageType: string) {
  const url = await buildImageUrl({
    moduleName: 'order',
    queryModel: 'businessImageRequest',
    businessId,
    imageType,
    download: true    // attachment,触发浏览器下载
  });
  window.open(url, '_blank');
}

6. GQL 请求示例

6.1 预览(download: false

query {
  businessImageRequestQuery {
    renderBusinessImage(businessImageRequest: {
      businessId: "ORD-20260702-001"
      imageType: "BARCODE"
      download: false
    }) {
      id
    }
  }
}

6.2 下载(download: true

query {
  businessImageRequestQuery {
    renderBusinessImage(businessImageRequest: {
      businessId: "ORD-20260702-001"
      imageType: "BARCODE"
      download: true
    }) {
      id
    }
  }
}

6.3 完整 GET URL(解码后示意)

/{basePath}/pamirs/order?query=query{businessImageRequestQuery{renderBusinessImage(businessImageRequest:{businessId:"ORD-20260702-001",imageType:"BARCODE",download:false}){id}}}&variables={"path":"order.OrderList#search"}

7. 注意事项

7.1 URL 长度

浏览器与网关对 GET URL 长度有限制(通常 2KB~8KB)。图片请求参数应保持精简(businessIdimageType 等标量字段),复杂渲染逻辑在后端按 ID 自行查数。

7.2 响应类型

场景 download Content-Type Content-Disposition
<img src> 预览 false image/png inline;filename=...
window.open 下载 true image/png attachment;filename=...

7.3 鉴权

GET 请求依赖同源 Cookievariables.path 用于恢复视图会话;若 Function 不依赖会话上下文,可按需简化。

7.4 本地开发代理

本地开发时 /pamirs 需代理到后端,例如在 Vue CLI vue.config.js 中:

proxy: {
  '/pamirs': { target: 'http://your-backend-host:port', changeOrigin: true }
}

8. 实施检查清单

  • [ ] 后端:BusinessImageRequest 模型 + renderBusinessImage Query Function(写 HttpServletResponse
  • [ ] 后端:download 字段控制 inline / attachment
  • [ ] 前端:公共 buildImageUrl 方法(GQL.query 构造 + encodeURIComponent
  • [ ] 前端:variables.path = getSessionPath()
  • [ ] 前端:UrlHelper.appendBasePath 拼接 BASE_PATH
  • [ ] 联调:dev 代理 /pamirs 到后端
  • [ ] 验证:<img> 内联预览、window.open 下载、未登录拦截

9. 源码索引

9.1 前端(Oinone 框架)

说明 路径
查询型文件下载 URL @oinone/kunlun-vue-ui-common/.../UploadService.ts (generatorDownloadUrl)
GQL Builder @oinone/kunlun-request/.../gql.ts
URL 工具 @oinone/kunlun-shared/.../UrlHelper.ts

9.2 后端(oinone-pamirs)

说明 路径
GET/POST 网关 pamirs-framework/pamirs-gateways-graph-java/.../RequestController.java
会话准备 pamirs-framework/pamirs-gateways-graph-java/.../RequestHelper.java
查询型文件流(首选参考) pamirs-core/pamirs-file2/pamirs-file2-api/.../FileAction.java (downloadFormData)
Excel 同步写流(机制参考) pamirs-core/pamirs-file2/pamirs-file2-api/.../ExcelFileServiceImpl.java (doExportSync)
GET URL 编码测试 pamirs-core/pamirs-file2/pamirs-file2-core/.../RequestGetUrlTest.java

10. 相关文档

Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/kai-fa-shi-jian/25587.html

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

Like (0)
nation's avatarnation数式员工
Previous 2026年3月31日 pm11:21
Next 2023年11月6日

相关推荐

  • OSS(CDN)配置和文件系统的一些操作

    目前Oinone支持的OSS类型 类型 服务 OSS 阿里云OSS UPYUN 又拍云 MINIO MinIO HUAWEI_OBS 华为云OBS LOCAL 本地NGINX文件存储 TENCENT_COS 腾讯云COS CTYUN_ZOS 天翼云ZOS OSS通用yaml配置 cdn: oss: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: others: [key]: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: PS:others中使用自定义key来指定OSS服务进行文件上传/下载功能。上传/下载必须匹配,否则无法正常使用。 OSS配置示例 阿里云OSS cdn: oss: name: 阿里云 type: OSS bucket: pamirs(根据实际情况修改) uploadUrl: oss-cn-hangzhou.aliyuncs.com downloadUrl: oss-cn-hangzhou.aliyuncs.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true imageResizeParameter: referer: 华为云OBS cdn: oss: name: 华为云 type: HUAWEI_OBS bucket: pamirs(根据实际情况修改) uploadUrl: obs.cn-east-2.myhuaweicloud.com downloadUrl: obs.cn-east-2.myhuaweicloud.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true allowedOrigin: http://192.168.95.31:8888,https://xxxx.xxxxx.com referer: 华为云OBS需要在启动工程增加以下依赖 <okhttp3.version>4.9.3</okhttp3.version> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp3.version}</version> </dependency> 注意事项华为云OBS的防盗链配置,仅允许携带特定referer的才可以,而excel导入后端处理的逻辑匿名读的时候是不带referer的,所以会被拒绝 MINIO 文件系统,mino的配置: cdn: oss: name: minio type: MINIO bucket: pamirs(根据实际情况修改) uploadUrl: http://192.168.243.6:32190(根据实际情况修改) downloadUrl: http://192.168.243.6:9000(根据实际情况修改) accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: MINIO无公网访问地址下OSS的配置方式: https://doc.oinone.top/yun-wei-shi-jian/7112.html 又拍云 cdn: oss: name: 又拍云…

    后端 2023年11月1日
    2.1K00
  • 问题排查调试工具使用手册

    当前端发起对应用的访问时,如果出现错误,那么我们可以通过以下方式进行简易排查,如果排查不出来,则也可以把排查工具给出的信息发送给Oinone官方售后进行进一步分析。本文将通过模拟异常信息,来介绍排查工具,提供了哪些辅助信息帮我们来快速定位问题。 排查工具基础介绍 通过前端页面的 /debug 路由路径访问调试工具的页面,假设我们的前端页面访问地址为http://localhost:6800,那么我们的排查工具请求路径就是 http://localhost:6800/debug排查工具可以帮我们排查前端页面元数据异常和后端接口的异常 排查前端页面元数据 将问题页面浏览器地址栏内 page 后的部分复制到调试工具的 debug 路由后重新发起请求,如图可以看到调试工具展示的信息,可以根据这些信息排查问题。 排查后端接口 后端接口出现问题后,打开(在原页面)浏览器的调试工具,切换到“网络”的标签页,在左侧的历史请求列表中找到需要调试的请求,右键会弹出菜单,点击菜单中的 “复制”,再次展开该菜单,点击二级菜单中的“以 fetch 格式复制”,这样可以复制到调试所需要的信息 2.复制调试信息到“接口调试”标签页内的文本框内,点击“发起请求”按钮获取调试结果 我们可以看到页面展示了该接口的各种调试信息,我们可以据此排查问题。 场景化的排查思路 业务代码中存在代码bug 报错后发起调试请求,我们可以看到,调试工具直接给出了异常抛出的具体代码所在位置,此时再切换到“全部堆栈”下,可以看到是业务类的233行导致的空指针异常,查看代码后分析可得是data.getName().eqauls方法在调用前未做条件判断补全该判断后代码可以正常执行 业务代码中没有直接的错误,异常在平台代码中抛出 报错后发起调试请求可以看到异常不在业务代码内再切换到“全部堆栈”,可以看到具体异常信息,提示core_demo_item表出现了重复的主键,该表是DemoItem模型的我们还可以切换到“sql调试”的标签页,可以看到出错的具体sql语句经过分析可以得知是240行的data.create()�重复创建数据导致的。 三、排查工具无法定位怎么办 当我们通过排查工具还是没有定位到问题的时候,可以通过调试页面的“下载全部调试数据”和“下载调试数据”按钮将调试信息的数据发送给官方售后人员帮助我们定位排查问题。 点击页面最顶部的“下载全部调试数据”按钮,可以下载页面调试数据和接口调试数据点击“调试接口”标签页内的“下载调试数据”按钮,可以下载接口调试数据 四、排查工具细节

    2024年5月21日
    2.6K00
  • 首次登录修改密码和自定义密码规则等

    场景描述 在某些场景下,可能需要实现 用户首次登录强制修改密码的功能,或者存在修改平台默认密码等校验规则等需求;本文将讲解不改变平台代码的情况下,如何实现这些功能需求。 首次登录修改密码 方案概述 自定义User增加是否是第一次登录的属性,登录后执行一个扩展点。 判断是否是一次登录,如果是则返回对应的状态码,前端根据状态码重定向到修改密码的页面。修改完成则充值第一次登录的标识。 PS:首次登录的标识平台前端已默认实现 扩展PamirsUser(例如:DemoUser) /** * @author wangxian */ @Model.model(DemoUser.MODEL_MODEL) @Model(displayName = "用户", labelFields = {"nickname"}) @Model.Advanced(index = {"companyId"}) public class DemoUser extends PamirsUser { public static final String MODEL_MODEL = "demo.DemoUser"; @Field.Integer @Field.Advanced(columnDefinition = "bigint DEFAULT '0'") @Field(displayName = "公司ID", invisible = true) private Long companyId; /** * 默认true->1 */ @Field.Boolean @Field.Advanced(columnDefinition = "tinyint(1) DEFAULT '1'") @Field(displayName = "是否首次登录") private Boolean firstLogin; } 定义扩展点接口(实际项目按需要增加和删减接口的定义) import pro.shushi.pamirs.meta.annotation.Ext; import pro.shushi.pamirs.meta.annotation.ExtPoint; import pro.shushi.pamirs.user.api.model.tmodel.PamirsUserTransient; @Ext(PamirsUserTransient.class) public interface PamirsUserTransientExtPoint { @ExtPoint PamirsUserTransient loginAfter(PamirsUserTransient user); @ExtPoint PamirsUserTransient loginCustomAfter(PamirsUserTransient user); @ExtPoint PamirsUserTransient firstResetPasswordAfter(PamirsUserTransient user); @ExtPoint PamirsUserTransient firstResetPasswordBefore(PamirsUserTransient user); @ExtPoint PamirsUserTransient modifyCurrentUserPasswordAfter(PamirsUserTransient user); @ExtPoint PamirsUserTransient modifyCurrentUserPasswordBefore(PamirsUserTransient user); } 编写扩展点实现(例如:DemoUserLoginExtPoint) @Order(0) @Component @Ext(PamirsUserTransient.class) @Slf4j public class DemoUserLoginExtPoint implements PamirsUserTransientExtPoint { @Override @ExtPoint.Implement public PamirsUserTransient loginAfter(PamirsUserTransient user) { return checkFirstLogin(user); } private PamirsUserTransient checkFirstLogin(PamirsUserTransient user) { //首次登录需要修改密码 Long userId = PamirsSession.getUserId(); if (userId == null) { return user; } DemoUser companyUser = new DemoUser().queryById(userId); // 判断用户是否是第一次登录,如果是第一次登录,需要返回错误码,页面重新向登录 Boolean isFirst = companyUser.getFirstLogin(); if (isFirst) { //如果是第一次登录,返回一个标识给前端。 // 首次登录的标识平台已默认实现 user.setBroken(Boolean.TRUE); user.setErrorCode(UserExpEnumerate.USER_FIRST_LOGIN_ERROR.code()); return user; } return user; } @Override public PamirsUserTransient loginCustomAfter(PamirsUserTransient user) { return checkFirstLogin(user); } @Override…

    2024年5月25日
    5.8K00
  • 【后端】项目开发后端知识要点地图

    大类 明细 文档链接 平台基础 如何开发Action,理解前后端协议 如何开发Action,理解前后端协议 CDN配置及文件操作相关 OSS(CDN)配置和文件系统的一些操作 MINIO无公网访问地址下OSS的配置 MINIO无公网访问地址下OSS的配置 分库分表与自定义分表规则 分库分表与自定义分表规则 Oinone引入搜索引擎(增强模型) Oinone引入搜索引擎(增强模型) 引入搜索/增强模型Channel)常见问题解决办法 引入搜索(增强模型Channel)常见问题解决办法 框架之MessageHub(信息提示) 框架之MessageHub(信息提示) DsHint和BatchSizeHint的使用 DsHint(指定数据源)和BatchSizeHint(查询批次数量) Oinone连接外部数据源方案 Oinone连接外部数据源方案 如何自定义SQL(Mapper)语句 如何自定义SQL(Mapper)语句 IWrapper、QueryWrapper和LambdaQueryWrapper使用 IWrapper、QueryWrapper和LambdaQueryWrapper使用 如何在代码中使用自增ID、手动方式获取CODE 如何在代码中使用自增ID、手动方式获取CODE 函数之触发与定时配置和示例 函数之触发与定时配置和示例 函数之异步执行 函数之异步执行 查询时自定义排序字段和排序规则 查询时自定义排序字段和排序规则 非存储字段搜索 非存储字段搜索,适应灵活的搜索场景 枚举/二进制枚举/多值枚举 如何使用位运算的数据字典 全局首页及应用首页配置方法(homepage) 全局首页及应用首页配置方法(homepage) 缓存连接由Jedis切换为Lettuce 缓存连接由Jedis切换为Lettuce GraphQL请求:后端接口实现逻辑解析 GraphQL请求:后端接口实现逻辑解析 Nacos支持 Nacos作为注册中心 Oinone项目引入Nacos作为注册中心 Nacos作为配置中心 Oinone项目引入Nacos作为配置中心 Nacos做为注册中心调用SpringCloud服务 Nacos做为注册中心调用SpringCloud服务 分布式相关 如何构建分布式项目 Oinone如何支持构建分布式项目 构建分布式项目一些要点(dubbo日志关闭等) Oinone构建分布式项目一些注意点 信创支持 后端部署使用达梦数据库 【达梦】后端使用达梦数据库 后端部署使用PostgreSQL数据库 【PostgreSQL】后端使用PostgreSQL数据库 后端部署使用OpenGauss数据库 【OpenGauss】后端使用OpenGauss数据库 后端部署使用MSSQL数据库(SQLServer) 【MSSQL】后端部署使用MSSQL数据库(SQLServer) 东方通Web和Tomcat部署Oinone项目 东方通Web和Tomcat部署Oinone项目 常见扩展 如何增加用户中心的菜单 如何增加用户中心的菜单 导入导出 如何批量导入 如何批量导入 如何支持多Excel多个Sheet导入功能 如何支持多Excel多个Sheet导入功能 如何自定义Excel导入功能 如何自定义Excel导入功能 如何自定义Excel导出功能 如何自定义Excel导出功能 如何自定义表达式 如何自定义表达式 登录扩展 对接外部SSO Oinone登录扩展:对接SSO(4.7.8及之后的版本) 自定义占位符 自定义RSQL占位符及在权限中使用 自定义RSQL占位符(placeholder)及在权限中使用 自定义数据权限拦截处理 自定义数据权限拦截处理 设计器公共 后端无代码设计器Jar包启动方法 后端无代码设计器Jar包启动方法 界面设计器 页面跳转时增加跳转参数 页面跳转时增加跳转参数 界面设计器的导入导出 界面设计器的导入导出 流程设计器 项目中工作流引入和流程触发 项目中工作流引入和流程触发 流程扩展自定义函数示例代码汇总 工作流-流程扩展自定义函数示例代码汇总 工作流-流程代办等页面自定义 工作流-流程代办等页面自定义 审核撤回/回退/拒绝钩子使用 工作流审核撤回/回退/拒绝钩子使用 流程设计器的导入导出 流程设计器的导入导出 如何添加工作流运行时依赖 如何添加工作流运行时依赖 数据可视化 项目中图表设计器引入 数据可视化-项目中数据可视化的实现引入 自定义图表模版 数据可视化中图表的低无一体 图表设计器数据获取示例 数据可视化-数据可视化数据获取示例 如何添加数据可视化运行时依赖 如何添加数据可视化运行时依赖 图表设计器的设计数据导入导出 图表设计器的设计数据导入导出

    2024年5月21日
    2.7K00

Leave a Reply

Please Login to Comment