199 lines
5.1 KiB
TypeScript
199 lines
5.1 KiB
TypeScript
import { RequestMethod } from 'umi-request';
|
|
import { request as req } from './schemas';
|
|
|
|
export interface ResourceOptions {
|
|
resourceName: string;
|
|
associatedIndex?: any;
|
|
associatedName?: string;
|
|
resourceIndex?: any;
|
|
}
|
|
|
|
export interface GetOptions {
|
|
resourceIndex?: any;
|
|
defaultAppends?: any[];
|
|
appends?: string[];
|
|
}
|
|
|
|
export interface SaveOptions {
|
|
resourceIndex?: any;
|
|
}
|
|
|
|
export interface ListOptions {
|
|
defaultFilter?: any;
|
|
filter?: any;
|
|
pageSize?: number;
|
|
defaultAppends?: any[];
|
|
appends?: string[];
|
|
perPage?: number;
|
|
}
|
|
|
|
export class Resource {
|
|
public options: ResourceOptions;
|
|
public request: RequestMethod;
|
|
|
|
constructor(options: string | ResourceOptions, request?: any) {
|
|
if (typeof options === 'string') {
|
|
this.options = { resourceName: options };
|
|
} else {
|
|
this.options = options;
|
|
}
|
|
this.request = request || req;
|
|
}
|
|
|
|
sort(options) {
|
|
const { resourceName } = this.options;
|
|
const { resourceIndex, target, field = 'sort' } = options;
|
|
return this.request(`${resourceName}:sort/${resourceIndex}`, {
|
|
method: 'post',
|
|
data: {
|
|
target,
|
|
field,
|
|
},
|
|
});
|
|
}
|
|
|
|
list(options: ListOptions = {}) {
|
|
const {
|
|
defaultAppends = [],
|
|
appends = [],
|
|
defaultFilter,
|
|
filter,
|
|
pageSize,
|
|
...others
|
|
} = options;
|
|
const { associatedIndex, associatedName, resourceName } = this.options;
|
|
let url = `${resourceName}:list`;
|
|
if (associatedName && associatedIndex) {
|
|
url = `${associatedName}/${associatedIndex}/${resourceName}:list`;
|
|
}
|
|
return this.request(url, {
|
|
method: 'get',
|
|
params: {
|
|
filter: decodeURIComponent(
|
|
JSON.stringify({ and: [defaultFilter, filter].filter(Boolean) }),
|
|
),
|
|
'fields[appends]': defaultAppends.concat(appends).join(','),
|
|
perPage: pageSize,
|
|
...others,
|
|
},
|
|
});
|
|
}
|
|
|
|
get(options: GetOptions = {}) {
|
|
const resourceIndex = options.resourceIndex || this.options.resourceIndex;
|
|
const { resourceName } = this.options;
|
|
if (!resourceIndex) {
|
|
return Promise.resolve({ data: {} });
|
|
}
|
|
const { defaultAppends = [], appends = [], ...others } = options;
|
|
return this.request(`${resourceName}:get/${resourceIndex}`, {
|
|
params: {
|
|
...others,
|
|
'fields[appends]': defaultAppends.concat(appends).join(','),
|
|
},
|
|
});
|
|
}
|
|
|
|
create(values: any) {
|
|
const { associatedIndex, associatedName, resourceName } = this.options;
|
|
let url = `${resourceName}:create`;
|
|
if (associatedIndex && associatedName) {
|
|
url = `${associatedName}/${associatedIndex}/${url}`;
|
|
}
|
|
return this.request(url, {
|
|
method: 'post',
|
|
data: values,
|
|
});
|
|
}
|
|
|
|
save(values: any, options: SaveOptions = {}) {
|
|
const resourceIndex = options.resourceIndex || this.options.resourceIndex;
|
|
const { associatedIndex, associatedName, resourceName } = this.options;
|
|
let url = `${resourceName}:${
|
|
resourceIndex ? `update/${resourceIndex}` : 'create'
|
|
}`;
|
|
if (associatedIndex && associatedName) {
|
|
url = `${associatedName}/${associatedIndex}/${url}`;
|
|
}
|
|
return this.request(url, {
|
|
method: 'post',
|
|
data: values,
|
|
});
|
|
}
|
|
|
|
export(options: any) {
|
|
const { resourceName } = this.options;
|
|
const { columns, ...others } = options;
|
|
const url = `${resourceName}:export`;
|
|
return this.request(url, {
|
|
method: 'post',
|
|
params: {
|
|
columns: JSON.stringify(columns),
|
|
...others,
|
|
},
|
|
parseResponse: false,
|
|
responseType: 'blob',
|
|
}).then(async (response: Response) => {
|
|
const filename = decodeURI(
|
|
response.headers
|
|
.get('Content-Disposition')
|
|
.replace('attachment; filename=', ''),
|
|
);
|
|
// ReadableStream
|
|
let res = new Response(response.body);
|
|
let blob = await res.blob();
|
|
let url = URL.createObjectURL(blob);
|
|
let a = document.createElement('a');
|
|
a.style.display = 'none';
|
|
a.href = url;
|
|
a.download = filename;
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
// cleanup
|
|
URL.revokeObjectURL(url);
|
|
document.body.removeChild(a);
|
|
a = null;
|
|
blob = null;
|
|
url = null;
|
|
res = null;
|
|
});
|
|
}
|
|
|
|
destroy(filter: any) {
|
|
const { resourceName } = this.options;
|
|
const url = `${resourceName}:destroy`;
|
|
return this.request(url, {
|
|
method: 'get',
|
|
params: {
|
|
filter,
|
|
},
|
|
});
|
|
}
|
|
|
|
toggle(options?: any) {
|
|
const { associatedIndex, associatedName, resourceName } = this.options;
|
|
const { resourceIndex } = options;
|
|
let url = `${associatedName}/${associatedIndex}/${resourceName}:toggle/${resourceIndex}`;
|
|
return this.request(url, {
|
|
method: 'post',
|
|
});
|
|
}
|
|
|
|
static make(
|
|
options: null | string | Resource | ResourceOptions,
|
|
request?: any,
|
|
): Resource | null {
|
|
if (typeof options === 'string') {
|
|
return new this({ resourceName: options }, request);
|
|
}
|
|
if (options instanceof Resource) {
|
|
return options;
|
|
}
|
|
if (typeof options === 'object' && options.resourceName) {
|
|
return new this(options, request);
|
|
}
|
|
console.warn('resource 初始化参数错误');
|
|
return null;
|
|
}
|
|
}
|