Skip to content

Commit

Permalink
feat(uni): useCrud
Browse files Browse the repository at this point in the history
  • Loading branch information
SoulLyoko committed Oct 13, 2022
1 parent 14677f4 commit 38690c3
Show file tree
Hide file tree
Showing 18 changed files with 1,219 additions and 680 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
"typecheck": "vue-tsc --noEmit"
},
"devDependencies": {
"@antfu/eslint-config": "^0.27.0",
"@commitlint/cli": "^17.1.2",
"@commitlint/config-conventional": "^17.1.0",
"@dcloudio/types": "^3.0.15",
"@iconify/vue": "4.0.0",
"@jsdevtools/version-bump-prompt": "^6.1.0",
"@smallwei/avue": "^3.2.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/composables/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
"dependencies": {
"@yusui/types": "workspace:*",
"@yusui/utils": "workspace:*",
"element-plus": "^2.2.17",
"lodash": "4.17.21",
"lodash-es": "4.17.21",
"lodash-unified": "1.0.2"
},
"devDependencies": {
"@types/lodash-es": "^4.17.6",
"element-plus": "^2.2.17",
"vue": "^3.2.37"
}
}
2 changes: 1 addition & 1 deletion packages/composables/use-crud/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function useCrud<T extends Data = Data, P extends Data = Data>(options: U
afterClose: afterCloseHook
} = useHooks<T, P>();

/** crudMethods */
/** methods */
let {
getDataList,
handleSave,
Expand Down
12 changes: 6 additions & 6 deletions packages/composables/use-crud/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ export function useCrudMethods<T extends Data, P extends Data>({
* @param {Function} loading 为表单停止loading函数
*/
const handleSave = async (row: T, done?: () => void, loading?: () => void) => {
const { create } = crudState.crudOption;
const { rowKey, create } = crudState.crudOption;
if (!create) return loading?.();
const data = cloneDeep({ ...crudState.formData, ...row });
const [err] = await to(emitter.emitAsync("beforeSave", data));
if (err !== null) return loading?.();
delete data[crudState.crudOption.rowKey];
delete data[rowKey];
try {
const res = await create(filterRow(data));
ElMessage.success("保存成功");
Expand Down Expand Up @@ -99,14 +99,14 @@ export function useCrudMethods<T extends Data, P extends Data>({
* @param {Object} row 行数据
*/
const handleDel = async (row: T) => {
const { remove } = crudState.crudOption;
const { rowKey, remove } = crudState.crudOption;
if (!remove) return;
const data = cloneDeep(row);
const [err] = await to(emitter.emitAsync("beforeDel", data));
if (err !== null) return;
await ElMessageBox.confirm("确认进行删除操作?", "提示", { type: "warning" });
try {
const res = await remove(data[crudState.crudOption.rowKey]);
const res = await remove(data[rowKey]);
ElMessage.success("删除成功");
await emitter.emitAsync("afterDel", res);
return getDataList();
Expand All @@ -118,7 +118,7 @@ export function useCrudMethods<T extends Data, P extends Data>({
* 批量删除
*/
const batchDel = async () => {
const { remove } = crudState.crudOption;
const { rowKey, remove } = crudState.crudOption;
if (!remove) return;
const data = cloneDeep(crudState.dataSelections);
const [err] = await to(emitter.emitAsync("beforeBatchDel", data));
Expand All @@ -127,7 +127,7 @@ export function useCrudMethods<T extends Data, P extends Data>({
if (!length) return ElMessage.warning("请选择删除项");
await ElMessageBox.confirm(`确认删除所选的${length}条数据?`, "提示", { type: "warning" });
const ids = data
.map(item => item[crudState.crudOption.rowKey])
.map(item => item[rowKey])
// 根据后端接口传数组或者逗号拼接的字符串
.join(",");
try {
Expand Down
10 changes: 5 additions & 5 deletions packages/composables/use-crud/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ export interface CrudState<T, P> {
mockCache: string;
}

export interface UseCrudStateOptions<T, P> extends Partial<Omit<CrudState<T, P>, "crudOption" | "pageOption">> {
crudOption?: Partial<CrudOption<T, P>>;
pageOption?: PageOption;
}

export type Emitter<T, P> = EmitterAsync<{
beforeGetList: P;
afterGetList: any;
Expand All @@ -75,6 +70,11 @@ export type Emitter<T, P> = EmitterAsync<{
afterClose: FormType;
}>;

export interface UseCrudStateOptions<T, P> extends Partial<Omit<CrudState<T, P>, "crudOption" | "pageOption">> {
crudOption?: Partial<CrudOption<T, P>>;
pageOption?: PageOption;
}

export type UseCrudMethodsReturns = ReturnType<typeof useCrudMethods>;

export type UseCrudOptions<T, P> = UseCrudStateOptions<T, P> & Partial<UseCrudMethodsReturns>;
3 changes: 3 additions & 0 deletions packages/eslint-config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ module.exports = {
node: true,
jest: true
},
globals: {
uni: "readonly"
},
parser: "vue-eslint-parser",
parserOptions: {
parser: "@typescript-eslint/parser",
Expand Down
1 change: 1 addition & 0 deletions packages/uni/composables/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./use-crud";
52 changes: 52 additions & 0 deletions packages/uni/composables/use-crud/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { Emitter } from "./types";

import { mittAsync } from "@yusui/utils";

export function useHooks<T, P>() {
/** emitter */
const emitter = mittAsync() as Emitter<T, P>;
/** 获取列表数据前 beforeGetList((params)=>{}) */
const beforeGetList = (cb: (params: P) => Promise<any> | any | void) => {
emitter.on("beforeGetList", async (...arg) => await cb?.(...arg));
};
/** 获取列表数据后 afterGetList((res)=>{}) */
const afterGetList = (cb: (res: any) => Promise<any> | any | void) => {
emitter.on("afterGetList", async (...arg) => await cb?.(...arg));
};
/** 删除数据前 beforeDel((row)=>{}) */
const beforeDel = (cb: (row: T) => Promise<any> | any | void) => {
emitter.on("beforeDel", async (...arg) => await cb?.(...arg));
};
/** 删除数据后 afterDel((res)=>{}) */
const afterDel = (cb: (res: any) => Promise<any> | any | void) => {
emitter.on("afterDel", async (...arg) => await cb?.(...arg));
};
/** 获取表单数据前 beforeGetInfo((urlFormData)=>{}) */
const beforeGetInfo = (cb: (urlFormData: any) => Promise<any> | any | void) => {
emitter.on("beforeGetInfo", async (...arg) => await cb?.(...arg));
};
/** 获取表单数据后 afterGetInfo((res)=>{}) */
const afterGetInfo = (cb: (res: any) => Promise<any> | any | void) => {
emitter.on("afterGetInfo", async (...arg) => await cb?.(...arg));
};
/** 提交数据前,可对form内的数据进行修改 beforeSubmit((form)=>{}) */
const beforeSubmit = (cb: (form: T) => Promise<any> | any | void) => {
emitter.on("beforeSubmit", async (...arg) => await cb?.(...arg));
};
/** 提交数据后 afterSubmit((res)=>{}) */
const afterSubmit = (cb: (res: any) => Promise<any> | any | void) => {
emitter.on("afterSubmit", async (...arg) => await cb?.(...arg));
};

return {
emitter,
beforeGetList,
afterGetList,
beforeDel,
afterDel,
beforeGetInfo,
afterGetInfo,
beforeSubmit,
afterSubmit
};
}
110 changes: 110 additions & 0 deletions packages/uni/composables/use-crud/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import type { Data } from "@yusui/types";
import type { UseCrudOptions } from "./types";

import { ref, computed, toRefs } from "vue";

import { useCrudState } from "./state";
import { useHooks } from "./hooks";
import { useCrudMethods } from "./methods";
import { useLifeCycle } from "./lifeCycle";

export function useCrud<T extends Data = Data, P extends Data = Data>(options: UseCrudOptions<T, P>) {
/** listRef.value等同于this.$refs.listRef */
const listRef = ref();
/** formRef.value等同于this.$refs.formRef */
const formRef = ref();

/** state */
const crudState = useCrudState(options);
const crudStateRefs = toRefs(crudState);

/** hooks */
const {
emitter,
beforeGetList,
afterGetList,
beforeDel,
afterDel,
beforeGetInfo,
afterGetInfo,
beforeSubmit,
afterSubmit
} = useHooks();

/** methods */
let {
getDataList,
handleDel,
loadMore,
handleRefresh,
handleSearch,
filterChange,
handleAdd,
handleEdit,
handleView,
getFormData,
handleSubmit
// @ts-ignore
} = useCrudMethods({ crudState, emitter });

/** 重置 */
getDataList = options.getDataList ?? getDataList;
handleDel = options.handleDel ?? handleDel;
loadMore = options.loadMore ?? loadMore;
handleRefresh = options.handleRefresh ?? handleRefresh;
handleSearch = options.handleSearch ?? handleSearch;
filterChange = options.filterChange ?? filterChange;
handleAdd = options.handleAdd ?? handleAdd;
handleEdit = options.handleEdit ?? handleEdit;
handleView = options.handleView ?? handleView;
getFormData = options.getFormData ?? getFormData;
handleSubmit = options.handleSubmit ?? handleSubmit;

/** 使用v-bind绑定的值 */
const bindVal = computed(() => ({
// 属性
ref: "listRef",
data: crudState.listData,
option: crudState.listOption ?? {}, //列表配置
// filterForm: crudState.searchForm,
status: crudState.loadStatus,
scrollTop: crudState.scrollTop,
searchValue: crudState.searchForm[crudState.crudOption.searchKey] ?? "",
// 事件
onSearch: handleSearch,
onLoadmore: loadMore,
// onFilterChange: filterChange,
"onUpdate:filterForm": (form: any) => Object.assign(crudState.searchForm, form),
"onUpdate:searchValue": (val: any) => (crudState.searchForm[crudState.crudOption.searchKey] = val)
}));

/** 使用一些默认的生命周期 */
useLifeCycle({ crudState, loadMore, handleRefresh });

return {
listRef,
formRef,
crudState,
crudStateRefs,
bindVal,
getDataList,
handleDel,
loadMore,
handleRefresh,
handleSearch,
filterChange,
handleAdd,
handleEdit,
handleView,
getFormData,
handleSubmit,
beforeGetList,
afterGetList,
beforeDel,
afterDel,
beforeGetInfo,
afterGetInfo,
beforeSubmit,
afterSubmit
};
}
20 changes: 20 additions & 0 deletions packages/uni/composables/use-crud/lifeCycle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { onReachBottom, onPullDownRefresh, onPageScroll } from "@dcloudio/uni-app";

export const useLifeCycle = ({ crudState, loadMore, handleRefresh }: any) => {
/** 触底加载更多数据 */
onReachBottom(() => {
const { isReachBottom } = crudState.crudOption;
isReachBottom && loadMore();
});
/** 下拉刷新 */
onPullDownRefresh(() => {
const { isPullDown } = crudState.crudOption;
isPullDown && handleRefresh();
});
/** @ts-ignore 返回顶部按钮 */
onPageScroll(e => {
if (crudState.crudOption.isSrollTop) {
crudState.scrollTop = e.scrollTop;
}
});
};
Loading

0 comments on commit 38690c3

Please sign in to comment.