UNPKG

dua

Version:
240 lines (233 loc) 7.34 kB
import { DuaApi, DuaModel, Option } from "./types"; import driver from "./driver"; export default function create<T>( namespace: string, api: DuaApi, option?: Option ): DuaModel<T> { const { fetch, fetchPart, create, update, remove, detail } = api; const type = (option && option.type) || "flat"; const drive = (option && option.drive) || driver.get(type); if (!drive) { throw new Error(`no drive for this type [${type}]`); } const { transform, normalize, mixed } = drive; const reduce = drive.reduce; return { namespace, state: { byId: {}, allIds: [], total: 0, }, effects: { *fetch({ payload }, { call, put, select }) { if (fetch) { const response = yield call(fetch, payload); if (response && (response.code === 200 || response.code === 0)) { //TODO这个retlist是java的,以后肯定要一致 const list = response.data.list || response.data.retlist || response.data || []; const total = response.data.total || list.length; const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onFetch", payload: { list, total, __extra__, }, }); return response || true; } } return false; }, *fetchPart({ payload }, { call, put, select }) { if (fetchPart) { const response = yield call(fetchPart, payload); if (response && (response.code === 200 || response.code === 0)) { const list = response.data.list || response.data || []; const total = response.data.total; const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onFetchPart", payload: { list, total, __extra__, }, }); return response || true; } } return false; }, *create({ payload }, { call, put, select }) { if (create) { const response = yield call(create, payload); if (response && (response.code === 200 || response.code === 0)) { const data = response.data; const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onCreate", payload: { ...payload, ...data, __extra__, }, }); return response || true; } } return false; }, *update({ payload }, { call, put, select }) { if (update) { const { id, ...otherData } = payload || {}; const response = yield call(update, id || payload, otherData); if (response && (response.code === 200 || response.code === 0)) { const data = response.data; const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onUpdate", payload: { ...payload, ...data, __extra__, }, }); return response || true; } } return false; }, *remove({ payload }, { call, put, select }) { if (remove) { const id = (payload && payload.id) || payload; const response = yield call(remove, id); if (response && (response.code === 200 || response.code === 0)) { const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onRemove", payload: { id: id, __extra__ }, __extra__, }); return response || true; } } return false; }, *detail({ payload }, { call, put, select }) { if (detail) { // const id = (payload && payload.id) || payload; const response = yield call(detail, payload); if (response && (response.code === 200 || response.code === 0)) { const data = response.data; const __extra__ = mixed ? yield select((state: any) => state) : null; yield put({ type: "onUpdate", payload: data, __extra__, }); return response || true; } } return false; }, }, reducers: { onFetch(state, { payload }) { const { list, total, __extra__ } = payload; const normalized = normalize(list, total); return reduce({ ...state, ...normalized }, __extra__); }, onFetchPart(state, { payload }) { const { list, total, __extra__ } = payload; function getListByTree(tree: any[]) { return tree.reduce((prev, c) => { if (c.children) { prev = prev.concat(getListByTree(c.children)); } prev = prev.concat({ ...c, children: undefined }); return prev; }, []); } const treeList = getListByTree(state.allIds); const normalized = normalize( [].concat(treeList, list), total ? total : state.total + list.length ); return reduce({ ...state, ...normalized }, __extra__); }, onCreate(state, { payload }) { if (payload && payload.id) { const byId = { ...state.byId, [payload.id]: payload }; const allIds = transform(byId); return reduce( { ...state, byId, allIds, total: state.total + 1 }, payload.__extra__ ); } else { return state; } }, onUpdate(state, { payload }) { if (payload) { if (payload.id) { const byId = { ...state.byId, [payload.id]: { ...state.byId[payload.id], ...payload, }, }; const allIds = transform(byId); return reduce({ ...state, byId, allIds }, payload.__extra__); } else { //如果没有ID的话给他一个固定ID(__id__) const byId = { ...state.byId, __auto_id__: { ...state.byId[payload.id], ...payload, }, }; const allIds = transform(byId); return reduce({ ...state, byId, allIds }, payload.__extra__); } } else { return state; } }, onRemove(state, { payload }) { if (payload && payload.id) { const byId = { ...state.byId }; delete byId[payload.id]; const allIds = transform(byId); return reduce( { ...state, byId, allIds, total: state.total - 1 }, payload.__extra__ ); } else { return state; } }, }, }; }