自动化脚本云原生之FaaS通用服务

一、FaaS 与通用服务介绍

自动化脚本融合了 FaaS(函数即服务)与 Serverless 架构,帮助开发者摆脱服务器管理、集群运维、弹性扩容等基础设施负担,仅需聚焦业务逻辑,用 JavaScript 编写微服务脚本即可快速扩展后端能力。通用服务作为 FaaS 体系的核心模块,专注于表格数据的全生命周期管理,覆盖数据增删改查、复杂业务执行、多条件联动查询等场景。

通用服务的核心优势在于低代码配置 + 全链路脚本支撑:无需从零搭建后端数据库与接口,通过可视化配置即可定义数据表格、查询条件、操作按钮;同时支持自定义 JS 脚本处理复杂业务逻辑,兼容 Java 后端系统对接,兼顾开发效率与扩展性。下文从核心能力、配置流程、源码实现、实战场景四个维度,全面讲解通用服务的使用与开发。

二、通用服务核心能力与应用场景

(一)核心能力

  1. 数据 CRUD 一体化:基于自定义表格,支持数据新增、查询、编辑、删除、批量操作,内置数据库交互函数,无需编写原生 SQL。
  2. 多类型参数支持:查询与操作参数兼容整数、浮点数、布尔、字符串、文件、下拉选项(静态 / 动态),动态选项可通过 FaaS 脚本实时获取数据。
  3. 联动查询配置 :支持参数间依赖关联(如设备选择后联动加载对应账户),通过next/previous属性实现级联过滤。
  4. 自定义业务逻辑:所有数据操作(新增 / 编辑 / 删除 / 查询)均支持绑定自定义 JS 函数,可实现数据校验、格式转换、跨表关联、第三方接口调用等复杂逻辑。
  5. 多端无缝对接 :移动端通过callMicroService调用,网页端直接嵌入服务界面,第三方系统通过 OpenAPI 接口访问,全场景覆盖数据交互需求。

(二)典型应用场景

  • 移动端数据管理:APP 内实现用户信息、设备数据、业务记录的增删改查,无需搭建独立后端。
  • 网页端后台系统:快速搭建轻量化管理后台,如订单管理、设备调度、数据录入平台,低代码配置即可上线。
  • 第三方系统对接:Java 后端系统通过 OpenAPI 调用冰狐通用服务,实现跨系统数据同步与业务协同。
  • 自动化业务流程:结合冰狐移动端自动化脚本,实现 "数据查询 - 条件判断 - 自动操作 - 结果更新" 的全流程自动化。

三、通用服务可视化配置流程

在编写脚本前,需先完成通用服务的基础配置,核心包括表格定义、参数配置、数据列映射、操作按钮绑定四大步骤,以下为详细配置流程:

(一)新建通用服务

  1. 登录冰狐智能辅助平台,进入【云服务】→【通用服务】,点击右上角 "+ 服务",输入服务名称(如 "设备管理服务"),选择关联的数据库表(如device_info)。
  2. 配置基础信息:设置服务描述、访问权限(公开 / 私有)、分页条数(默认 10 条),保存后生成服务唯一标识。

(二)配置查询参数

查询参数用于定义数据过滤条件,支持静态参数与动态联动参数,示例配置如下:

表格

参数名 ID 类型 默认值 关联关系 描述
设备 UUID uuid select {"functionName":"getDevice"} next:"account" 选择设备后联动加载账户
账户名称 account select {"functionName":"getAccount"} previous:"device" 依赖设备参数过滤账户
设备状态 status string 按设备状态筛选(在线 / 离线)
  • 静态选项 :直接硬编码,格式名称:值,名称:值,如在线:1,离线:0
  • 动态选项 :绑定 FaaS 脚本函数,实时获取数据,格式{"scriptName":"设备脚本","functionName":"getDevice"}

(三)配置数据列

数据列用于定义表格展示字段,列 ID 必须与数据库表字段 / 脚本返回数据 Key 一致,否则无法正常显示,示例配置:

表格

列名 ID 宽度 排序 描述
设备 UUID uuid 200px 设备唯一标识
设备名称 name 150px 设备自定义名称
在线状态 status 120px 1 = 在线,0 = 离线
创建时间 create_time 180px 设备绑定时间

