apijson 让前端自己定义接口

1,527 阅读5分钟

不知道各位前端有没有遇见这种问题,就是你前端界面写好了,但是后端因为忙别的事,导致接口没时间写!迫于无奈,你只能使用mock.js等模拟后端数据,等你兴高采烈的搞完了数据模拟,发现后端写的接口和你想要的数据又不是一个样子的,然后你会?

A. 和后端大吵一架,让他重写

B. 忍气吞声,默默修改你前端字段

C. 立刻掀桌,告诉领导,要求加人或者换人

D. 辞职不干

现在,菜鸟告诉你:apijson可以解决你的这些烦恼了!

介绍

image.png

注意

apijson后端框架,需要后端配置好!

后端配置好之后,可以少写很多接口(包括:apijson自带的登录、注册),后续apijson也可以很方便的由前端去查询数据库,后端就不用写简单的接口了!(涉及后端逻辑以及需要后端操作的还是要写接口)

此外多表修改数据库的操作,也应该由后端完成!如果只是更新单表,那么apijson完全可以胜任!(apijson也不是不能多表修改,只是前端可能不理解数据库关系,导致错误,反而会让后端更头疼)

使用

apiJson的官方文档例子都挺清晰:apiJson 官网

apijson中如果只查一条数据很简单:

{
    "数据库名称"{
        "查询字段名""值", // 可多个
        "@column":"你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
        "@order":"你想排序的数据库字段(+ 从小往大,- 从大到小)"
    }
}

image.png

到这里都很容易理解,直到文档中突然冒出一个 []!

多条数据

这个 [] 菜鸟一开始就没理解,但是和后端沟通后发现,这个东西就是固定的传参,表示的是获取多条数据的意思

解释一下查多条数据的例子:

