Appearance
@hiapi/hiapi-cloud-admin-lib
源码:hiapi-cloud-admin-lib/(仓库根目录)· 当前 0.0.13 · main: src(发的是 TS 源码)
管理后台的公共层:HTTP 客户端、列表页组件、鉴权、验证码、库内文案 i18n。 消费方三个:hiapi-cloud-admin-ts、hiapi-cloud-shop-admin、vem-admin(都是 ^0.0.13)。
改了源码,下游看不见
main: src 容易让人以为改完立刻生效 —— 不会。下游 node_modules 里是 pnpm 指向 registry 版本的软链。必须走完:改源码 → npm version patch → npm publish --access public → 回下游手改版本号字符串 → pnpm install。
useApi()
ts
import {useApi} from '@hiapi/hiapi-cloud-admin-lib/src/utils/api'
const api = useApi()HTTP
ts
get <T>(url, params = {}) // 数组参数自动 join(',')
post<T>(url, data = {}, params = {}) // ⚠️ 第二个 body,第三个 query
put <T>(url, data = {}, params = {}) // ⚠️ 同上
request<T>(config: CustomRequestConfig)
upload(url, file: File, params, onUploadProgress?)参数顺序和 HiapiUtils 是反的
ts
useApi().post(url, data, params) // 先 body
HiapiUtils.post(url, params, data) // 先 query2026-08-22 在 shop-admin 一次修掉 22 处 post(url, {}, payload) —— payload 全跑 query、body 空,而那些接口全是 @RequestBody,HTTP 200 但什么都没做。 详见一号陷阱。
只发 body(最常见):api.post(url, payload)只发 query(后端是 @RequestParam):api.post(url, {}, {id})
get 会把数组参数 join(',') —— 后端按逗号分隔字符串接。别自己再 join 一遍。
快捷业务方法
ts
apiQuery<T>(url, data) // 自动拼 /query 并 GET → 配合 BasicQueryController
apiPost <T>(url, data) // data.id 存在 → /edit,否则 → /add
postConfirm<T>(msg, url, params, data) // ⚠️ 第三个 params、第四个 datapostConfirm 又是另一个顺序
postConfirm(msg, url, params, data) —— 内部调 post(url, data, params)。 所以只发 body 时写 postConfirm(msg, url, {}, payload)。 三个方法三种顺序,写的时候老实回来看这一页。
apiQuery 是列表页的标准取数:
ts
const onLoad = (data: PageRequestParams) => api.apiQuery('/cloud-shop/merchant/shop/product', data)
// → GET /cloud-shop/merchant/shop/product/query?page=&size=&...反馈与弹窗
ts
showNotify(msg, title, type)
showNotifySuccess(msg) / showNotifyError(msg)
showAlert(msg, title?) // ElMessageBox.alert
showConfirm(msg, title?) // ElMessageBox.confirm,取消是 reject
copy(text) // clipboard.js,自带成功/失败提示showConfirm 的取消走 reject —— 不接住就是一条 unhandled rejection。
导航
ts
go(url, query = {}) // http 开头 → window.open;否则 HiapiUtils.href
r(url, query = {}) // redirect 语义
back(delta = 1)请求层内建行为(别重复实现)
baseURL: '/api'- 自动带
Authorization: Bearer <token> code === 401→ 跳/login?redirect=...,已在/login时不跳 (这根保险丝是为了挡"401 → 跳转 → 路由钩子再请求 → 401"死循环,不要删)code为402 / 403→ 跳/403- 其余非 200:
showError时弹错误通知,并reject(res) showLoading为 true 时挂全屏 loading;未显式给showLoading时showError被置为 true
HiapiUtilsInit()
把 HiapiUtils 的网络与弹窗方法接到本库的 axios 实例上,供后台里只认 HiapiUtils 的共享代码(装修 widget、上传器)使用。三个后台的 main.ts 都调它。
ts
import {HiapiUtilsInit} from '@hiapi/hiapi-cloud-admin-lib'
HiapiUtilsInit()它接了:get / post / put / delete / showToast / showAlert / showConfirm。
2026-08-22 修了两个 bug
post/put的形参照HiapiUtils命名(params, data),实参却按位置透传给useApi().post—— body 与 query 整个对调。HiapiUtils.delete实现成api.get(url, params)—— DELETE 静默降级成 GET, 请求打到查询接口,不报错也没删掉任何东西。
两处当时都没有调用点(所以从未暴露),但共享 widget 一进来就会中招。 这是"适配时不要透传"的典型反面样本。
TablePage
ts
import TablePage from '@hiapi/hiapi-cloud-admin-lib/src/components/TablePage/index.vue'
import type {PageRequestParams, TableColumn, TableHeader} from '@hiapi/hiapi-cloud-admin-lib/src/types'vue
<TablePage :header="header" :columns="columns" :request="onLoad" :query="query"/>所有页面级标准分页列表一律用它,不要手写 el-table + 分页。 完整 props / 列类型 / 插槽见管理后台前端规范。
要点:
header[].key就是查询参数名,用户输入自动并进request的入参columns[].type:render(返回 VNode,用h())/date/money(正绿负红,读row.scale/row.symbol)/buttons/index/image/selectionquery是每次都带的固定参数(默认排序放这里)request必须返回{data: [], total: number}- ref 上有
reload(data?)
不适用的场景:接口不是标准 /query 分页(自定义 /list、子组件内的小表格)。
其它导出
ts
// 鉴权(js-cookie)
import {getToken, setToken, removeToken} from '@hiapi/hiapi-cloud-admin-lib/src/utils/auth'
// 验证码
import {captchaInit, showCaptcha, setCaptchaLocale} from '.../utils/captcha'
showCaptcha(): Promise<string> // resolve 出票据
// 库内文案语言(宿主切语言时调用)
import {setLibLocale, libLocale, libT, type LibLang} from '@hiapi/hiapi-cloud-admin-lib'
// 布局
import TableLayout from '.../components/TableLayout/index.vue'removeToken() 之外别忘了清 store —— 只清 cookie 会留下"看着已登录、请求全 401"的状态。
依赖约束
peer 级别的现实依赖:vue ^3.5、element-plus ^2.13、axios ^1.15、 @hiapi/hiapi-cloud-web-basic >=0.0.22、clipboard、js-cookie。 下游不要装不同大版本的 Element Plus。