(四)配置数据操作

数据操作定义表格行的功能按钮(新增 / 编辑 / 删除 / 执行),每个按钮绑定对应的 FaaS 处理函数,核心配置包括按钮文本、图标、确认弹窗、处理函数

  1. 新增按钮 :文本 "新增设备",图标plus,弹窗显示参数输入框(名称 / 状态),绑定confirmAdd函数。
  2. 编辑按钮 :文本 "编辑",图标edit,弹窗回显当前行数据,绑定confirmEdit函数。
  3. 删除按钮 :文本 "删除",图标trash,弹窗提示 "确认删除该设备?",绑定confirmDelete函数。
  4. 批量操作 :支持多选数据行,配置 "批量删除" 按钮,绑定confirmBatchDelete函数。

四、冰狐 JS 脚本实战

通用服务的业务逻辑通过冰狐 JS 脚本实现,需在【云服务】→【云服务脚本】中新建脚本(如device_service.js),关联通用服务后即可生效。以下为设备管理通用服务的完整源码,包含动态选项、查询、新增、编辑、删除、批量操作六大核心函数。

(一)动态选项函数(联动查询)

javascript 复制代码
// 获取设备列表(动态选项:设备UUID→设备名称)
function getDevice() {
    // 获取当前用户的设备列表(平台内置函数:deviceList())
    let list = deviceList(rsOpenId);
    let ret = [];
    for (let item of list) {
        // 返回格式:[{name:"显示名称", value:"实际值"}]
        ret.push({ name: item.name, value: item.uuid });
    }
    return ret;
}

// 根据设备UUID获取关联账户(联动查询)
function getAccount(uuid) {
    let ret = [{ name: "全部", value: "" }]; // 默认"全部"选项
    let arr = [];
    if (strIsNotEmpty(uuid)) {
        // 按设备UUID查询账户表(dbQuery:平台内置数据库查询函数)
        arr = dbQuery("account_table", "*", [`uuid='${uuid}'`]);
    } else {
        // 无设备筛选时查询所有账户
        arr = dbQuery("account_table", "*", [`id>0`]);
    }
    for (let item of arr) {
        ret.push({ name: item.account_name, value: item.account_name });
    }
    return ret;
}

(二)数据查询函数(分页 + 多条件过滤)

javascript 复制代码
/**
 * 数据查询核心函数
 * @param {boolean} fetchCountOnly - 是否仅获取数据总数
 * @param {Array} conditions - 查询条件([{name:"参数名", value:"参数值"}])
 * @param {number} startIndex - 分页起始索引
 * @param {number} itemCount - 每页条数
 * @returns {Array|number} 数据列表或总数
 */
function query(fetchCountOnly, conditions, startIndex, itemCount) {
    let params = [];
    // 解析查询条件,拼接SQL过滤参数
    for (let item of conditions) {
        if (item.name === "uuid" && strIsNotEmpty(item.value)) {
            params.push(`uuid="${item.value}"`);
        }
        if (item.name === "account" && strIsNotEmpty(item.value)) {
            params.push(`account_name="${item.value}"`);
        }
        if (item.name === "status" && strIsNotEmpty(item.value)) {
            params.push(`status=${item.value}`);
        }
    }

    // 仅获取总数(用于分页)
    if (fetchCountOnly) {
        let countRet = dbQuery("device_info", "count(id) as count", params);
        return countRet[0].count;
    } 
    // 获取分页数据
    else {
        let dataRet = dbQuery(
            "device_info", 
            "*", 
            params, 
            "id DESC", // 排序规则:按ID倒序
            startIndex, 
            itemCount
        );
        return dataRet;
    }
}

(三)数据新增函数

javascript 复制代码
/**
 * 新增设备
 * @param {Array} itemIds - 选中数据ID(新增时为空)
 * @param {Array} params - 表单参数([{name:"参数名", value:"参数值", type:"参数类型"}])
 * @returns {boolean} 新增结果
 */
function confirmAdd(itemIds, params) {
    console.log("新增设备参数:", params);
    let obj = {};
    // 格式化参数,构建数据库插入对象
    for (let p of params) {
        obj[p.name] = p.value;
    }
    // 补充创建时间与用户ID
    obj.create_time = new Date().getTime();
    obj.creator_openid = rsOpenId;

    // 数据库插入(dbInsert:平台内置函数)
    let ret = dbInsert("device_info", obj);
    console.log("新增结果:", ret);
    return ret > 0; // 返回是否成功
}

(四)数据编辑函数

javascript 复制代码
/**
 * 编辑设备
 * @param {Array} itemIds - 选中数据ID(单条)
 * @param {Array} params - 表单参数
 * @returns {boolean} 编辑结果
 */
function confirmEdit(itemIds, params) {
    console.log("编辑设备ID:", itemIds, "参数:", params);
    let sets = [];
    // 拼接更新字段
    for (let item of params) {
        let fieldName = item.name === "device" ? "uuid" : item.name;
        let setStr = `${fieldName}=`;
        // 字符串类型加引号,数值类型不加
        if (item.type === "string") {
            setStr += `"${item.value}"`;
        } else {
            setStr += item.value;
        }
        sets.push(setStr);
    }

    // 数据库更新(dbUpdate:平台内置函数)
    let success = false;
    for (let id of itemIds) {
        success = dbUpdate("device_info", sets, [`id=${id}`]);
    }
    console.log("编辑结果:", success);
    return success;
}

(五)数据删除与批量删除函数

javascript 复制代码
/**
 * 删除单条设备
 * @param {Array} itemIds - 选中数据ID
 * @param {Array} params - 无需参数
 * @returns {boolean} 删除结果
 */
function confirmDelete(itemIds, params) {
    console.log("删除设备ID:", itemIds);
    let success = false;
    for (let id of itemIds) {
        // 数据库删除(dbDelete:平台内置函数)
        success = dbDelete("device_info", [`id=${id}`]);
    }
    return success;
}

/**
 * 批量删除设备
 * @param {Array} itemIds - 选中数据ID列表
 * @param {Array} params - 无需参数
 * @returns {boolean} 批量删除结果
 */
function confirmBatchDelete(itemIds, params) {
    console.log("批量删除设备ID:", itemIds);
    let success = true;
    for (let id of itemIds) {
        if (!dbDelete("device_info", [`id=${id}`])) {
            success = false;
            break;
        }
    }
    return success;
}

五、Java 后端对接冰狐通用服务源码

冰狐通用服务支持第三方系统通过OpenAPI 接口 调用,Java 后端可通过 HTTP 请求对接,实现数据查询、新增、编辑、删除等操作。以下为 Java(SpringBoot)对接示例,包含接口调用工具类、数据查询、新增设备三大核心模块。

(一)配置冰狐平台参数

XML 复制代码
# application.properties 冰狐平台配置
aznfz.openapi.url=https://aznfz.com/api/call_micro_service
aznfz.openapi.client-key=你的客户端密钥(平台获取)
aznfz.openapi.access-token=你的访问令牌(平台获取)
aznfz.openapi.script-name=device_service  // FaaS脚本名称
aznfz.openapi.is-dev=true  // 开发环境:true,生产环境:false

(二)HTTP 请求工具类

java 复制代码
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 冰狐OpenAPI调用工具类
 */
@Component
public class AznfzOpenApiUtil {

    @Value("${aznfz.openapi.url}")
    private String apiUrl;

    @Value("${aznfz.openapi.client-key}")
    private String clientKey;

    @Value("${aznfz.openapi.access-token}")
    private String accessToken;

    @Value("${aznfz.openapi.script-name}")
    private String scriptName;

    @Value("${aznfz.openapi.is-dev}")
    private boolean isDev;

    private final RestTemplate restTemplate = new RestTemplate();