{
    "[]": {
        "数据库名称"{
            "查询字段名&{}":多个值的且操作(eg:">10,<40" --> 表示大于10且小于40,
            "查询字段名{}":多个值的或操作(eg:"<10,>40" --> 表示小于10或者大于40, // 默认的逻辑关系是 `|`,所以可简写
            "查询字段名!{}":多个值的非操作(eg:"[12]" --> 表示不等于12, // 可同时出现多个
            "@column":"你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
            "@order":"你想排序的数据库字段(+ 从小往大,- 从大到小)"
        }
    }
}

解释一下分页查询的例子:

{
    "[]": {
        "数据库名称"{
            "@combine":"筛选字段1~ | 筛选字段2~ | 筛选字段3~", // 模糊查询,相当于where
            "筛选字段1":"搜索值",
            "筛选字段2":"搜索值",
            "筛选字段3":"搜索值",
            "@column":"你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
            "@order":"你想排序的数据库字段(+ 从小往大,- 从大到小)"
        },
        // 放在数据库名外!
        query: 2, // 1获取数量(单独写,不写下面的@total也不会返回总数!),2是获取数据(一般都是2)
        count: params.count, // 分页条数
        page: params.page - 1 // page从0开始所以减1
    },
    total@: "/[]/total" // 查询总数必须加,不然不返回total,不管query是1还是2
}

使用

image.png

likeJoin 是封装的一个模糊查询的函数:

/** 模糊查询like拼接 **/
export const likeJoin = (keyList = [], value = "") => {
  const likeData = {}
  // 设置筛选字段
  keyList.forEach((k) => (likeData[k] = value))
  if (keyList.length) {
    // 设置 @combine
    likeData["@combine"] = keyList.join(" | ")
  }
  return likeData
}

  1. @combine 并不在官方文档中,菜鸟也是看外包使用了找了半天才找到(见第2条),这里菜鸟还是 推荐直接用官网的模糊查询,官网的模糊查询也可以同时写多个,且结构比这个简单

  2. @combine的使用是有限制的见:github.com/Tencent/API…

  3. APIList 就是对返回的数据进行格式化整理的封装,见代码:

export const APIList = async (baseURL, tableName, data) => {
  // 读者使用可以直接把这里替换到上面蓝框处,自己对返回数据进行处理 --> request就按照平常的axios封装就行
  const ret = await request({ url: `${baseURL}/get`, method: "POST", data })
  
  // 格式化返回数据 --> 按需使用
  if (ret["[]"] && ret["[]"][0]) {
    const keys = Object.keys(ret["[]"][0])
    for (let k of keys) {
      if (k === tableName) k = "data"
      ret[k] = listFormat(ret["[]"], k === "data" ? tableName : k).filter((item) => !!item)
    }
  }
  delete ret["[]"]
  return ret
}

axios封装可以见:vue3+eslint(推荐配置)|prettier+elementplus+国际化+axios封装+pinia

所以上述分页可以写成这样

{
    "[]": {
        "数据库名称"{
            "筛选字段1~":"搜索值", // 模糊查询,
            "筛选字段2":"%搜索值%", // 等价上一个
            "筛选字段3~":"搜索值",
            "@column":"你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
            "@order":"你想排序的数据库字段(+ 从小往大,- 从大到小)"
        },
        // 放在数据库名外!
        query: 2, // 1获取数量(单独写,不写下面的@total也不会返回总数!),2是获取数据(一般都是2)
        count: params.count, // 分页条数
        page: params.page - 1 // page从0开始所以减1
    },
    total@: "/[]/total" // 查询总数必须加,不然不返回total,不管query是1还是2
}

官网说明

image.png

关联查询

最常见的,两表一对一查询 (示例为返回列表,不是列表可以不要 "[]" 这层)

{
  "[]": {
    "数据库名称": {
      "@column": "你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
      "查询字段名": "值"
    },
    "需要关联的数据库名称": {
      "需要关联的数据库中关联字段@": "/上面的数据库名称/对应上面的数据库名称中的哪一个字段",
      "@column": "你只想获取的数据库字段,你只想获取的数据库字段:别名(别名可不要)",
    }
  }
}

image.png

返回结构会给你分别放两个里面,展示要自己改:

image.png

两表 1对多

1对多,示例为返回列表,不是列表可以不要 "[]" 这层!

{ 
    "[]": {
        "Test_user": {},
        "Test_user_moent_ref[]":{ // 多加一层[]
            "Test_user_moent_ref":{
                "entity_id@":"Test_user/id"
            }
        }
    }
}

返回结构

image.png

问题1

但是菜鸟遇见一个问题,就是同一个数据库,对应另一个数据库的同一个字段apijson就无法使用!

image.png

希望有遇见过这种情况的apijson的大佬可以指点一下!!!

评论区大佬已解答,github菜鸟问的也得到了解答,见:github.com/Tencent/API…

image.png

问题2 -- JOIN

这是菜鸟最近(2024/12/24)发现的一个问题,就是 需要连表查询并且还需要进行多个表的模糊查询时 就不知道怎么写了,官网也没例子,所以这里菜鸟举例子解释一下!

/** 获取我的分析列表 **/
export async function analysisListApi(params = {}, keysword) {
  const data = {
    "[]": {
      join: `|/Project/projectId@`, // 这里见解释
      query: 2,
      count: params.count,
      page: params.page - 1
    },
    "total@": "/[]/total"
  }

  // 设置模糊查询参数
  const likeList1 = keysword ? likeJoin(["taskName~", "taskId~", "projectId~"], keysword) : {}
  const likeList2 = keysword ? likeJoin(["projectName~", "BNId~"], keysword) : {}

  data["[]"][tableName] = {
    isDelete: 0,
    "@order": "taskCreateTime-",
    // 表字段参数
    ...params.data,
    ...likeList1
  }
  data["[]"]["Project"] = {
    uId: params.uId,
    "projectId@": `/${tableName}/projectId`,
    ...likeList2
  }
  data["[]"]["User"] = {
    id: params.uId,
    "@column": "id,name,email",
    "id@": `/${tableName}/uId`
  }
  delete data.data
  return APIList(baseURL, tableName, data)
}
解释

这里主要就是 join ,菜鸟一开始以为是生成的 sql 的 OR 或者 AND 的区别,但是后面在官网发现是 JOIN 的区别!

官网地址:github.com/Tencent/API…

直接搜:LEFT,就可以搜到!

image.png

这里巨坑:菜鸟用这个直接导致了一个重大级bug,让用户可以看见别的用户的数据了,直接凉凉!后续将|/Project/projectId@ 改成了 |/Project/projectId@,&/User/id@ 算是解决了,但是不清楚为什么可以解决!(菜鸟不是很懂 JOIN)

这里可以看菜鸟github上的提问:github.com/Tencent/API…

修改数据库(新增/修改)

上面展示的都是查询语句,但是apijson的功能可不止这么简单!其还可以由前端去更新数据库,当然正如菜鸟上面所说,所以这里只举例对单个表进行操作!

读者可能会问,为什么只有新增和修改?因为删除一般都是假删,直接修改删除字段等于修改!

新增

// 项目申请
export async function projectApplyApi(params) {
  const data = {
    T_customer_project_apply: params,
    tag: "T_customer_project_apply" // 后端定义
  }
  data["T_customer_project_apply"]["user_id"] = JSON.parse(localStorage.getItem("user")).id
  // baseURL就是后端的请求地址,见下方红框
  const res = request({ url: `${baseURL}/post`, method: "POST", data })
  return res
}

修改

// 驳回项目
export async function rejectApplyApi(params) {
  const data = {
    T_customer_project_apply: params,
    tag: "T_customer_project_apply" // 后端定义
  }
  // baseURL就是后端的请求地址,见下方红框
  const res = request({ url: `${baseURL}/put`, method: "POST", data })
  return res
}

image.png

  1. 这里新增一般是post/修改是put/获取是get。其实我们前端请求的是apijson提供的请求地址,所以全部都是一样的,只是请求方式不一样 + 你传递的参数不一样apijson会通过参数去查询对应的数据库,所以给我们的感觉和后端一般的接口每一个都是一个路径的感觉不一样!

  2. 这里的params就按照我们正常的对象结构就行(修改和创建都是直接把需要 填/改 的数据库字段名 [一定要和数据库字段名一样] 和对应的值传过去就行),如下:

image.png

  1. 还有一个槽点,就是如果你传入的结构不是上图这样,而是这样没有外面一层,apijson不会报错,但是也不会成功加入数据库!(推荐让后端给你postman的分享链接,你请求后的结果和后端测试的对比一下,不同的话,可能就是菜鸟说的这个原因)

image.png

  1. 感觉 apijson 更适合后端使用!对前端不太友好!后续将不会再更新此篇文章,菜鸟公司的后端后续还是决定自己写,不让前端操作数据库了!大家不懂的还是直接github上提问吧!菜鸟感觉 apijson 只适合简单的项目使用!