| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- /**
- * 领域接口服务的共用底座(票 05)。
- *
- * 三个领域模块(`mapApi` / `detailApi` / `runtimeApi`)都做同一件事:
- * 拼查询串 → 走票 04 的 `requestCockpitJson` → 用 `sectionFromResult` 收成一个分区。
- * 这段样板收在这里,领域模块只留「路径 + 转换函数 + 空判据」。
- *
- * 分工不变(票 04 的票面):地址拼接、凭据、mock/real 切换全在 `cockpitApi.js`;
- * 本文件与领域模块**不出现** `Authorization`,也读不到令牌。
- */
- import { requestCockpitJson } from './cockpitApi.js'
- import { sectionFromResult } from '../domain/sectionState.js'
- /** 拼查询串;空值(undefined/null/'')跳过,数组按重复键展开。 */
- export function buildQuery(params) {
- const search = new URLSearchParams()
- for (const [key, value] of Object.entries(params || {})) {
- if (value === undefined || value === null || value === '') continue
- if (Array.isArray(value)) {
- for (const item of value) {
- if (item !== undefined && item !== null && item !== '') search.append(key, String(item))
- }
- continue
- }
- search.append(key, String(value))
- }
- const text = search.toString()
- return text ? `?${text}` : ''
- }
- /**
- * 取一个分区。
- * @param {string} path 领域路径
- * @param {object} [options]
- * @param {object} [options.params] 查询参数
- * @param {(raw: any) => any} [options.toData] 载荷 → 领域对象
- * @param {(raw: any) => boolean} [options.isEmpty] 空数据判据
- * @param {(raw: any) => string} [options.freshnessOf] 取新鲜度字符串
- * @param {object} [options.config] / [options.fetchImpl] 单测注入
- */
- export async function fetchSection(path, options = {}) {
- const result = await requestCockpitJson(`${path}${buildQuery(options.params)}`, {
- config: options.config,
- fetchImpl: options.fetchImpl,
- })
- return sectionFromResult(result, {
- toData: options.toData,
- isEmpty: options.isEmpty,
- freshnessOf: options.freshnessOf,
- })
- }
- /** 「列表长度为 0」这类通用空判据。 */
- export function isEmptyBy(predicate) {
- return (payload) => {
- try {
- return !!predicate(payload)
- } catch {
- // 载荷形状意外时不要当成空——交给转换层记 missing,别静默显示「无数据」。
- return false
- }
- }
- }
|