    /**
     * 调用冰狐FaaS函数
     * @param functionName 函数名
     * @param params 函数参数
     * @return 接口返回结果
     */
    public String callFaaSFunction(String functionName, List<Object> params) {
        // 构建请求参数
        Map<String, Object> requestParams = new HashMap<>();
        requestParams.put("clientKey", clientKey);
        requestParams.put("accessToken", accessToken);
        requestParams.put("name", scriptName);
        requestParams.put("functionName", functionName);
        requestParams.put("isDev", isDev);
        requestParams.put("params", JSON.toJSONString(params));

        // 发送GET请求(冰狐OpenAPI支持GET/POST)
        return restTemplate.getForObject(apiUrl + "?clientKey={clientKey}&accessToken={accessToken}&name={name}&functionName={functionName}&isDev={isDev}&params={params}",
                String.class, requestParams);
    }
}

(三)设备管理业务接口

java 复制代码
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;

/**
 * 设备管理Java接口(对接冰狐通用服务)
 */
@RestController
@RequestMapping("/device")
public class DeviceController {

    private final AznfzOpenApiUtil aznfzOpenApiUtil;

    // 构造注入
    public DeviceController(AznfzOpenApiUtil aznfzOpenApiUtil) {
        this.aznfzOpenApiUtil = aznfzOpenApiUtil;
    }

    /**
     * 查询设备列表
     * @param status 设备状态(可选)
     * @param startIndex 分页起始索引
     * @param itemCount 每页条数
     * @return 设备列表
     */
    @GetMapping("/list")
    public List<Map<String, Object>> getDeviceList(
            @RequestParam(required = false) String status,
            @RequestParam(defaultValue = "0") Integer startIndex,
            @RequestParam(defaultValue = "10") Integer itemCount) {
        // 构建查询条件
        List<Object> params = List.of(
                false, // fetchCountOnly:false(查询数据)
                List.of(Map.of("name", "status", "value", status)), // 条件
                startIndex,
                itemCount
        );
        // 调用冰狐query函数
        String result = aznfzOpenApiUtil.callFaaSFunction("query", params);
        // 解析返回结果
        return JSON.parseObject(result, new TypeReference<List<Map<String, Object>>>() {});
    }

    /**
     * 新增设备
     * @param device 设备信息
     * @return 新增结果
     */
    @PostMapping("/add")
    public boolean addDevice(@RequestBody Map<String, Object> device) {
        // 构建参数:itemIds(空)、params(设备信息)
        List<Object> params = List.of(
                List.of(), // itemIds:新增时为空
                List.of(
                        Map.of("name", "name", "value", device.get("name"), "type", "string"),
                        Map.of("name", "status", "value", device.get("status"), "type", "int")
                )
        );
        // 调用冰狐confirmAdd函数
        String result = aznfzOpenApiUtil.callFaaSFunction("confirmAdd", params);
        return Boolean.parseBoolean(result);
    }
}

六、实战总结与扩展建议

(一)实战总结

FaaS 通用服务以低代码配置 + Serverless 架构 + 多端适配为核心,开发者无需管理服务器、无需编写复杂 SQL、无需搭建独立后端,通过可视化配置定义数据结构与操作逻辑,用少量 JS 脚本处理复杂业务,即可快速实现数据管理系统。特别适合移动端辅助工具、轻量化管理后台、自动化业务流程等场景。

相关推荐
逆境不可逃2 小时前
一篇速通互联网架构的不断升级过程:从单机到云原生
java·elasticsearch·搜索引擎·云原生·架构
白云偷星子2 小时前
云原生笔记8
笔记·云原生
珂玥c9 小时前
k8s集群网络插件caclico切换为flannel
云原生·容器·kubernetes
Zhu7589 小时前
【问题处理】minIO(AIStor)在k8s部署后,API访问失败的问题,TLS
云原生·容器·kubernetes
古城小栈13 小时前
通过 Kind 快速构建 k8s 集群
云原生·kubernetes·kind
Apache RocketMQ13 小时前
RocketMQ源码解析——秒级定时消息介绍
java·云原生·消息队列·rocketmq·java-rocketmq
珂玥c15 小时前
kubeadm方式部署 k8s 1.21
云原生·容器·kubernetes
小义_16 小时前
【Kubernetes】(十九)监控与升级
云原生·容器·kubernetes
炸炸鱼.17 小时前
Kubernetes Pod 深度理解:从入门到实战
云原生·容器·kubernetes·pod