支持es编译
This commit is contained in:
parent
be381fbb8b
commit
dbf6034b16
|
|
@ -0,0 +1,74 @@
|
|||
import { EntityDict, OperateOption, SelectOption, OperationResult, AggregationResult } from "oak-domain/lib/types";
|
||||
import { AmapInstance } from "oak-external-sdk";
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { AsyncContext } from "oak-domain/lib/store/AsyncRowStore";
|
||||
export declare type CommonAspectDict<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>> = {
|
||||
operate: <T extends keyof ED, OP extends OperateOption>(params: {
|
||||
entity: T;
|
||||
operation: ED[T]['Operation'] | ED[T]['Operation'][];
|
||||
option?: OP;
|
||||
}, context: Cxt) => Promise<OperationResult<ED>[] | OperationResult<ED>>;
|
||||
select: <T extends keyof ED, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
selection: ED[T]['Selection'];
|
||||
option?: OP;
|
||||
getCount?: true;
|
||||
}, context: Cxt) => Promise<{
|
||||
ids: string[];
|
||||
count?: number;
|
||||
aggr?: (Partial<ED[T]['Schema']> | undefined)[];
|
||||
}>;
|
||||
aggregate: <T extends keyof ED, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
aggregation: ED[T]['Aggregation'];
|
||||
option?: OP;
|
||||
}, context: Cxt) => Promise<AggregationResult<ED[T]['Schema']>>;
|
||||
count: <T extends keyof ED, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
selection: Pick<ED[T]['Selection'], 'filter'>;
|
||||
option?: OP;
|
||||
}, context: Cxt) => Promise<number>;
|
||||
fetchRows: <OP extends SelectOption>(params: Array<{
|
||||
entity: keyof ED;
|
||||
selection: ED[keyof ED]['Selection'];
|
||||
option?: OP;
|
||||
}>, context: Cxt) => Promise<void>;
|
||||
amap: <T extends 'getDrivingPath' | 'regeo' | 'ipLoc' | 'getDistrict' | 'geocode'>(params: {
|
||||
key: string;
|
||||
method: T;
|
||||
data: Parameters<AmapInstance[T]>[0];
|
||||
}) => Promise<any>;
|
||||
getTranslations: (params: {
|
||||
namespace: string | string[];
|
||||
locale: string;
|
||||
}) => Promise<any>;
|
||||
importEntity: (params: FormData, context: Cxt) => Promise<void | ArrayBuffer>;
|
||||
exportEntity: <T extends keyof ED>(params: {
|
||||
entity: T;
|
||||
id: string;
|
||||
filter?: ED[T]['Selection']['filter'];
|
||||
properties?: Record<string, any>;
|
||||
}, context: Cxt) => Promise<ArrayBuffer>;
|
||||
getImportationTemplate: (params: {
|
||||
id: string;
|
||||
}, context: Cxt) => Promise<ArrayBuffer>;
|
||||
searchPoi: (options: {
|
||||
value: string;
|
||||
areaCode?: string;
|
||||
indexFrom?: number;
|
||||
count?: number;
|
||||
typeCode?: string;
|
||||
}) => Promise<{
|
||||
id: string;
|
||||
areaId: string;
|
||||
poiName: string;
|
||||
detail: string;
|
||||
coordinate: [number, number];
|
||||
}[]>;
|
||||
loadRelations: (params: {
|
||||
entities: (keyof ED)[];
|
||||
}, context: Cxt) => Promise<ED['userRelation']['OpSchema'][]>;
|
||||
crossBridge: (params: {
|
||||
url: string;
|
||||
}) => Promise<ReadableStream<Uint8Array>>;
|
||||
};
|
||||
|
|
@ -0,0 +1 @@
|
|||
export {};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { AmapInstance } from 'oak-external-sdk';
|
||||
export declare function amap<T extends 'getDrivingPath' | 'regeo' | 'ipLoc' | 'getDistrict' | 'geocode'>(options: {
|
||||
key: string;
|
||||
method: T;
|
||||
data: Parameters<AmapInstance[T]>[0];
|
||||
}): Promise<any>;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { AmapSDK } from 'oak-external-sdk';
|
||||
export async function amap(options) {
|
||||
const { key, method, data } = options;
|
||||
const instance = AmapSDK.getInstance(key);
|
||||
const fn = instance[method];
|
||||
if (!fn) {
|
||||
throw new Error('method not implemented');
|
||||
}
|
||||
// data any后面再改
|
||||
return fn(data);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import { OperateOption, EntityDict, SelectOption } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
export declare function operate<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends OperateOption>(params: {
|
||||
entity: T;
|
||||
operation: ED[T]['Operation'] | ED[T]['Operation'][];
|
||||
option?: OP;
|
||||
}, context: Cxt): Promise<import("oak-domain/lib/types").OperationResult<ED> | Awaited<import("oak-domain/lib/types").OperationResult<ED>>[]>;
|
||||
export declare function select<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
selection: ED[T]['Selection'];
|
||||
option?: OP;
|
||||
getCount?: true;
|
||||
maxCount?: number;
|
||||
}, context: Cxt): Promise<{
|
||||
ids: string[];
|
||||
count?: number | undefined;
|
||||
aggr?: (Partial<ED[T]["Schema"]> | undefined)[] | undefined;
|
||||
}>;
|
||||
export declare function aggregate<ED extends BaseEntityDict & EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
aggregation: ED[T]['Aggregation'];
|
||||
option?: OP;
|
||||
}, context: Cxt): Promise<import("oak-domain/lib/types").AggregationResult<ED[T]["Schema"]>>;
|
||||
export declare function fetchRows<ED extends EntityDict & BaseEntityDict, OP extends SelectOption, Cxt extends AsyncContext<ED>>(params: Array<{
|
||||
entity: keyof ED;
|
||||
selection: ED[keyof ED]['Selection'];
|
||||
option?: OP;
|
||||
}>, context: Cxt): Promise<void>;
|
||||
export declare function count<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, OP extends SelectOption>(params: {
|
||||
entity: T;
|
||||
selection: Pick<ED[T]['Selection'], 'filter'>;
|
||||
option?: OP;
|
||||
}, context: Cxt): Promise<number>;
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import { OakUserUnpermittedException, } from 'oak-domain/lib/types';
|
||||
import { judgeRelation } from 'oak-domain/lib/store/relation';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
export async function operate(params, context) {
|
||||
const { entity, operation, option } = params;
|
||||
/* const userId = context.getCurrentUserId();
|
||||
if (!userId) {
|
||||
// operate默认必须用户登录
|
||||
throw new OakUnloggedInException();
|
||||
} */
|
||||
if (!context.allowUserUpdate()) {
|
||||
throw new OakUserUnpermittedException('您被禁更新');
|
||||
}
|
||||
if (operation instanceof Array) {
|
||||
const result = [];
|
||||
for (const oper of operation) {
|
||||
const r = await context.operate(entity, oper, option || {});
|
||||
result.push(r);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return await context.operate(entity, operation, option || {});
|
||||
}
|
||||
function pruneAggrResult(schema, entity, result) {
|
||||
const pruneInner = (e, r) => {
|
||||
const r2 = {};
|
||||
let hasAggr = false;
|
||||
for (const attr in r) {
|
||||
if (attr.endsWith('$$aggr')) {
|
||||
hasAggr = true;
|
||||
Object.assign(r2, {
|
||||
[attr]: r[attr],
|
||||
});
|
||||
}
|
||||
else if (typeof r[attr] === 'object') {
|
||||
const rel = judgeRelation(schema, e, attr);
|
||||
if (rel === 2 || typeof rel === 'string') {
|
||||
const rr = pruneInner(rel === 2 ? attr : rel, r[attr]);
|
||||
if (rr) {
|
||||
hasAggr = true;
|
||||
Object.assign(r2, {
|
||||
[attr]: rr,
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (rel instanceof Array) {
|
||||
assert(r[attr] instanceof Array);
|
||||
const rr = r[attr].map((ele) => pruneInner(rel[0], ele));
|
||||
if (rr.find((ele) => !ele)) {
|
||||
hasAggr = true;
|
||||
Object.assign(r2, {
|
||||
[attr]: rr,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasAggr) {
|
||||
return r2;
|
||||
}
|
||||
return;
|
||||
};
|
||||
const result2 = result.map((row) => pruneInner(entity, row));
|
||||
if (result2.find(ele => !!ele)) {
|
||||
return result2;
|
||||
}
|
||||
}
|
||||
export async function select(params, context) {
|
||||
const { entity, selection, option, getCount, maxCount } = params;
|
||||
const { randomRange, count } = selection;
|
||||
let selection2 = selection;
|
||||
if (randomRange) {
|
||||
// 如果是随机取值,这里就从randomRange的ids中随机取
|
||||
const idSelection = Object.assign({}, selection, {
|
||||
indexFrom: 0,
|
||||
count: randomRange,
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
});
|
||||
const idResults = await context.select(entity, idSelection, option || {});
|
||||
const possibility = count / idResults.length;
|
||||
let reduced = idResults.length - count;
|
||||
const ids2 = idResults.map(ele => ele.id).filter((id) => {
|
||||
const rand = Math.random();
|
||||
if (rand > possibility && reduced) {
|
||||
reduced--;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
selection2.filter = {
|
||||
id: {
|
||||
$in: ids2,
|
||||
},
|
||||
};
|
||||
}
|
||||
const data = await context.select(entity, selection2, option || {});
|
||||
const result = {
|
||||
ids: data.map(ele => ele.id),
|
||||
};
|
||||
if (getCount && !randomRange) {
|
||||
const { filter } = selection;
|
||||
const count = await context.count(entity, Object.assign({}, { filter, count: maxCount || 1000 }), option || {});
|
||||
Object.assign(result, {
|
||||
count,
|
||||
});
|
||||
}
|
||||
if (data.length === 0) {
|
||||
}
|
||||
else {
|
||||
const aggrData = pruneAggrResult(context.getSchema(), entity, data);
|
||||
if (aggrData) {
|
||||
result.aggr = aggrData;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export async function aggregate(params, context) {
|
||||
const { entity, aggregation, option } = params;
|
||||
return context.aggregate(entity, aggregation, option || {});
|
||||
}
|
||||
export async function fetchRows(params, context) {
|
||||
await Promise.all(params.map((ele) => context.select(ele.entity, ele.selection, ele.option || {})));
|
||||
}
|
||||
export async function count(params, context) {
|
||||
const { entity, selection, option } = params;
|
||||
const { filter } = selection;
|
||||
const count = await context.count(entity, Object.assign({}, { filter }), option || {});
|
||||
return count;
|
||||
}
|
||||
/*
|
||||
export type AspectDict<ED extends EntityDict> = {
|
||||
operation: <T extends keyof ED>(options: { entity: T, operation: ED[T]['Operation'], params?: OperateParams }, context: Context<ED>) => Promise<OperationResult>;
|
||||
select: <T extends keyof ED, S extends ED[T]['Selection']>( options: { entity: T, selection: S, params?: object }, context: Context<ED>) => Promise<SelectionResult2<ED[T]['Schema'], S>>;
|
||||
}; */
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export declare function searchPoi(options: {
|
||||
value: string;
|
||||
areaCode?: string;
|
||||
indexFrom?: number;
|
||||
count?: number;
|
||||
typeCode?: string;
|
||||
}): Promise<{
|
||||
id: string;
|
||||
areaId: string;
|
||||
poiName: string;
|
||||
coordinate: [number, number];
|
||||
}[]>;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
export async function searchPoi(options) {
|
||||
const { value, areaCode, indexFrom, count } = options;
|
||||
const form = new FormData();
|
||||
form.set('stName', value);
|
||||
if (areaCode) {
|
||||
form.set('code', areaCode);
|
||||
}
|
||||
if (indexFrom && count) {
|
||||
form.set('page', `${indexFrom / count}`);
|
||||
form.set('size', `${count}`);
|
||||
}
|
||||
const result = await fetch('https://dmfw.mca.gov.cn/9095/stname/listPub', {
|
||||
method: 'post',
|
||||
body: form,
|
||||
});
|
||||
const { records } = await result.json();
|
||||
const pois = await Promise.all(records.map(async (ele) => {
|
||||
let { area, standard_name, gdm, id, province_name, city_name, area_name, place_type, } = ele;
|
||||
// 对返回的area数据进行一些清洗,不规范
|
||||
if (area.length === 9) {
|
||||
if (area.endsWith('999')) {
|
||||
area = area.slice(0, 6);
|
||||
}
|
||||
}
|
||||
if (area === '000000') {
|
||||
// 搜索如长江这样的地理名称时会返回这样的数据,过滤掉
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
id,
|
||||
areaId: area,
|
||||
poiName: standard_name,
|
||||
coordinate: gdm.coordinates[0],
|
||||
detail: `${province_name}${city_name}${area_name}${standard_name}(${place_type})`,
|
||||
};
|
||||
}));
|
||||
return pois.filter((poi) => !!poi);
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { operate, select, fetchRows, count, aggregate } from './crud';
|
||||
import { amap } from './amap';
|
||||
import { getTranslations } from './locales';
|
||||
import { registerPorts, clearPorts, importEntity, exportEntity, getImportationTemplate } from './port';
|
||||
import { searchPoi } from './geo';
|
||||
import { loadRelations } from './relation';
|
||||
import { crossBridge } from './utils';
|
||||
declare const aspectDict: {
|
||||
operate: typeof operate;
|
||||
select: typeof select;
|
||||
count: typeof count;
|
||||
aggregate: typeof aggregate;
|
||||
fetchRows: typeof fetchRows;
|
||||
amap: typeof amap;
|
||||
getTranslations: typeof getTranslations;
|
||||
importEntity: typeof importEntity;
|
||||
exportEntity: typeof exportEntity;
|
||||
getImportationTemplate: typeof getImportationTemplate;
|
||||
searchPoi: typeof searchPoi;
|
||||
loadRelations: typeof loadRelations;
|
||||
crossBridge: typeof crossBridge;
|
||||
};
|
||||
export default aspectDict;
|
||||
export * from './AspectDict';
|
||||
export { registerPorts, clearPorts, };
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { operate, select, fetchRows, count, aggregate } from './crud';
|
||||
import { amap } from './amap';
|
||||
import { getTranslations } from './locales';
|
||||
import { registerPorts, clearPorts, importEntity, exportEntity, getImportationTemplate } from './port';
|
||||
import { searchPoi } from './geo';
|
||||
import { loadRelations } from './relation';
|
||||
import { crossBridge } from './utils';
|
||||
const aspectDict = {
|
||||
operate,
|
||||
select,
|
||||
count,
|
||||
aggregate,
|
||||
fetchRows,
|
||||
amap,
|
||||
getTranslations,
|
||||
importEntity,
|
||||
exportEntity,
|
||||
getImportationTemplate,
|
||||
searchPoi,
|
||||
loadRelations,
|
||||
crossBridge,
|
||||
};
|
||||
export default aspectDict;
|
||||
export * from './AspectDict';
|
||||
export { registerPorts, clearPorts, };
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
export declare function getTranslations(options: {
|
||||
namespace: string | string[];
|
||||
locale: string;
|
||||
}): Promise<{
|
||||
common: {
|
||||
action: {
|
||||
confirm: string;
|
||||
};
|
||||
};
|
||||
}>;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
export async function getTranslations(options) {
|
||||
const { namespace, locale } = options;
|
||||
// 表示entity locale表示zh_CN
|
||||
let translations = {};
|
||||
return {
|
||||
common: {
|
||||
action: {
|
||||
confirm: '确定2',
|
||||
},
|
||||
},
|
||||
};
|
||||
// const getTranslations = (ns: string) => {
|
||||
// const entityName = ns.substring(0, 1).toUpperCase() + ns.substring(1);
|
||||
// const entityName2 = ns.toLowerCase();
|
||||
// try {
|
||||
// const data = require(`${entityName}/locales/${locale}.ts`).default;
|
||||
// assign(translations, {
|
||||
// [entityName2]: data,
|
||||
// });
|
||||
// }
|
||||
// catch (err) {
|
||||
// throw err
|
||||
// }
|
||||
// };
|
||||
// if (namespace instanceof Array) {
|
||||
// namespace.forEach((ns) => {
|
||||
// getTranslations(ns);
|
||||
// })
|
||||
// }
|
||||
// else {
|
||||
// getTranslations(namespace);
|
||||
// }
|
||||
// return translations;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { EntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { Importation, Exportation } from 'oak-domain/lib/types/Port';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
export declare function registerPorts<ED extends EntityDict>(importations: Importation<ED, keyof ED, any>[], exportations: Exportation<ED, keyof ED, any>[]): void;
|
||||
export declare function clearPorts(): void;
|
||||
export declare function importEntity<ED extends EntityDict, Cxt extends AsyncContext<ED>>(params: {
|
||||
entity: string;
|
||||
id: string;
|
||||
file: any;
|
||||
option: string;
|
||||
}, context: Cxt): Promise<ArrayBuffer | void>;
|
||||
export declare function exportEntity<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>>(params: {
|
||||
entity: T;
|
||||
id: string;
|
||||
filter?: ED[T]['Selection']['filter'];
|
||||
properties?: Record<string, any>;
|
||||
}, context: Cxt): Promise<ArrayBuffer>;
|
||||
export declare function getImportationTemplate<ED extends EntityDict, Cxt extends AsyncContext<ED>>(params: {
|
||||
id: string;
|
||||
}, context: Cxt): Promise<ArrayBuffer>;
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { utils, write, readFile } from 'xlsx';
|
||||
const Importations = {};
|
||||
const Exportations = {};
|
||||
export function registerPorts(importations, exportations) {
|
||||
for (const i of importations) {
|
||||
assert(!Importations.hasOwnProperty(i.id), `Importation中的id【${i.id}】重复了`);
|
||||
Object.assign(Importations, {
|
||||
[i.id]: i,
|
||||
});
|
||||
}
|
||||
for (const e of exportations) {
|
||||
assert(!Exportations.hasOwnProperty(e.id), `Exportation中的id【${e.id}】重复了`);
|
||||
Object.assign(Exportations, {
|
||||
[e.id]: e,
|
||||
});
|
||||
}
|
||||
}
|
||||
export function clearPorts() {
|
||||
for (const i in Importations) {
|
||||
delete Importations[i];
|
||||
}
|
||||
for (const e in Exportations) {
|
||||
delete Exportations[e];
|
||||
}
|
||||
}
|
||||
function getImportation(id) {
|
||||
assert(Importations.hasOwnProperty(id), `id为[${id}]的importation不存在`);
|
||||
return Importations[id];
|
||||
}
|
||||
function getExportation(id) {
|
||||
assert(Exportations.hasOwnProperty(id), `id为[${id}]的exportation不存在`);
|
||||
return Exportations[id];
|
||||
}
|
||||
export async function importEntity(params, context) {
|
||||
const entity = params.entity;
|
||||
const file = params.file;
|
||||
const id = params.id;
|
||||
const option = JSON.parse(params.option);
|
||||
const importation = getImportation(id);
|
||||
if (!importation) {
|
||||
throw new Error('尚不支持此数据的导入');
|
||||
}
|
||||
const { fn } = importation;
|
||||
// const arrayBuffer = await file.arrayBuffer();
|
||||
const workbook = readFile(file.filepath, { type: 'buffer' });
|
||||
const { SheetNames, Sheets } = workbook;
|
||||
const errorSheets = [];
|
||||
for (const sheetName of SheetNames) {
|
||||
const sheet = Sheets[sheetName];
|
||||
const dataList = utils.sheet_to_json(sheet);
|
||||
const errorMessageList = await fn(dataList, context, option);
|
||||
if (errorMessageList.length > 0) {
|
||||
errorSheets.push({
|
||||
sheetName,
|
||||
worksheet: utils.json_to_sheet(errorMessageList),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (errorSheets.length > 0) {
|
||||
const errorWorkbook = utils.book_new();
|
||||
for (const sheetData of errorSheets) {
|
||||
utils.book_append_sheet(errorWorkbook, sheetData.worksheet, sheetData.sheetName);
|
||||
}
|
||||
return await write(errorWorkbook, { type: 'buffer' });
|
||||
}
|
||||
// throw new Error('not implement yet');
|
||||
}
|
||||
export async function exportEntity(params, context) {
|
||||
const id = params.id;
|
||||
const filter = params.filter;
|
||||
const properties = params.properties;
|
||||
const exportation = getExportation(id);
|
||||
if (!exportation) {
|
||||
throw new Error('尚不支持此数据的导出');
|
||||
}
|
||||
const { projection, headers, fn, entity, makeHeaders } = exportation;
|
||||
const dataList = await context.select(entity, {
|
||||
filter,
|
||||
data: projection,
|
||||
}, {});
|
||||
const headers2 = makeHeaders ? makeHeaders(dataList) : headers;
|
||||
assert(headers2 && headers2.length > 0, '导出未传入表头');
|
||||
const fittedDatalist = [];
|
||||
for (const data of dataList) {
|
||||
fittedDatalist.push(await fn(data, context, properties));
|
||||
}
|
||||
const exportSheet = utils.json_to_sheet(fittedDatalist, {
|
||||
header: headers2,
|
||||
});
|
||||
const exportBook = utils.book_new();
|
||||
utils.book_append_sheet(exportBook, exportSheet);
|
||||
return await write(exportBook, { type: 'buffer' });
|
||||
// throw new Error('export not implement yet');
|
||||
}
|
||||
export async function getImportationTemplate(params, context) {
|
||||
const id = params.id;
|
||||
const importation = getImportation(id);
|
||||
const { headers } = importation;
|
||||
if (!importation) {
|
||||
throw new Error('未找到对应的模板');
|
||||
}
|
||||
const exportSheet = utils.json_to_sheet([], { header: headers });
|
||||
const widthList = headers.map((ele) => {
|
||||
return {
|
||||
width: ele.length * 2.2,
|
||||
};
|
||||
});
|
||||
exportSheet['!cols'] = widthList;
|
||||
const exportBook = utils.book_new();
|
||||
utils.book_append_sheet(exportBook, exportSheet);
|
||||
return await write(exportBook, { type: 'buffer' });
|
||||
// throw new Error('not implement yet');
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
export declare function loadRelations<ED extends BaseEntityDict & EntityDict, Cxt extends AsyncContext<ED>>(params: {
|
||||
entities: (keyof ED)[];
|
||||
}, context: Cxt): Promise<ED["userRelation"]["OpSchema"][]>;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { OakUnloggedInException, } from 'oak-domain/lib/types';
|
||||
import { omit } from 'oak-domain/lib/utils/lodash';
|
||||
export async function loadRelations(params, context) {
|
||||
const { entities } = params;
|
||||
const userId = context.getCurrentUserId();
|
||||
if (!userId) {
|
||||
throw new OakUnloggedInException();
|
||||
}
|
||||
const userRelations = await context.select('userRelation', {
|
||||
data: {
|
||||
id: 1,
|
||||
userId: 1,
|
||||
relationId: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
relation: {
|
||||
id: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
name: 1,
|
||||
display: 1,
|
||||
actionAuth$relation: {
|
||||
$entity: 'actionAuth',
|
||||
data: {
|
||||
id: 1,
|
||||
paths: 1,
|
||||
destEntity: 1,
|
||||
deActions: 1,
|
||||
},
|
||||
},
|
||||
relationAuth$sourceRelation: {
|
||||
$entity: 'relationAuth',
|
||||
data: {
|
||||
id: 1,
|
||||
sourceRelationId: 1,
|
||||
destRelationId: 1,
|
||||
destRelation: {
|
||||
id: 1,
|
||||
entity: 1,
|
||||
entityId: 1,
|
||||
name: 1,
|
||||
display: 1,
|
||||
},
|
||||
path: 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
filter: {
|
||||
userId,
|
||||
/* entity: {
|
||||
$in: entities as string[],
|
||||
}, */
|
||||
},
|
||||
}, {});
|
||||
const result = userRelations.map((userRelation) => omit(userRelation, 'relation'));
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export declare function crossBridge(params: {
|
||||
url: string;
|
||||
}): Promise<ReadableStream<Uint8Array> | null>;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export async function crossBridge(params) {
|
||||
const { url } = params;
|
||||
const res = await fetch(url);
|
||||
return res.body;
|
||||
}
|
||||
|
|
@ -9,9 +9,13 @@
|
|||
"lib/**/*"
|
||||
],
|
||||
"main": "lib/index",
|
||||
"module": "es/index",
|
||||
"types": "es/index.d.ts",
|
||||
"typings": "es/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "test",
|
||||
"build": "tsc"
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"build-es": "tsc -p tsconfig.es.json"
|
||||
},
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
|
|
@ -22,6 +26,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"assert": "^2.0.0",
|
||||
"ts-node": "~10.9.1",
|
||||
"tslib": "^2.4.0",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
import { judgeRelation } from 'oak-domain/lib/store/relation';
|
||||
import assert from 'assert';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
|
||||
export async function operate<
|
||||
ED extends BaseEntityDict & EntityDict,
|
||||
|
|
|
|||
46
src/geo.ts
46
src/geo.ts
|
|
@ -1,4 +1,4 @@
|
|||
import assert from 'assert';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
|
||||
/**
|
||||
* 根据poiName搜索地理位置
|
||||
|
|
@ -10,14 +10,14 @@ type DmfwPoi = {
|
|||
area: string;
|
||||
standard_name: string;
|
||||
gdm: {
|
||||
coordinates: [[number, number]],
|
||||
},
|
||||
coordinates: [[number, number]];
|
||||
};
|
||||
place_type: string;
|
||||
place_code: string;
|
||||
area_name: string;
|
||||
city_name: string;
|
||||
province_name: string;
|
||||
}
|
||||
};
|
||||
|
||||
export async function searchPoi(options: {
|
||||
value: string;
|
||||
|
|
@ -25,7 +25,14 @@ export async function searchPoi(options: {
|
|||
indexFrom?: number;
|
||||
count?: number;
|
||||
typeCode?: string;
|
||||
}): Promise<{ id: string; areaId: string; poiName: string; coordinate: [number, number] }[]> {
|
||||
}): Promise<
|
||||
{
|
||||
id: string;
|
||||
areaId: string;
|
||||
poiName: string;
|
||||
coordinate: [number, number];
|
||||
}[]
|
||||
> {
|
||||
const { value, areaCode, indexFrom, count } = options;
|
||||
const form = new FormData();
|
||||
form.set('stName', value);
|
||||
|
|
@ -43,12 +50,19 @@ export async function searchPoi(options: {
|
|||
});
|
||||
const { records } = await result.json();
|
||||
const pois = await Promise.all(
|
||||
records.map(
|
||||
async (ele: DmfwPoi) => {
|
||||
let { area, standard_name, gdm, id,
|
||||
province_name, city_name, area_name, place_type } = ele;
|
||||
records.map(async (ele: DmfwPoi) => {
|
||||
let {
|
||||
area,
|
||||
standard_name,
|
||||
gdm,
|
||||
id,
|
||||
province_name,
|
||||
city_name,
|
||||
area_name,
|
||||
place_type,
|
||||
} = ele;
|
||||
// 对返回的area数据进行一些清洗,不规范
|
||||
if(area.length === 9) {
|
||||
if (area.length === 9) {
|
||||
if (area.endsWith('999')) {
|
||||
area = area.slice(0, 6);
|
||||
}
|
||||
|
|
@ -65,10 +79,12 @@ export async function searchPoi(options: {
|
|||
coordinate: gdm.coordinates[0],
|
||||
detail: `${province_name}${city_name}${area_name}${standard_name}(${place_type})`,
|
||||
};
|
||||
}
|
||||
)
|
||||
})
|
||||
);
|
||||
return pois.filter(
|
||||
poi => !!poi
|
||||
) as { id: string; areaId: string; poiName: string; coordinate: [number, number] }[];
|
||||
return pois.filter((poi) => !!poi) as {
|
||||
id: string;
|
||||
areaId: string;
|
||||
poiName: string;
|
||||
coordinate: [number, number];
|
||||
}[];
|
||||
}
|
||||
81
src/port.ts
81
src/port.ts
|
|
@ -1,23 +1,32 @@
|
|||
import assert from 'assert';
|
||||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { EntityDict, SelectOption } from 'oak-domain/lib/types/Entity';
|
||||
import { Importation, Exportation } from 'oak-domain/lib/types/Port';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
import { read, utils, write, readFile } from 'xlsx';
|
||||
import { buffer } from 'stream/consumers';
|
||||
import { Duplex } from 'stream';
|
||||
|
||||
|
||||
const Importations: Record<string, any> = {};
|
||||
const Exportations: Record<string, any> = {};
|
||||
|
||||
export function registerPorts<ED extends EntityDict>(importations: Importation<ED, keyof ED, any>[], exportations: Exportation<ED, keyof ED, any>[]) {
|
||||
export function registerPorts<ED extends EntityDict>(
|
||||
importations: Importation<ED, keyof ED, any>[],
|
||||
exportations: Exportation<ED, keyof ED, any>[]
|
||||
) {
|
||||
for (const i of importations) {
|
||||
assert(!Importations.hasOwnProperty(i.id), `Importation中的id【${i.id}】重复了`);
|
||||
assert(
|
||||
!Importations.hasOwnProperty(i.id),
|
||||
`Importation中的id【${i.id}】重复了`
|
||||
);
|
||||
Object.assign(Importations, {
|
||||
[i.id]: i,
|
||||
});
|
||||
}
|
||||
|
||||
for (const e of exportations) {
|
||||
assert(!Exportations.hasOwnProperty(e.id), `Exportation中的id【${e.id}】重复了`);
|
||||
assert(
|
||||
!Exportations.hasOwnProperty(e.id),
|
||||
`Exportation中的id【${e.id}】重复了`
|
||||
);
|
||||
Object.assign(Exportations, {
|
||||
[e.id]: e,
|
||||
});
|
||||
|
|
@ -46,12 +55,15 @@ function getExportation<ED extends EntityDict, T extends keyof ED>(id: string) {
|
|||
export async function importEntity<
|
||||
ED extends EntityDict,
|
||||
Cxt extends AsyncContext<ED>
|
||||
>(params: {
|
||||
entity: string,
|
||||
id: string,
|
||||
file: any, // 是否链接后台的file类型不一致,暂时无法解决
|
||||
option: string,
|
||||
}, context: Cxt): Promise<ArrayBuffer | void> {
|
||||
>(
|
||||
params: {
|
||||
entity: string;
|
||||
id: string;
|
||||
file: any; // 是否链接后台的file类型不一致,暂时无法解决
|
||||
option: string;
|
||||
},
|
||||
context: Cxt
|
||||
): Promise<ArrayBuffer | void> {
|
||||
const entity = params.entity;
|
||||
const file = params.file;
|
||||
const id = params.id;
|
||||
|
|
@ -68,23 +80,27 @@ export async function importEntity<
|
|||
|
||||
for (const sheetName of SheetNames) {
|
||||
const sheet = Sheets[sheetName];
|
||||
const dataList = utils.sheet_to_json(
|
||||
sheet
|
||||
const dataList = utils.sheet_to_json(sheet);
|
||||
const errorMessageList = await fn(
|
||||
dataList as Record<string, string | number | boolean>[],
|
||||
context,
|
||||
option
|
||||
);
|
||||
const errorMessageList = await fn(dataList as Record<string, string | number | boolean>[], context, option);
|
||||
if (errorMessageList.length > 0) {
|
||||
errorSheets.push(
|
||||
{
|
||||
errorSheets.push({
|
||||
sheetName,
|
||||
worksheet: utils.json_to_sheet(errorMessageList),
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (errorSheets.length > 0) {
|
||||
const errorWorkbook = utils.book_new();
|
||||
for (const sheetData of errorSheets) {
|
||||
utils.book_append_sheet(errorWorkbook, sheetData.worksheet, sheetData.sheetName);
|
||||
utils.book_append_sheet(
|
||||
errorWorkbook,
|
||||
sheetData.worksheet,
|
||||
sheetData.sheetName
|
||||
);
|
||||
}
|
||||
return await write(errorWorkbook, { type: 'buffer' });
|
||||
}
|
||||
|
|
@ -95,12 +111,15 @@ export async function exportEntity<
|
|||
ED extends EntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends AsyncContext<ED>
|
||||
>(params: {
|
||||
>(
|
||||
params: {
|
||||
entity: T;
|
||||
id: string;
|
||||
filter?: ED[T]['Selection']['filter'];
|
||||
properties?: Record<string, any>;
|
||||
}, context: Cxt): Promise<ArrayBuffer> {
|
||||
},
|
||||
context: Cxt
|
||||
): Promise<ArrayBuffer> {
|
||||
const id = params.id;
|
||||
const filter = params.filter;
|
||||
const properties = params.properties;
|
||||
|
|
@ -118,12 +137,16 @@ export async function exportEntity<
|
|||
{}
|
||||
);
|
||||
const headers2 = makeHeaders ? makeHeaders(dataList) : headers;
|
||||
assert(headers2 && headers2.length > 0, '导出未传入表头')
|
||||
const fittedDatalist = []
|
||||
assert(headers2 && headers2.length > 0, '导出未传入表头');
|
||||
const fittedDatalist = [];
|
||||
for (const data of dataList) {
|
||||
fittedDatalist.push(await fn(data as ED[keyof ED]['Schema'], context, properties));
|
||||
fittedDatalist.push(
|
||||
await fn(data as ED[keyof ED]['Schema'], context, properties)
|
||||
);
|
||||
}
|
||||
const exportSheet = utils.json_to_sheet(fittedDatalist, { header: headers2 });
|
||||
const exportSheet = utils.json_to_sheet(fittedDatalist, {
|
||||
header: headers2,
|
||||
});
|
||||
const exportBook = utils.book_new();
|
||||
utils.book_append_sheet(exportBook, exportSheet);
|
||||
return await write(exportBook, { type: 'buffer' });
|
||||
|
|
@ -141,13 +164,11 @@ export async function getImportationTemplate<
|
|||
throw new Error('未找到对应的模板');
|
||||
}
|
||||
const exportSheet = utils.json_to_sheet([], { header: headers });
|
||||
const widthList = headers.map(
|
||||
(ele: string) => {
|
||||
const widthList = headers.map((ele: string) => {
|
||||
return {
|
||||
width: ele.length * 2.2,
|
||||
};
|
||||
}
|
||||
)
|
||||
});
|
||||
exportSheet['!cols'] = widthList;
|
||||
const exportBook = utils.book_new();
|
||||
utils.book_append_sheet(exportBook, exportSheet);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"jsx": "preserve",
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "ESNEXT", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
// "lib": [], /* Specify library files to be included in the compilation. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
"declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
"importHelpers": true,
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "es", /* Redirect output structure to the directory. */
|
||||
"rootDir": "src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
"downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"skipLibCheck": true,
|
||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
/* Module Resolution Options */
|
||||
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
/* Advanced Options */
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"types": [
|
||||
"node",
|
||||
"miniprogram-api-typings"
|
||||
],
|
||||
"include": [ "src/**/*.ts" ],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"**/*.spec.ts",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue