123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- import { computed, reactive } from "vue";
- export class StateRoot {
- protected computed<F extends (state: Omit<this, "reactive">) => any>(fn: F) {
- return fn as ReturnType<F>;
- }
- reactive = () => {
- return createReactive(this) as Omit<this, "reactive">;
- };
- }
- function createReactive(obj: any) {
- const data: any = {};
- for (const name in obj) {
- if (name === "reactive" || name === "computed" || name === "proxy")
- continue;
- const objItem: any = obj[name];
- if (objItem instanceof Function) {
- data[name] = computed(() => objItem(state));
- } else {
- data[name] = objItem;
- }
- }
- const state: any = reactive(data);
- return state;
- }
- class ListItemBase {
- _id?: string = "";
- }
- class StatePageList<T extends ListItemBase, Q> extends StateRoot {
- size = 10;
- page = 1;
- total = 0;
- list: T[] = [];
- query: Q = {} as any;
- fields = ""; //字段使用逗号隔开
- loading = false;
- canLoadNext = this.computed((state) => {
- const { size, page, total } = state;
- return page * size < total;
- });
- }
- /**
- * 分页列表控制器
- */
- export class ListController<T extends ListItemBase, Q> {
- state = new StatePageList<T, Q>().reactive();
- request: any;
- dataList: any[] = [];
- httpGet?: (
- page: number,
- size: number,
- query?: any,
- fields?: string
- ) => Promise<any>;
- httpDelete?: (id: string) => Promise<any>;
- httpDetail?: (id: string) => Promise<any>;
- httpAdd?: (query?: any) => Promise<any>;
- httpSave?: (item: T) => Promise<any>;
- hasLimit = false;
- listFilter: ((item: T) => T) | null = null;
- constructor(
- request: any,
- get?: () => (
- page: number,
- size: number,
- query?: any,
- fields?: string
- ) => Promise<any>
- ) {
- this.request = request;
- if (get) {
- this.httpGet = get();
- }
- }
- crud(
- prefix: string,
- type: "list" | "create" | "update" | "delete" | "detail",
- data?: any
- ) {
- const config: any = { method: "POST" };
- if (type == "list") {
- config.method = "GET";
- config.params = data;
- } else if (type == "detail") {
- config.method = "GET";
- } else {
- config.data = data;
- }
- let uri = `${prefix}/${type}`;
- if (type == "delete" || type == "detail") uri += `/${data}`;
- return this.request(uri, config);
- }
- setCrudPrefix(prefix: string) {
- this.httpGet = (
- page: number,
- size: number,
- query: any,
- fields?: string
- ) => {
- return this.crud(prefix, "list", {
- page,
- size,
- query,
- fields,
- });
- };
- this.httpAdd = (data: any) => {
- return this.crud(prefix, "create", data);
- };
- this.httpSave = (data: any) => {
- return this.crud(prefix, "update", data);
- };
- this.httpDelete = (id: string) => {
- return this.crud(prefix, "delete", id);
- };
- this.httpDetail = (id: string) => {
- return this.crud(prefix, "detail", id);
- };
- }
- async resumeShow() {
- if (this.state.list.length < 1) {
- await this.loadPage(1);
- }
- }
- //刷新页面,重新获取数据
- async fresh() {
- await this.loadPage(this.state.page, this.state.size);
- if (this.state.list.length == 0 && this.state.page != 1) {
- await this.loadPage(this.state.page - 1, this.state.size);
- }
- }
- loadNextPage = () => {
- return this.loadPage(this.state.page + 1);
- };
- async loadPage(page: number, size?: number): Promise<boolean> {
- if (!this.httpGet) return false;
- this.state.loading = true;
- if (!size) size = this.state.size;
- const ret = await this.httpGet(
- page,
- size,
- this.state.query,
- this.state.fields
- );
- this.state.loading = false;
- if (ret.errorNo == 200) {
- const result = ret.result;
- this.state.page = page;
- this.state.size = size;
- let list = [];
- if (this.listFilter) {
- list = result.list.map(this.listFilter) || [];
- } else {
- list = [...result.list];
- }
- if (page == 1 || !this.hasLimit) {
- this.dataList = [...result.list];
- this.state.list = list;
- } else {
- this.state.list = [...this.state.list, ...list];
- this.dataList = [...this.dataList, ...result.list];
- }
- setTimeout(() => {
- this.state.total = result.total;
- }, 100);
- return true;
- }
- return false;
- }
- async addItem(data: ListItemBase) {
- if (!this.httpAdd) return { errorNo: 500, errorDesc: "httpAdd 未定义" };
- this.state.loading = true;
- const ret = await this.httpAdd(data);
- this.state.loading = false;
- if (ret.errorNo == 200) {
- await this.fresh();
- }
- return ret;
- }
- async deleteItem(id: string) {
- if (!this.httpDelete) return;
- this.state.loading = true;
- const ret = await this.httpDelete(id);
- this.state.loading = false;
- if (ret.errorNo == 200) {
- await this.fresh();
- }
- return ret;
- }
- async saveItem(item: T) {
- if (!this.httpSave) return;
- this.state.loading = true;
- const ret = await this.httpSave(item);
- this.state.loading = false;
- if (ret.errorNo == 200) {
- await this.fresh();
- }
- return ret;
- }
- async itemDetail(id: string) {
- if (!this.httpDetail) return;
- this.state.loading = true;
- const ret = await this.httpDetail(id);
- this.state.loading = false;
- return ret;
- }
- }
|