import { merge, pickBy, isNil, cloneDeep } from "lodash-es"; import type { FindListResult, ArrayUtilsOptions } from "./ArrayUtils"; import ArrayUtils, { STATE_CODE } from "./ArrayUtils"; import type { JSONObject, QueryParams, RequestData, MapFunction, RequestMapFunction, GetListFunc, } from "./type"; const errMsg: Record = { 404: "未找到对应子项", 501: "未传入表单 id", }; /** * ArrayDataModel 构造函数参数接口 */ export interface ArrayDataModelOptions extends ArrayUtilsOptions { /** 请求 url 替换的额外参数 */ ctx?: JSONObject; /** GET 请求的参数 */ query?: QueryParams; /** POST 接口地址 */ createApi?: string; /** POST 接口提交前的数据处理回调 */ createMap?: MapFunction; /** GET 详情 接口地址 */ getApi?: string; /** GET 详情 接口返回后的数据处理回调 */ getMap?: MapFunction; /** GET 列表 接口地址 */ getListApi?: string; /** GET 列表 接口返回后的数据处理回调 */ getListMap?: MapFunction; /** GET 列表 接口回调,用于自定义列表请求接口 */ getListFunc?: GetListFunc; /** PUT 接口地址 */ updateApi?: string; /** PUT 接口提交前的数据处理回调 */ updateMap?: MapFunction; /** PATCH 接口地址 */ patchApi?: string; /** PATCH 接口提交前的数据处理回调 */ patchMap?: MapFunction; /** DELETE 接口地址 */ deleteApi?: string; /** DELETE 批量删除 接口地址 */ multipleDeleteApi?: string; /** GET 列表 接口请求前数据处理回调 */ getListReqMap?: RequestMapFunction; /** GET 列表 接口请求结果数据处理回调 */ getListResMap?: MapFunction; /** GET 详情 接口请求前数据处理回调 */ getReqMap?: RequestMapFunction; /** GET 详情 接口请求结果数据处理回调 */ getResMap?: MapFunction; /** POST 接口请求前数据处理回调 */ createReqMap?: RequestMapFunction; /** POST 接口请求结果数据处理回调 */ createResMap?: MapFunction; /** PUT 接口请求前数据处理回调 */ updateReqMap?: RequestMapFunction; /** PUT 接口请求结果数据处理回调 */ updateResMap?: MapFunction; /** PATCH 接口请求前数据处理回调 */ patchReqMap?: RequestMapFunction; /** PATCH 接口请求结果数据处理回调 */ patchResMap?: MapFunction; /** DELETE 接口请求前数据处理回调 */ deleteReqMap?: RequestMapFunction; /** DELETE 接口请求结果数据处理回调 */ deleteResMap?: MapFunction; /** DELETE 批量删除 接口请求前数据处理回调 */ multipleDeleteReqMap?: RequestMapFunction; /** DELETE 批量删除 接口请求结果数据处理回调 */ multipleDeleteResMap?: MapFunction; /** 查询选项 */ arrOptions?: ArrOptions; } /** * 查询选项 */ export interface ArrOptions { /** 字符串字段是否开启模糊匹配 */ fuzzy?: boolean; /** 模糊匹配时是否忽略大小写 */ ignoreCase?: boolean; } /** * 删除请求配置接口 */ export interface ArrayDeleteConfig { /** axios delete url 参数 */ params?: Record; /** axios delete data 参数 */ data?: Record; /** 其他 axios delete 配置 */ [key: string]: any; } /** * 错误处理选项接口 */ export interface HandleMsgOptions { /** 是否使用 response.statusText 作为兜底 msg */ useStatusText?: boolean; } /** * 批量删除结果接口 */ export interface MultipleDeleteResult { /** 成功删除的 ID 列表 */ sucList: any[]; /** 失败删除的 ID 列表 */ failList: any[]; } /** * ArrayDataModel 本地数据 DataModel * @template T - 数据类型 */ class ArrayDataModel extends ArrayUtils { /** 请求 url 替换的额外参数 */ ctx: Record; /** GET 请求的参数 */ query: QueryParams; /** POST 接口地址 */ createApi?: string; /** POST 接口提交前的数据处理回调 */ createMap?: MapFunction; /** GET 详情 接口地址 */ getApi?: string; /** GET 详情 接口返回后的数据处理回调 */ getMap?: MapFunction; /** GET 列表 接口地址 */ getListApi?: string; /** GET 列表 接口返回后的数据处理回调 */ getListMap?: MapFunction; /** GET 列表 接口回调,用于自定义列表请求接口 */ getListFunc?: GetListFunc; /** PUT 接口地址 */ updateApi?: string; /** PUT 接口提交前的数据处理回调 */ updateMap?: MapFunction; /** PATCH 接口地址 */ patchApi?: string; /** PATCH 接口提交前的数据处理回调 */ patchMap?: MapFunction; /** DELETE 接口地址 */ deleteApi?: string; /** DELETE 批量删除 接口地址 */ multipleDeleteApi?: string; /** GET 列表 接口请求前数据处理回调 */ getListReqMap?: RequestMapFunction; /** GET 列表 接口请求结果数据处理回调 */ getListResMap?: MapFunction; /** GET 详情 接口请求前数据处理回调 */ getReqMap?: RequestMapFunction; /** GET 详情 接口请求结果数据处理回调 */ getResMap?: MapFunction; /** POST 接口请求前数据处理回调 */ createReqMap?: RequestMapFunction; /** POST 接口请求结果数据处理回调 */ createResMap?: MapFunction; /** PUT 接口请求前数据处理回调 */ updateReqMap?: RequestMapFunction; /** PUT 接口请求结果数据处理回调 */ updateResMap?: MapFunction; /** PATCH 接口请求前数据处理回调 */ patchReqMap?: RequestMapFunction; /** PATCH 接口请求结果数据处理回调 */ patchResMap?: MapFunction; /** DELETE 接口请求前数据处理回调 */ deleteReqMap?: RequestMapFunction; /** DELETE 接口请求结果数据处理回调 */ deleteResMap?: MapFunction; /** DELETE 批量删除 接口请求前数据处理回调 */ multipleDeleteReqMap?: RequestMapFunction; /** DELETE 批量删除 接口请求结果数据处理回调 */ multipleDeleteResMap?: MapFunction; /** 查询选项 */ private _arrOptions?: ArrOptions; constructor(params: ArrayDataModelOptions = {} as ArrayDataModelOptions) { super(params); const { ctx, query, createApi, createMap, getApi, getMap, getListApi, getListMap, getListFunc, updateApi, updateMap, patchApi, patchMap, deleteApi, multipleDeleteApi, } = params; this.ctx = ctx || {}; this.query = query || {}; this.createApi = createApi; this.createMap = createMap; this.getApi = getApi; this.getMap = getMap; this.getListApi = getListApi; this.getListMap = getListMap; this.getListFunc = getListFunc; this.updateApi = updateApi; this.updateMap = updateMap; this.patchApi = patchApi; this.patchMap = patchMap; this.deleteApi = deleteApi; this.multipleDeleteApi = multipleDeleteApi; const { getListReqMap, getListResMap, getReqMap, getResMap, createReqMap, createResMap, updateReqMap, updateResMap, patchReqMap, patchResMap, deleteReqMap, deleteResMap, multipleDeleteReqMap, multipleDeleteResMap, arrOptions, } = params || {}; this.getListReqMap = getListReqMap; this.getListResMap = getListResMap; this.getReqMap = getReqMap; this.getResMap = getResMap; this.createReqMap = createReqMap; this.createResMap = createResMap; this.updateReqMap = updateReqMap; this.updateResMap = updateResMap; this.patchReqMap = patchReqMap; this.patchResMap = patchResMap; this.deleteReqMap = deleteReqMap; this.deleteResMap = deleteResMap; this.multipleDeleteReqMap = multipleDeleteReqMap; this.multipleDeleteResMap = multipleDeleteResMap; this._arrOptions = arrOptions; } /** * GET 详情请求 * @param q query 参数 * @returns Promise */ async get(q: QueryParams = {}): Promise { let query = merge({}, this.query, q); query = pickBy(query, (val) => !isNil(val) && val !== ""); if (this.getReqMap) { query = await this.getReqMap(query); } return new Promise((resolve) => { let res = this.findItem(query, this._arrOptions); if (res && this.getMap) { res = this.getMap(res); } if (res && this.getResMap) { res = this.getResMap(res); } resolve(res); }); } /** * GET 列表请求 * @param q query 参数 * @returns Promise> */ async getList(q: QueryParams = {}): Promise> { let query = merge({}, this.query, q); query = pickBy(query, (val) => !isNil(val) && val !== ""); if (this.getListReqMap) { query = await this.getListReqMap(query); } let resultList: FindListResult; if (this.getListFunc) { resultList = await this.getListFunc(query); } else { resultList = await this.findListByQuery(query, this._arrOptions); } const getListMap = this.getListMap; if (getListMap) { resultList.list = resultList?.list?.map((record) => getListMap(record)); } const getListResMap = this.getListResMap; if (getListResMap) { resultList = getListResMap(resultList); } return resultList; } /** * POST 请求 * @param params 参数 * @returns Promise> */ create(params: RequestData | FormData): Promise> { return new Promise(async (resolve, reject) => { const _params = await this.handleInputParams(params, this.createReqMap); const res = this.pushItem(_params); this.handleRes(res, resolve, reject, { resMap: this.createResMap }); }); } /** * PUT 请求 * @param params 参数 * @returns Promise> */ update(params: RequestData | FormData): Promise> { return new Promise(async (resolve, reject) => { const _params = await this.handleInputParams(params, this.updateReqMap); const res = this.replaceItem(_params as T); this.handleRes(res, resolve, reject, { resMap: this.updateResMap }); }); } /** * PATCH 请求 * @param params 参数 * @returns Promise> */ patch(params: RequestData | FormData): Promise> { return new Promise(async (resolve, reject) => { const _params = await this.handleInputParams(params, this.patchReqMap); const res = this.updateItemValue(_params); this.handleRes(res, resolve, reject, { resMap: this.patchResMap }); }); } /** * 删除接口 * @param config axios.delete config 参数 * @param config.params axios.delete url 参数 * @param config.data axios.delete data 参数 * @param ctx url 替换的额外参数 * @returns Promise> */ delete(config?: ArrayDeleteConfig, ctx?: Record): Promise> { let _config = cloneDeep(config) || {}; if (this.deleteReqMap) { _config = this.deleteReqMap(_config); } return new Promise((resolve, reject) => { const { _idKey } = this; const id = (config as any)?.[_idKey] || config?.params?.[_idKey] || config?.data?.[_idKey] || ctx?.[_idKey]; const res = this.delItem(id); this.handleRes(res, resolve, reject, { resMap: this.deleteResMap }); }); } /** * 批量删除接口 * @param config axios.delete config 参数 * @param config.params axios.delete url 参数 * @param config.data axios.delete data 参数 * @param ctx url 替换的额外参数 * @returns Promise */ multipleDelete( config?: ArrayDeleteConfig, ctx?: Record, ): Promise { let _config = cloneDeep(config) || {}; if (this.multipleDeleteReqMap) { _config = this.multipleDeleteReqMap(_config); } return new Promise((resolve, reject) => { const { _idKey } = this; let ids = (config as any)?.[_idKey] || config?.params?.[_idKey] || config?.data?.[_idKey] || ctx?.[_idKey]; if (typeof ids === "string") { ids = ids.split(","); } if (Array.isArray(ids)) { const sucList: any[] = []; const failList: any[] = []; ids.forEach((id: any) => { try { const res = this.delItem(id); if (res === STATE_CODE.SUC) { sucList.push(id); } else { failList.push(id); } } catch (error) { console.log("error", error); } }); if (sucList.length > 0) { let _res: MultipleDeleteResult = { sucList, failList }; if (this.multipleDeleteResMap) { _res = this.multipleDeleteResMap(_res); } resolve(_res); } else { reject({ failList }); } return; } reject({}); }); } /** * 处理传入的数据 * @param params 参数 * @param reqMapFn 请求前处理函数 * @returns 处理后的参数 */ async handleInputParams( params: any, reqMapFn?: (params: Record, originalParams?: any) => Record, ): Promise & Record> { let _params = cloneDeep(params) as Partial & Record; if (reqMapFn) { _params = (await reqMapFn(_params, params)) as Partial & Record; } // TODO: FormData 文件存储? // if (params instanceof FormData) { // _params = objToFormData(_params); // } return _params; } /** * 处理响应结果 * @param response 响应对象 * @param resolve 成功回调 * @param reject 失败回调 */ handleRes(res: any, resolve: (res: any) => void, reject: (err: any) => void, opt?): void { const { resMap } = opt || {}; if (res === STATE_CODE.SUC) { let _res: Record = {}; if (resMap) { _res = resMap(_res); } resolve(_res); } else { reject({ code: res, _message: errMsg[res] || "未知错误", _msg: errMsg[res] || "未知错误", }); } } } export { ArrayDataModel }; export default ArrayDataModel;