first commit
This commit is contained in:
1
src/core/.pydio
Normal file
1
src/core/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
d7cca889-05d9-4311-b88d-a72968fc4581
|
||||
1
src/core/annotation/.pydio
Normal file
1
src/core/annotation/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
c2c6ec3b-b4b9-42f4-92b0-4e10d1e027a6
|
||||
1
src/core/annotation/JsonToClass/.pydio
Normal file
1
src/core/annotation/JsonToClass/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
cbff3cfc-8ebf-4480-a698-e4a7c6040408
|
||||
103
src/core/annotation/JsonToClass/decorators.ts
Normal file
103
src/core/annotation/JsonToClass/decorators.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { setStore } from './store';
|
||||
import { StoreItemType, StoreItemOptions } from './typing';
|
||||
|
||||
export function serialize(serializer: StoreItemType['serializer'], disallowIgnore = false) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
serializer,
|
||||
disallowIgnoreSerializer: disallowIgnore,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function deserialize(deserializer: StoreItemType['deserializer'], disallowIgnore = false) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
deserializer,
|
||||
disallowIgnoreDeserializer: disallowIgnore,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function beforeDeserialize(beforeDeserializer: StoreItemType['beforeDeserializer'], disallowIgnore = false) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
beforeDeserializer,
|
||||
disallowIgnoreBeforeDeserializer: disallowIgnore,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function afterSerialize(afterSerializer: StoreItemType['afterSerializer'], disallowIgnore = false) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
afterSerializer,
|
||||
disallowIgnoreAfterSerializer: disallowIgnore,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function serializeTarget() {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
serializeTarget: true,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function property(originalKey?: string, targetClass?: StoreItemType['targetClass'], isOptional = false) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
|
||||
// propertyKey 使用装饰器的 属性 名称,例如:id
|
||||
// originalKey json 数据的 key,例如: { i: 1, name: 123 } 中的 i
|
||||
// console.log("property target: ", target);
|
||||
// console.log("property propertyKey: ", propertyKey);
|
||||
// console.log("property originalKey: ", originalKey);
|
||||
|
||||
const config: StoreItemOptions = {
|
||||
originalKey: originalKey || propertyKey,
|
||||
key: propertyKey,
|
||||
};
|
||||
if (targetClass) {
|
||||
config.targetClass = targetClass.prototype.constructor;
|
||||
// console.log("有 targetClass ...");
|
||||
// console.log("config: ",config.targetClass);
|
||||
}
|
||||
if (isOptional) {
|
||||
config.optional = isOptional;
|
||||
}
|
||||
setStore(target, config);
|
||||
};
|
||||
}
|
||||
|
||||
export function typed(targetClass: StoreItemType['targetClass']) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
targetClass,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function optional() {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
optional: true,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function defaultValue(value: any) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
setStore(target, {
|
||||
key: propertyKey,
|
||||
default: value,
|
||||
});
|
||||
};
|
||||
}
|
||||
4
src/core/annotation/JsonToClass/index.ts
Normal file
4
src/core/annotation/JsonToClass/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './to-class';
|
||||
export * from './to-plain';
|
||||
export * from './decorators';
|
||||
export * from './typing';
|
||||
27
src/core/annotation/JsonToClass/store.ts
Normal file
27
src/core/annotation/JsonToClass/store.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// @ts-nocheck
|
||||
import { StoreItemOptions, StoreItemType } from './typing';
|
||||
|
||||
const store = new Map<Function, Map<string, StoreItemType>>();
|
||||
|
||||
export const originalKeyStores = new Map<Function, Map<string, StoreItemOptions[]>>();
|
||||
export const keyStores = new Map<Function, Map<string, StoreItemType>>();
|
||||
|
||||
export const setStore = (target: Function, options: StoreItemOptions) => {
|
||||
const { key, ...rest } = options;
|
||||
// 获取被装饰 属性 所在类的 构造函数,作为存储 Map 的 key
|
||||
const storeKey = target.constructor;
|
||||
// 判断是否已经存储过,如果已经存在 get 获取之前存在的 key 对应的数值,不存在 创建新的 map
|
||||
const targetStore = store.has(storeKey) ? store.get(storeKey) : new Map<string, StoreItemType>();
|
||||
|
||||
// 判断被装饰的 属性(id,name)是否已经存在, 存在 获取 key 对应 的 StoreItemType,不存在为 {}
|
||||
let value = targetStore.has(key) ? targetStore.get(key) : {};
|
||||
value = {
|
||||
...value,
|
||||
...rest,
|
||||
};
|
||||
|
||||
targetStore.set(key, value);
|
||||
store.set(storeKey, targetStore);
|
||||
};
|
||||
|
||||
export default store;
|
||||
79
src/core/annotation/JsonToClass/to-class.ts
Normal file
79
src/core/annotation/JsonToClass/to-class.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import isArray from 'isarray';
|
||||
import { getOriginalKeyStore, isUndefined, isNullOrUndefined } from './utils';
|
||||
import { JosnType, StoreItemOptions, BasicClass, ToClassOptions } from './typing';
|
||||
|
||||
export const arrayItemToClass = <T>(arrayVal: any[], Clazz: BasicClass<T>, options: ToClassOptions): any => {
|
||||
return arrayVal.map((v: any) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
isArray(v) ? arrayItemToClass(v, Clazz, options) : objectToClass(v, Clazz, options),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param jsonObj json 数据
|
||||
* @param Clazz 传入类的 构造函数
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
const objectToClass = <T>(jsonObj: Record<string, any>, Clazz: BasicClass<T>, options: ToClassOptions): T => {
|
||||
// 初始化 传入的类
|
||||
const instance: any = new Clazz();
|
||||
const originalKeyStore = getOriginalKeyStore(Clazz);
|
||||
|
||||
originalKeyStore.forEach((propertiesOptions: StoreItemOptions[], originalKey) => {
|
||||
const originalValue = jsonObj[originalKey];
|
||||
propertiesOptions.forEach((storeItemoptions: StoreItemOptions) => {
|
||||
// console.log("propertiesOptions storeItemoptions: ", storeItemoptions);
|
||||
const { key, beforeDeserializer, deserializer, targetClass, optional } = storeItemoptions;
|
||||
|
||||
const disallowIgnoreDeserializer = storeItemoptions.disallowIgnoreDeserializer || !options.ignoreDeserializer;
|
||||
const disallowIgnoreBeforeDeserializer =
|
||||
storeItemoptions.disallowIgnoreBeforeDeserializer || !options.ignoreBeforeDeserializer;
|
||||
|
||||
const isValueNotExist = options.distinguishNullAndUndefined ? isUndefined : isNullOrUndefined;
|
||||
let value = originalValue;
|
||||
if (isValueNotExist(value)) {
|
||||
if (!isValueNotExist(storeItemoptions.default)) {
|
||||
instance[key] = storeItemoptions.default;
|
||||
return;
|
||||
}
|
||||
if (!optional) {
|
||||
throw new Error(`Can't map '${originalKey}' to ${Clazz.name}.${key}, property '${originalKey}' not found`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
value =
|
||||
beforeDeserializer && disallowIgnoreBeforeDeserializer
|
||||
? beforeDeserializer(value, instance, jsonObj, options)
|
||||
: value;
|
||||
if (value && targetClass) {
|
||||
if (isArray(value)) {
|
||||
value = arrayItemToClass(value, targetClass, options);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
value = toClass(value, targetClass, options);
|
||||
}
|
||||
}
|
||||
instance[key] =
|
||||
deserializer && disallowIgnoreDeserializer ? deserializer(value, instance, jsonObj, options) : value;
|
||||
});
|
||||
});
|
||||
return instance;
|
||||
};
|
||||
|
||||
export const toClasses = <T>(rawJson: JosnType[], Clazz: BasicClass<T>, options: ToClassOptions = {}): T[] => {
|
||||
if (!isArray(rawJson)) {
|
||||
throw new Error(`rawJson ${rawJson} must be an array`);
|
||||
}
|
||||
const { constructor } = Clazz.prototype;
|
||||
return rawJson.map((item: object) => objectToClass<T>(item, constructor, options));
|
||||
};
|
||||
|
||||
export const toClass = <T>(rawJson: JosnType, Clazz: BasicClass<T>, options: ToClassOptions = {}): T => {
|
||||
const { constructor } = Clazz.prototype;
|
||||
return objectToClass<T>(rawJson as object, constructor, options);
|
||||
};
|
||||
|
||||
export const JsontoClass = toClass
|
||||
export const JsontoClasses = toClasses
|
||||
55
src/core/annotation/JsonToClass/to-plain.ts
Normal file
55
src/core/annotation/JsonToClass/to-plain.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
// @ts-nocheck
|
||||
import isArray from 'isarray';
|
||||
import { getKeyStore, isUndefined, isNullOrUndefined } from './utils';
|
||||
import { JosnType, BasicClass, StoreItemType, ToPlainOptions } from './typing';
|
||||
|
||||
export const arrayItemToObject = <T>(arrayVal: any[], Clazz: BasicClass<T>, options: ToPlainOptions): any => {
|
||||
return arrayVal.map((v: any) =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
isArray(v) ? arrayItemToObject(v, Clazz, options) : classToObject(v, Clazz, options),
|
||||
);
|
||||
};
|
||||
|
||||
const classToObject = <T>(instance: JosnType, Clazz: BasicClass<T>, options: ToPlainOptions): JosnType => {
|
||||
const obj: JosnType = {};
|
||||
const keyStore = getKeyStore(Clazz);
|
||||
keyStore.forEach((propertiesOption: StoreItemType, key: keyof JosnType) => {
|
||||
const isValueNotExist = options.distinguishNullAndUndefined ? isUndefined : isNullOrUndefined;
|
||||
const instanceValue = isValueNotExist(instance[key]) ? propertiesOption.default : instance[key];
|
||||
const { originalKey, afterSerializer, serializer, targetClass, optional } = propertiesOption;
|
||||
const disallowIgnoreSerializer = propertiesOption.disallowIgnoreSerializer || !options.ignoreSerializer;
|
||||
const disallowIgnoreAfterSerializer =
|
||||
propertiesOption.disallowIgnoreAfterSerializer || !options.ignoreAfterSerializer;
|
||||
|
||||
if (isValueNotExist(instanceValue)) {
|
||||
if (!optional) {
|
||||
throw new Error(`Property '${Clazz.name}.${key}' not found`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let value =
|
||||
serializer && disallowIgnoreSerializer ? serializer(instanceValue, instance, obj, options) : instanceValue;
|
||||
if (value && targetClass) {
|
||||
if (isArray(value)) {
|
||||
value = arrayItemToObject(value, targetClass, options);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
value = toPlain(value, targetClass, options);
|
||||
}
|
||||
}
|
||||
obj[originalKey] =
|
||||
afterSerializer && disallowIgnoreAfterSerializer ? afterSerializer(value, instance, obj, options) : value;
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
export const toPlains = <T>(instances: (T | JosnType)[], Clazz: BasicClass<T>, options: ToPlainOptions = {}): any[] => {
|
||||
if (!isArray(instances)) {
|
||||
throw new Error(`${Clazz} instances must be an array`);
|
||||
}
|
||||
return instances.map((item: JosnType) => classToObject<T>(item, Clazz, options));
|
||||
};
|
||||
|
||||
export const toPlain = <T>(instance: T | JosnType, Clazz: BasicClass<T>, options: ToPlainOptions = {}): any => {
|
||||
return classToObject<T>(instance, Clazz, options);
|
||||
};
|
||||
38
src/core/annotation/JsonToClass/typing.ts
Normal file
38
src/core/annotation/JsonToClass/typing.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export type StoreItemType = {
|
||||
originalKey?: string;
|
||||
targetClass?: BasicClass;
|
||||
serializer?: (value: any, instance: any, origin: any, options: ToPlainOptions) => any;
|
||||
disallowIgnoreSerializer?: boolean;
|
||||
afterSerializer?: (value: any, instance: any, origin: any, options: ToPlainOptions) => any;
|
||||
disallowIgnoreAfterSerializer?: boolean;
|
||||
deserializer?: (value: any, instance: any, origin: any, options: ToClassOptions) => any;
|
||||
disallowIgnoreDeserializer?: boolean;
|
||||
beforeDeserializer?: (value: any, instance: any, origin: any, options: ToClassOptions) => any;
|
||||
disallowIgnoreBeforeDeserializer?: boolean;
|
||||
default?: any;
|
||||
autoTypeDetection?: boolean;
|
||||
optional?: boolean;
|
||||
serializeTarget?: boolean;
|
||||
};
|
||||
|
||||
export type StoreItemOptions = StoreItemType & {
|
||||
key: string;
|
||||
};
|
||||
|
||||
export type BasicClass<T = any> = {
|
||||
new (...args: any[]): T;
|
||||
};
|
||||
|
||||
export type JosnType = { [key: string]: any };
|
||||
|
||||
export interface ToClassOptions {
|
||||
ignoreDeserializer?: boolean;
|
||||
ignoreBeforeDeserializer?: boolean;
|
||||
distinguishNullAndUndefined?: boolean;
|
||||
}
|
||||
|
||||
export interface ToPlainOptions {
|
||||
ignoreSerializer?: boolean;
|
||||
ignoreAfterSerializer?: boolean;
|
||||
distinguishNullAndUndefined?: boolean;
|
||||
}
|
||||
78
src/core/annotation/JsonToClass/utils.ts
Normal file
78
src/core/annotation/JsonToClass/utils.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
// @ts-nocheck
|
||||
import { StoreItemOptions, StoreItemType, BasicClass } from './typing';
|
||||
import store, { keyStores, originalKeyStores } from './store';
|
||||
|
||||
export const isNull = (val: any) => val === null;
|
||||
|
||||
export const isUndefined = (val: any) => val === undefined;
|
||||
|
||||
export const isNullOrUndefined = (val: any) => isNull(val) || isUndefined(val);
|
||||
|
||||
export const getOriginalKeyStore = <T>(Clazz: BasicClass<T>) => {
|
||||
let curLayer = Clazz;
|
||||
|
||||
const cacheOriginalKeyStore = originalKeyStores.get(curLayer);
|
||||
|
||||
// console.log("cacheOriginalKeyStore: ", cacheOriginalKeyStore);
|
||||
|
||||
if (cacheOriginalKeyStore) {
|
||||
return cacheOriginalKeyStore;
|
||||
}
|
||||
const originalKeyStore = new Map<string, StoreItemOptions[]>();
|
||||
while (curLayer.name && curLayer.prototype) {
|
||||
const { constructor } = curLayer.prototype;
|
||||
const targetStore = store.get(constructor);
|
||||
// console.log("targetStore: ", targetStore);
|
||||
|
||||
if (targetStore) {
|
||||
targetStore.forEach((storeItem, key) => {
|
||||
const item = {
|
||||
key,
|
||||
...storeItem,
|
||||
};
|
||||
|
||||
// console.log("item: ", item);
|
||||
|
||||
if (!originalKeyStore.has(storeItem.originalKey)) {
|
||||
originalKeyStore.set(storeItem.originalKey, [item]);
|
||||
} else {
|
||||
const exists = originalKeyStore.get(storeItem.originalKey);
|
||||
if (!exists.find((exist: StoreItemOptions) => exist.key === key)) {
|
||||
originalKeyStore.set(storeItem.originalKey, [...originalKeyStore.get(storeItem.originalKey), item]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
curLayer = Object.getPrototypeOf(constructor);
|
||||
}
|
||||
originalKeyStores.set(Clazz, originalKeyStore);
|
||||
return originalKeyStore;
|
||||
};
|
||||
|
||||
export const getKeyStore = <T>(Clazz: BasicClass<T>) => {
|
||||
const cacheKeyStore = keyStores.get(Clazz);
|
||||
if (cacheKeyStore) {
|
||||
return cacheKeyStore;
|
||||
}
|
||||
const keyStore = new Map<string, StoreItemType>();
|
||||
const originalKeyStore = getOriginalKeyStore(Clazz);
|
||||
originalKeyStore.forEach(storeItems => {
|
||||
const [firstStoreItem] = storeItems;
|
||||
if (storeItems.length === 1) {
|
||||
keyStore.set(firstStoreItem.key, firstStoreItem);
|
||||
} else {
|
||||
const hasStoreItems = storeItems.filter(storeItem => storeItem.serializeTarget);
|
||||
if (hasStoreItems.length !== 1) {
|
||||
throw new Error(
|
||||
`Only one of keys(${storeItems.map(storeItem => storeItem.key).join(', ')}) in ${
|
||||
Clazz.name
|
||||
} can contain a serializeTarget when use toPlain`,
|
||||
);
|
||||
}
|
||||
const hasStoreItem = hasStoreItems[0];
|
||||
keyStore.set(hasStoreItem.key, hasStoreItem);
|
||||
}
|
||||
});
|
||||
keyStores.set(Clazz, keyStore);
|
||||
return keyStore;
|
||||
};
|
||||
120
src/core/annotation/http.annotation.ts
Normal file
120
src/core/annotation/http.annotation.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2023. bmy
|
||||
* Email:2271608011@qq.com
|
||||
* Github:https://github.com/helpcode
|
||||
*/
|
||||
|
||||
import { ConfigureConfig } from "@config/configure.config";
|
||||
import AxioDao from "@dao/index.dao";
|
||||
import { JsontoClass, JsontoClasses } from "@ann/JsonToClass";
|
||||
|
||||
|
||||
interface ParamsType {
|
||||
url?: string;
|
||||
useHandle?: boolean;
|
||||
header?: { [key: string]: any };
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 接口返回 数据所对应的 类,在类的方法上定义元数据,key为mapper,值为 传入的 type
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
export function Mapper(type: { new(...args: any[]): any }) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
Reflect.defineMetadata('mapper', type, target, propertyKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 请求注解
|
||||
* @param RequestParams
|
||||
* @constructor
|
||||
*/
|
||||
export function GET(RequestParams?: ParamsType) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
CheckParams('get', target, propertyKey, descriptor, <ParamsType>RequestParams)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 请求注解
|
||||
* @param RequestParams
|
||||
* @constructor
|
||||
*/
|
||||
export function POST(RequestParams?: ParamsType) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
CheckParams('post', target, propertyKey, descriptor, <ParamsType>RequestParams)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT 请求注解
|
||||
* @param RequestParams
|
||||
* @constructor
|
||||
*/
|
||||
export function PUT(RequestParams?: ParamsType) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
CheckParams('put', target, propertyKey, descriptor, <ParamsType>RequestParams)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE 请求注解
|
||||
* @param RequestParams
|
||||
* @constructor
|
||||
*/
|
||||
export function DELETE(RequestParams?: ParamsType) {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
|
||||
CheckParams('delete', target, propertyKey, descriptor, <ParamsType>RequestParams)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// GET POST PUT DELETE 四个装饰器最终 都会走这里代码进行发送请求
|
||||
// 所以 在 http.annotation.ts 文件中 引入插件 json-class-interface
|
||||
// 调 json-class-interface 的方法 来配置 生成的 class 存放路径 为 /service/type 文件夹
|
||||
// 请求完成后 先使用 装饰器 的 target.name+_+propertyKey 作为文件名并 在路径下生成空的 .ts 文件
|
||||
// 然后调用 json-class-interface 的 toClass 方法传入propertyKey作为第一层类的名称
|
||||
// 并传入 res 请求到的json数据,得到最终的 类代码,然后让 json-class-interface 将 类代码 写入刚生成的 .ts 文件中
|
||||
|
||||
|
||||
// 唯一需要开发者手动做的事情如下,举例:
|
||||
// User.service.impl.ts 中 的 xxx 方法 GET 装饰器 传入 刚生成文件中的 propertyKey 类名
|
||||
// 这里的代码会自动调用 插件 json-mapper-class 进行 JsontoClasses 或者 JsontoClass 进行序列化
|
||||
|
||||
// 伪代码
|
||||
// configTypePath("service/type")
|
||||
// wirteFileType(`${target.name_propertyKey}.ts`, toClass(propertyKey,res) )
|
||||
|
||||
//
|
||||
function CheckParams(
|
||||
methods: "get" | "post" | "put" | "delete",
|
||||
target: any, propertyKey: string,
|
||||
descriptor: PropertyDescriptor,
|
||||
Params: ParamsType) {
|
||||
|
||||
Params == undefined ? Params = {} : null;
|
||||
Params.url = Params.url || ConfigureConfig.AjaxConfig.ApiList[propertyKey]
|
||||
Params.useHandle = Params.useHandle || false
|
||||
Params.header = Params.header || {}
|
||||
let MapperClass = Reflect.getMetadata('mapper', target, propertyKey);
|
||||
|
||||
if (MapperClass) {
|
||||
let OldMethods = descriptor.value;
|
||||
descriptor.value = async (data: { [key: string]: any }) => {
|
||||
let res = await AxioDao[methods]({
|
||||
url: <string>Params.url, data,
|
||||
headers: Params.header
|
||||
});
|
||||
res = res instanceof Array ? JsontoClasses(res, MapperClass) : JsontoClass(res, MapperClass)
|
||||
if (Params.useHandle) {
|
||||
return await OldMethods.call(target, res)
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
14
src/core/annotation/ioc.annotation.ts
Normal file
14
src/core/annotation/ioc.annotation.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
export function Autowired(params?: any) {
|
||||
return (target: any, propertyKey: string) => {
|
||||
let typeClass = Reflect.getMetadata('design:type', target, propertyKey);
|
||||
Object.defineProperty(target, propertyKey, {
|
||||
value: params ? new typeClass(new params) : new typeClass(),
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
}
|
||||
}
|
||||
53
src/core/annotation/register.annotation.ts
Normal file
53
src/core/annotation/register.annotation.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import Vue from 'vue';
|
||||
import { ConfigureConfig } from "@config/configure.config";
|
||||
import { CreateElement } from 'vue/types/umd';
|
||||
import Es6Promise from 'es6-promise'
|
||||
|
||||
Es6Promise.polyfill()
|
||||
|
||||
export function Start<T extends { new ( ...args: any[] ): { } }>( _ : T ) : T {
|
||||
// @ts-ignore
|
||||
return class extends _ {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
(new Vue({
|
||||
// @ts-ignore
|
||||
router: this.Router, store: this.VueX, render: (h: CreateElement) => h(this.app)
|
||||
}) as Vue).$mount('#app')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function RegServiceAndMethods(constructor: { new(...args: any[]): {}; }) {
|
||||
// newInstance(require.context("../service/impl", false, /\.ts$/))
|
||||
newInstance(require.context("../utils", false, /\.ts$/))
|
||||
}
|
||||
|
||||
function newInstance(context: __WebpackModuleApi.RequireContext) {
|
||||
context.keys().forEach((key: any) => {
|
||||
let m = context(key), className: string = Object.keys(m)[0];
|
||||
new m[className]()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 自动注册Vue插件
|
||||
* @constructor
|
||||
*/
|
||||
export function RegVuePlugs(constructor: { new(...args: any[]): {}; }) {
|
||||
ConfigureConfig.VuePlugs.forEach((v: any) => Vue.use(v))
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动挂载Vue 全局方法
|
||||
* @constructor
|
||||
*/
|
||||
export function GlobalMethod(target: any, propertyKey: string) {
|
||||
Vue.prototype[`$${ propertyKey }`] = target[propertyKey]
|
||||
}
|
||||
1
src/core/config/.pydio
Normal file
1
src/core/config/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
f0ed9e16-3f2b-4d50-9858-120dc2e2ae2c
|
||||
53
src/core/config/configure.config.ts
Normal file
53
src/core/config/configure.config.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
* Email:2271608011@qq.com
|
||||
* Github:https://github.com/helpcode
|
||||
*/
|
||||
|
||||
import VueRouter, { RouterOptions } from 'vue-router';
|
||||
import Vuex from 'vuex';
|
||||
import Antd from 'ant-design-vue';
|
||||
import 'ant-design-vue/dist/antd.css';
|
||||
import { AutoRoutesConfig } from "@config/route.config";
|
||||
import { PluginObject } from "vue";
|
||||
|
||||
export class ConfigureConfig {
|
||||
|
||||
/**
|
||||
* 接口配置: 测试环境基地址,正式环境基地址,具体页面接口
|
||||
*/
|
||||
public static AjaxConfig: {
|
||||
DevUrl: string,
|
||||
ProdUrl: string,
|
||||
ApiList: { [key: string]: string }
|
||||
} = {
|
||||
DevUrl: 'http://127.0.0.1:8080',
|
||||
ProdUrl: 'http://127.0.0.1:9090/api',
|
||||
ApiList: {
|
||||
// start - 注释内的key都将被Node.js监听并diff取出实时编辑后的差异项,然后程序决定是否增删请求中间层xx文件中的xx方法代码【不要删除】
|
||||
UserList: '/UserList',
|
||||
// User_IndexTest: '/test',
|
||||
// Car_carList: '/test',
|
||||
// Car_addCar: '/test',
|
||||
// Index_reg: '/reg',
|
||||
// Order_test: '/test',
|
||||
// end - 注释内的key都将被Node.js监听并diff取出实时编辑后的差异项,然后程序决定是否增删请求中间层xx文件中的xx方法代码【不要删除】
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Vue 插件
|
||||
*/
|
||||
public static VuePlugs: PluginObject<never>[] = [
|
||||
VueRouter, Vuex, Antd
|
||||
];
|
||||
|
||||
/**
|
||||
* 路由配置
|
||||
*/
|
||||
public static RouterConfigUrl: RouterOptions = {
|
||||
mode: 'hash',
|
||||
base: './',
|
||||
routes: AutoRoutesConfig
|
||||
};
|
||||
}
|
||||
18
src/core/config/route.config.ts
Normal file
18
src/core/config/route.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// 根据page目录结构,自动生成的路由配置文件
|
||||
// 参考Nuxt.js 源码,同时自己 + ast 实现 https://zh.nuxtjs.org/guide/routing
|
||||
// @ts-ignore
|
||||
|
||||
export const AutoRoutesConfig = [
|
||||
{
|
||||
name: "About",
|
||||
path: "/About",
|
||||
component: () => import(/* webpackChunkName: 'About' */ '@page/about'),
|
||||
meta: { title: '关于我页面', showNav: true, isLogin: true }
|
||||
},
|
||||
{
|
||||
name: "Home",
|
||||
path: "/Home",
|
||||
component: () => import(/* webpackChunkName: 'Home' */ '@page/home'),
|
||||
meta: { title: '首页', showNav: true, isLogin: true }
|
||||
}
|
||||
];
|
||||
1
src/core/dao/.pydio
Normal file
1
src/core/dao/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
852dea68-05ee-4958-8884-27c503363732
|
||||
98
src/core/dao/index.dao.ts
Normal file
98
src/core/dao/index.dao.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import axios, { AxiosInstance, AxiosError, AxiosRequestConfig } from "axios";
|
||||
import { IndexUtils } from "@utils/index.utils";
|
||||
|
||||
/**
|
||||
* axios的封装
|
||||
*/
|
||||
export class AxioDao {
|
||||
instance: AxiosInstance;
|
||||
|
||||
public constructor() {
|
||||
this.instance = axios.create({
|
||||
baseURL: IndexUtils.CheckAjaxUrl(),
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
this.ResponseInterceptor();
|
||||
this.RequestInterceptor();
|
||||
}
|
||||
|
||||
public async get(params: AxiosRequestConfig): Promise<any> {
|
||||
return await this.instance.get(<string>params.url, {
|
||||
params: params.data,
|
||||
headers: Object.assign({ Authorization: localStorage.getItem("token") }, params.headers)
|
||||
});
|
||||
}
|
||||
|
||||
public async post(params: AxiosRequestConfig): Promise<any> {
|
||||
return await this.instance.post(<string>params.url, params.data, {
|
||||
headers: Object.assign({ Authorization: localStorage.getItem("token") }, params.headers)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Put 请求
|
||||
* 请求参数请参考接口:RequestParams
|
||||
* @param params
|
||||
*/
|
||||
public async put(params: AxiosRequestConfig): Promise<any> {
|
||||
return await this.instance.put(<string>params.url, params.data)
|
||||
}
|
||||
|
||||
/**
|
||||
* delete 请求
|
||||
* 请求参数请参考接口:RequestParams
|
||||
* @param params
|
||||
*/
|
||||
public async delete(params: AxiosRequestConfig): Promise<any> {
|
||||
return await this.instance.delete(<string>params.url, { params: params.data })
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应拦截器
|
||||
* @constructor
|
||||
*/
|
||||
public async ResponseInterceptor(): Promise<any> {
|
||||
this.instance.interceptors.response.use(
|
||||
(response: any) => {
|
||||
return response.data.result;
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log(`
|
||||
❌ 请求错误 ❌
|
||||
1、基地址: ${error.config.baseURL}
|
||||
2、短地址: ${error.config.url}
|
||||
3、请求 方式: ${error.config.method}
|
||||
4、请求 参数: ${JSON.stringify(error.config.params)}
|
||||
5、请求 头 : ${JSON.stringify(error.config.headers)}
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
6、错误信息为: ${error.message}
|
||||
7、错误代码为: ${error.stack}
|
||||
`);
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加请求拦截器
|
||||
* @constructor
|
||||
*/
|
||||
public async RequestInterceptor(): Promise<any> {
|
||||
this.instance.interceptors.request.use((config: any) => {
|
||||
return config
|
||||
}, function (error: AxiosError) {
|
||||
return Promise.reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new AxioDao();
|
||||
1
src/core/run/.pydio
Normal file
1
src/core/run/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
45df40b6-06b8-4b49-9ece-3df4b113d74f
|
||||
51
src/core/run/init.run.ts
Normal file
51
src/core/run/init.run.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import 'reflect-metadata';
|
||||
import 'babel-polyfill'
|
||||
// import '@types/RouterHooks';
|
||||
import Vue, { VueConstructor, Component } from 'vue';
|
||||
import App from '@application/app'
|
||||
import { ConfigureConfig } from "@config/configure.config";
|
||||
import NavigationGuards from "@utils/navigation-guards.utils";
|
||||
import VueRouter, { RawLocation, Route } from 'vue-router';
|
||||
import Vuex, { Store } from 'vuex'
|
||||
import StoreModeule from '@store/index'
|
||||
import { RegServiceAndMethods, RegVuePlugs, Start } from "@ann/register.annotation";
|
||||
import { Autowired } from "@ann/ioc.annotation";
|
||||
|
||||
@Start
|
||||
@RegVuePlugs
|
||||
@RegServiceAndMethods
|
||||
export class InitRun {
|
||||
|
||||
@Autowired()
|
||||
protected NavigationGuards!: NavigationGuards;
|
||||
|
||||
protected Router!: VueRouter;
|
||||
protected VueX!: Store<typeof StoreModeule>;
|
||||
protected app: Component = App;
|
||||
|
||||
constructor() {
|
||||
Vue.config.productionTip = false;
|
||||
this.VueRouterAndVuex()
|
||||
}
|
||||
|
||||
private VueRouterAndVuex(): void {
|
||||
this.Router = new VueRouter(ConfigureConfig.RouterConfigUrl);
|
||||
// this.NavigationGuards.beforeEach(this.Router)
|
||||
// this.NavigationGuards.afterEach(this.Router)
|
||||
|
||||
// 重写路由Push
|
||||
const routerPush: (location: RawLocation) => Promise<Route> = VueRouter.prototype.push;
|
||||
VueRouter.prototype.push = function push(location: RawLocation): Promise<Route> {
|
||||
// @ts-ignore
|
||||
return routerPush.call(this, location).catch((error: Error) => error)
|
||||
};
|
||||
|
||||
this.VueX = new Vuex.Store(StoreModeule)
|
||||
}
|
||||
}
|
||||
|
||||
new InitRun();
|
||||
1
src/core/service/.pydio
Normal file
1
src/core/service/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
b6c30b87-ba50-4860-a92d-3dfe07d0ff5c
|
||||
46
src/core/service/user.service.ts
Normal file
46
src/core/service/user.service.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2023. bmy
|
||||
*/
|
||||
import { GET, Mapper } from "@ann/http.annotation";
|
||||
import { property, defaultValue, deserialize } from "@ann/JsonToClass";
|
||||
|
||||
// ajax接口数据返回 为 ResponseType[]
|
||||
// 这里定义类,将 接口返回的数据 映射到 类中存储
|
||||
export class ResponseType {
|
||||
// 接口返回数据的字段 为 id,这里映射改为 user_id,代码里面用 user_id
|
||||
@property("id")
|
||||
@defaultValue(0)
|
||||
user_id!: number;
|
||||
|
||||
@property("name")
|
||||
@defaultValue("如果接口字段无数值,那这个参数就是默认值")
|
||||
user_name!: string
|
||||
}
|
||||
|
||||
export class UserService {
|
||||
/**
|
||||
* 1 提供 四个【请求装饰器】:@GET @POST @PUT @DELETE
|
||||
* 参数说明:
|
||||
* url 可选:接口请求短地址,如果不填默认使用 configure.config.ts 中和方法名IndexTest同名的对象key中地址
|
||||
* 如果传,使用你传的地址
|
||||
*
|
||||
* useHandle 可选:是否需要对网络请求的结果进行修改后再返回给页面,如果需要传 true,则请求方法的入参 params 会变为ajax请求
|
||||
* 得到的接口数据,处理完数据后,请 return 结果。否则 IndexTest 代码内部留空,节省大量 冗余代码!!
|
||||
*
|
||||
* header 可选:自定义请求头,例如文件上传等 可以在这自定义
|
||||
*
|
||||
* 2 @Mapper() 装饰器
|
||||
* 参数说明:
|
||||
* 请求方法的返回类型(必须用类来描述JSON数据类型),会被 Reflect.defineMetadata 注入 元数据,在 上一步
|
||||
* 【请求装饰器】结束请求后,会从 Reflect.getMetadata 取出 元数据,然后 被 JsonToClass 使用到。
|
||||
* JsonToClass 会将json数据映射到 @Mapper() 装饰器的 参数中,也就是 json数据自动存储到类属性中
|
||||
*/
|
||||
@GET()
|
||||
@Mapper(ResponseType)
|
||||
// @ts-ignore
|
||||
public async UserList (params: object | ResponseType[]): Promise<ResponseType[]> {
|
||||
// 留空,不要写请求代码 即可发送请求,除非 useHandle: true,这时 方法入参 params 为 ajax 接口数据,直接处理 params
|
||||
// 即可,也不需要写请求代码!!
|
||||
}
|
||||
|
||||
}
|
||||
1
src/core/store/.pydio
Normal file
1
src/core/store/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
6dd651dd-0493-4995-a44b-c15ccfdf75a4
|
||||
10
src/core/store/getters.ts
Normal file
10
src/core/store/getters.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
export default {
|
||||
GettersTabsContentArr: (state: any) => state.PublicConfig.TabsContentArr,
|
||||
GettersTabsActive: (state: any) => state.PublicConfig.TabsActive,
|
||||
GettersAsideMenu: (state: any) => state.PublicConfig.AsideMenu,
|
||||
GettersIsLogin: (state: any) => state.PublicConfig.isLogin,
|
||||
}
|
||||
12
src/core/store/index.ts
Normal file
12
src/core/store/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import index from './modules'
|
||||
import getters from './getters'
|
||||
|
||||
// 统一导出各模块
|
||||
export default {
|
||||
modules: { ...index },
|
||||
getters
|
||||
}
|
||||
1
src/core/store/modules/.pydio
Normal file
1
src/core/store/modules/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
d3359e2f-bc25-4e14-b202-20080d06b04a
|
||||
9
src/core/store/modules/index.ts
Normal file
9
src/core/store/modules/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import PublicConfig from './publicConfig'
|
||||
|
||||
export default {
|
||||
PublicConfig
|
||||
}
|
||||
117
src/core/store/modules/publicConfig.ts
Normal file
117
src/core/store/modules/publicConfig.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
interface state {
|
||||
TabsContentArr: Array<{
|
||||
title: string,
|
||||
url: string,
|
||||
closable: boolean,
|
||||
icon: string
|
||||
}>,
|
||||
TabsActive: string,
|
||||
isLogin: boolean,
|
||||
AsideMenu: Array<{
|
||||
web_href: string,
|
||||
web_title: string,
|
||||
icon: string,
|
||||
children: Array<{
|
||||
web_href: string,
|
||||
web_title: string,
|
||||
icon: string,
|
||||
}>
|
||||
}>
|
||||
}
|
||||
|
||||
export default {
|
||||
state: {
|
||||
isLogin: false,
|
||||
TabsContentArr: [
|
||||
{ title: '系统首页', url: '/', closable: false, icon: 'el-icon-house' },
|
||||
],
|
||||
TabsActive: '/',
|
||||
AsideMenu: [
|
||||
{
|
||||
web_href: '/', web_title: '系统首页', icon: 'el-icon-house',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
web_href: '/System', web_title: '系统设置', icon: 'el-icon-setting',
|
||||
children: [
|
||||
{ web_href: '/System/MenuConfig', web_title: '菜单配置', icon: 'el-icon-tickets' },
|
||||
{ web_href: '/System/wardenList', web_title: '管理员列表', icon: 'el-icon-user' },
|
||||
]
|
||||
},
|
||||
{
|
||||
web_href: '/Jurisdiction', web_title: '权限管理', icon: 'el-icon-lock',
|
||||
children: [
|
||||
{ web_href: '/Jurisdiction/RolePermissions', web_title: '角色权限', icon: 'el-icon-key' },
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
mutations: {
|
||||
// 保存顶部菜单
|
||||
SET_TABCONTENT: (state: state, activeMenu: string) => {
|
||||
// 检查是否已经添加过了
|
||||
let s = state.TabsContentArr.filter(function (val: any, index: number) {
|
||||
return activeMenu == val.url
|
||||
});
|
||||
// 如果没有添加过
|
||||
if (s.length == 0) {
|
||||
state.AsideMenu.forEach((v, i) => {
|
||||
// 如果等于,表示一级菜单
|
||||
if (activeMenu == v.web_href) {
|
||||
state.TabsContentArr.push({
|
||||
title: v.web_title,
|
||||
url: v.web_href,
|
||||
icon: v.icon,
|
||||
closable: true
|
||||
})
|
||||
} else {
|
||||
v.children.forEach((va, ix) => {
|
||||
if (activeMenu == va.web_href) {
|
||||
state.TabsContentArr.push({
|
||||
title: va.web_title,
|
||||
url: va.web_href,
|
||||
icon: va.icon,
|
||||
closable: true
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
},
|
||||
// 切换激活
|
||||
SET_TABACTIVE: (state: state, active: string) => {
|
||||
state.TabsActive = active
|
||||
},
|
||||
// 移除激活
|
||||
SET_REMOVETABS: (state: state, targetName: string) => {
|
||||
let tabs = state.TabsContentArr;
|
||||
let activeName = state.TabsActive;
|
||||
// 如果删除的是当前激活菜单
|
||||
if (activeName === targetName) {
|
||||
tabs.forEach((tab: { [key: string]: any }, index: number) => {
|
||||
if (tab.url === targetName) {
|
||||
let nextTab: { [key: string]: any } = tabs[index + 1] || tabs[index - 1];
|
||||
if (nextTab) {
|
||||
activeName = nextTab.url;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
state.TabsActive = activeName;
|
||||
state.TabsContentArr = tabs.filter((tab: { [key: string]: any }) => {
|
||||
return tab.url !== targetName
|
||||
});
|
||||
},
|
||||
// 修改状态
|
||||
SET_LOGINSTATUS: (state: state, status: boolean) => {
|
||||
state.isLogin = status
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
1
src/core/types/.pydio
Normal file
1
src/core/types/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
e5b979e5-1ac3-429c-bf03-7d570eba9033
|
||||
11
src/core/types/RouterHooks.ts
Normal file
11
src/core/types/RouterHooks.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import Component from 'vue-class-component'
|
||||
|
||||
Component.registerHooks([
|
||||
'beforeRouteEnter',
|
||||
'beforeRouteLeave',
|
||||
'beforeRouteUpdate'
|
||||
])
|
||||
359
src/core/types/process.d.ts
vendored
Normal file
359
src/core/types/process.d.ts
vendored
Normal file
@@ -0,0 +1,359 @@
|
||||
// Type definitions for webpack (module API) 1.15
|
||||
// Project: https://github.com/webpack/webpack
|
||||
// Definitions by: use-strict <https://github.com/use-strict>
|
||||
// rhonsby <https://github.com/rhonsby>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.1
|
||||
|
||||
/**
|
||||
* Webpack module API - variables and global functions available inside modules
|
||||
*/
|
||||
|
||||
declare namespace __WebpackModuleApi {
|
||||
interface RequireResolve {
|
||||
(id: string): string | number;
|
||||
}
|
||||
|
||||
interface RequireContext {
|
||||
keys(): string[];
|
||||
(id: string): any;
|
||||
<T>(id: string): T;
|
||||
resolve(id: string): string;
|
||||
/** The module id of the context module. This may be useful for module.hot.accept. */
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface RequireFunction {
|
||||
/**
|
||||
* Returns the exports from a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
|
||||
*/
|
||||
(path: string): any;
|
||||
<T>(path: string): T;
|
||||
/**
|
||||
* Behaves similar to require.ensure, but the callback is called with the exports of each dependency in the paths array. There is no option to provide a chunk name.
|
||||
*/
|
||||
(paths: string[], callback: (...modules: any[]) => void): void;
|
||||
/**
|
||||
* Download additional dependencies on demand. The paths array lists modules that should be available. When they are, callback is called. If the callback is a function expression, dependencies in that source part are extracted and also loaded on demand. A single request is fired to the server, except if all modules are already available.
|
||||
*
|
||||
* This creates a chunk. The chunk can be named. If a chunk with this name already exists, the dependencies are merged into that chunk and that chunk is used.
|
||||
*/
|
||||
ensure(paths: string[], callback: (require: NodeRequire) => void, chunkName?: string): void;
|
||||
ensure(paths: string[], callback: (require: NodeRequire) => void, errorCallback?: (error: any) => void, chunkName?: string): void;
|
||||
context(path: string, deep?: boolean, filter?: RegExp, mode?: "sync" | "eager" | "weak" | "lazy" | "lazy-once"): RequireContext;
|
||||
/**
|
||||
* Returns the module id of a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
|
||||
*
|
||||
* The module id is a number in webpack (in contrast to node.js where it is a string, the filename).
|
||||
*/
|
||||
resolve: NodeJS.RequireResolve;
|
||||
/**
|
||||
* Like require.resolve, but doesn’t include the module into the bundle. It’s a weak dependency.
|
||||
*/
|
||||
resolveWeak(path: string): number | string;
|
||||
/**
|
||||
* Ensures that the dependency is available, but don’t execute it. This can be use for optimizing the position of a module in the chunks.
|
||||
*/
|
||||
include(path: string): void;
|
||||
/**
|
||||
* Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. This is only needed in rare cases (for compatibility!).
|
||||
*/
|
||||
cache: {
|
||||
[id: string]: NodeModule | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
interface Module {
|
||||
exports: any;
|
||||
id: string;
|
||||
filename: string;
|
||||
loaded: boolean;
|
||||
parent: NodeModule | null | undefined;
|
||||
children: NodeModule[];
|
||||
hot?: Hot;
|
||||
}
|
||||
// @ts-ignore
|
||||
type ModuleId = string|number;
|
||||
|
||||
interface HotNotifierInfo {
|
||||
type:
|
||||
| 'self-declined'
|
||||
| 'declined'
|
||||
| 'unaccepted'
|
||||
| 'accepted'
|
||||
| 'disposed'
|
||||
| 'accept-errored'
|
||||
| 'self-accept-errored'
|
||||
| 'self-accept-error-handler-errored';
|
||||
/**
|
||||
* The module in question.
|
||||
*/
|
||||
moduleId: number;
|
||||
/**
|
||||
* For errors: the module id owning the accept handler.
|
||||
*/
|
||||
dependencyId?: number;
|
||||
/**
|
||||
* For declined/accepted/unaccepted: the chain from where the update was propagated.
|
||||
*/
|
||||
chain?: number[];
|
||||
/**
|
||||
* For declined: the module id of the declining parent
|
||||
*/
|
||||
parentId?: number;
|
||||
/**
|
||||
* For accepted: the modules that are outdated and will be disposed
|
||||
*/
|
||||
outdatedModules?: number[];
|
||||
/**
|
||||
* For accepted: The location of accept handlers that will handle the update
|
||||
*/
|
||||
outdatedDependencies?: {
|
||||
[dependencyId: number]: number[];
|
||||
};
|
||||
/**
|
||||
* For errors: the thrown error
|
||||
*/
|
||||
error?: Error;
|
||||
/**
|
||||
* For self-accept-error-handler-errored: the error thrown by the module
|
||||
* before the error handler tried to handle it.
|
||||
*/
|
||||
originalError?: Error;
|
||||
}
|
||||
|
||||
interface Hot {
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependencies
|
||||
* @param callback
|
||||
*/
|
||||
accept(dependencies: string[], callback?: (updatedDependencies: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
|
||||
* @param dependency
|
||||
* @param callback
|
||||
*/
|
||||
accept(dependency: string, callback?: () => void): void;
|
||||
/**
|
||||
* Accept code updates for this module without notification of parents.
|
||||
* This should only be used if the module doesn’t export anything.
|
||||
* The errHandler can be used to handle errors that occur while loading the updated module.
|
||||
* @param errHandler
|
||||
*/
|
||||
accept(errHandler?: (err: Error) => void): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependencies: string[]): void;
|
||||
/**
|
||||
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
|
||||
*/
|
||||
decline(dependency: string): void;
|
||||
/**
|
||||
* Flag the current module as not update-able. If updated the update code would fail with code "decline".
|
||||
*/
|
||||
decline(): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
dispose(callback: (data: any) => void): void;
|
||||
dispose(callback: <T>(data: T) => void): void;
|
||||
/**
|
||||
* Add a one time handler, which is executed when the current module code is replaced.
|
||||
* Here you should destroy/remove any persistent resource you have claimed/created.
|
||||
* If you want to transfer state to the new module, add it to data object.
|
||||
* The data will be available at module.hot.data on the new module.
|
||||
* @param callback
|
||||
*/
|
||||
addDisposeHandler(callback: (data: any) => void): void;
|
||||
addDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Remove a handler.
|
||||
* This can useful to add a temporary dispose handler. You could i. e. replace code while in the middle of a multi-step async function.
|
||||
* @param callback
|
||||
*/
|
||||
removeDisposeHandler(callback: (data: any) => void): void;
|
||||
removeDisposeHandler<T>(callback: (data: T) => void): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* If autoApply is truthy the callback will be called with all modules that were disposed.
|
||||
* apply() is automatically called with autoApply as options parameter.
|
||||
* If autoApply is not set the callback will be called with all modules that will be disposed on apply().
|
||||
* @param autoApply
|
||||
* @param callback
|
||||
*/
|
||||
check(autoApply: boolean, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Throws an exceptions if status() is not idle.
|
||||
* Check all currently loaded modules for updates and apply updates if found.
|
||||
* If no update was found, the callback is called with null.
|
||||
* The callback will be called with all modules that will be disposed on apply().
|
||||
* @param callback
|
||||
*/
|
||||
check(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param options
|
||||
* @param callback
|
||||
*/
|
||||
apply(options: AcceptOptions, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* If status() != "ready" it throws an error.
|
||||
* Continue the update process.
|
||||
* @param callback
|
||||
*/
|
||||
apply(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
|
||||
/**
|
||||
* Return one of idle, check, watch, watch-delay, prepare, ready, dispose, apply, abort or fail.
|
||||
*/
|
||||
status(): string;
|
||||
/** Register a callback on status change. */
|
||||
status(callback: (status: string) => void): void;
|
||||
/** Register a callback on status change. */
|
||||
addStatusHandler(callback: (status: string) => void): void;
|
||||
/**
|
||||
* Remove a registered status change handler.
|
||||
* @param callback
|
||||
*/
|
||||
removeStatusHandler(callback: (status: string) => void): void;
|
||||
|
||||
active: boolean;
|
||||
data: any;
|
||||
}
|
||||
|
||||
interface AcceptOptions {
|
||||
/**
|
||||
* If true the update process continues even if some modules are not accepted (and would bubble to the entry point).
|
||||
*/
|
||||
ignoreUnaccepted?: boolean;
|
||||
/**
|
||||
* Ignore changes made to declined modules.
|
||||
*/
|
||||
ignoreDeclined?: boolean;
|
||||
/**
|
||||
* Ignore errors throw in accept handlers, error handlers and while reevaluating module.
|
||||
*/
|
||||
ignoreErrored?: boolean;
|
||||
/**
|
||||
* Notifier for declined modules.
|
||||
*/
|
||||
onDeclined?: (info: HotNotifierInfo) => void;
|
||||
/**
|
||||
* Notifier for unaccepted modules.
|
||||
*/
|
||||
onUnaccepted?: (info: HotNotifierInfo) => void;
|
||||
/**
|
||||
* Notifier for accepted modules.
|
||||
*/
|
||||
onAccepted?: (info: HotNotifierInfo) => void;
|
||||
/**
|
||||
* Notifier for disposed modules.
|
||||
*/
|
||||
onDisposed?: (info: HotNotifierInfo) => void;
|
||||
/**
|
||||
* Notifier for errors.
|
||||
*/
|
||||
onErrored?: (info: HotNotifierInfo) => void;
|
||||
/**
|
||||
* Indicates that apply() is automatically called by check function
|
||||
*/
|
||||
autoApply?: boolean;
|
||||
}
|
||||
/**
|
||||
* Inside env you can pass any variable
|
||||
*/
|
||||
interface NodeProcess {
|
||||
// @ts-ignore
|
||||
env: {
|
||||
NODE_ENV: string
|
||||
};
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
type __Require1 = (id: string) => any;
|
||||
// @ts-ignore
|
||||
type __Require2 = <T>(id: string) => T;
|
||||
// @ts-ignore
|
||||
type RequireLambda = __Require1 & __Require2;
|
||||
}
|
||||
|
||||
interface NodeRequire extends NodeJS.Require {}
|
||||
|
||||
declare var require: NodeRequire;
|
||||
|
||||
/**
|
||||
* The resource query of the current module.
|
||||
*
|
||||
* e.g. __resourceQuery === "?test" // Inside "file.js?test"
|
||||
*/
|
||||
declare var __resourceQuery: string;
|
||||
|
||||
/**
|
||||
* Equals the config options output.publicPath.
|
||||
*/
|
||||
declare var __webpack_public_path__: string;
|
||||
|
||||
/**
|
||||
* The raw require function. This expression isn’t parsed by the Parser for dependencies.
|
||||
*/
|
||||
declare var __webpack_require__: any;
|
||||
|
||||
/**
|
||||
* The internal chunk loading function
|
||||
*
|
||||
* @param chunkId The id for the chunk to load.
|
||||
* @param callback A callback function called once the chunk is loaded.
|
||||
*/
|
||||
declare var __webpack_chunk_load__: (chunkId: any, callback: (require: __WebpackModuleApi.RequireLambda) => void) => void;
|
||||
|
||||
/**
|
||||
* Access to the internal object of all modules.
|
||||
*/
|
||||
declare var __webpack_modules__: any[];
|
||||
|
||||
/**
|
||||
* Access to the hash of the compilation.
|
||||
*
|
||||
* Only available with the HotModuleReplacementPlugin or the ExtendedAPIPlugin
|
||||
*/
|
||||
declare var __webpack_hash__: any;
|
||||
|
||||
/**
|
||||
* Generates a require function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available.
|
||||
*/
|
||||
declare var __non_webpack_require__: any;
|
||||
|
||||
/**
|
||||
* Adds nonce to all scripts that webpack loads.
|
||||
*
|
||||
* To activate the feature a __webpack_nonce__ variable needs to be set in your entry script.
|
||||
*/
|
||||
declare var __webpack_nonce__: string;
|
||||
|
||||
/**
|
||||
* Equals the config option debug
|
||||
*/
|
||||
declare var DEBUG: boolean;
|
||||
|
||||
interface NodeModule extends NodeJS.Module {}
|
||||
|
||||
declare var module: NodeModule;
|
||||
|
||||
/**
|
||||
* Declare process variable
|
||||
*/
|
||||
declare namespace NodeJS {
|
||||
interface Process extends __WebpackModuleApi.NodeProcess {}
|
||||
interface RequireResolve extends __WebpackModuleApi.RequireResolve {}
|
||||
interface Module extends __WebpackModuleApi.Module {}
|
||||
interface Require extends __WebpackModuleApi.RequireFunction {}
|
||||
}
|
||||
declare var process: NodeJS.Process;
|
||||
48
src/core/types/shims-tsx.d.ts
vendored
Normal file
48
src/core/types/shims-tsx.d.ts
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
import Vue, { VNode } from 'vue'
|
||||
|
||||
declare global {
|
||||
namespace Vue {
|
||||
any
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface ElementAttributesProperty {
|
||||
$props: any // 设置类组件的props类型检查属性
|
||||
}
|
||||
|
||||
// tslint:disable no-empty-interface
|
||||
interface Element extends VNode {
|
||||
}
|
||||
|
||||
// tslint:disable no-empty-interface
|
||||
interface ElementClass extends Vue {
|
||||
}
|
||||
|
||||
interface IntrinsicAttributes {
|
||||
// 给组件元素增加属性
|
||||
on?: any
|
||||
vModel?: any
|
||||
vShow?: boolean
|
||||
value?: any
|
||||
oninput?: Function
|
||||
nativeOnClick?: (event: MouseEvent) => void
|
||||
oncontextmenu?: (event: MouseEvent) => void
|
||||
onmouseup?: (event: MouseEvent) => void
|
||||
onclick?: (event: MouseEvent) => void
|
||||
onclick_prevent?: (event: MouseEvent) => void
|
||||
ref?: string
|
||||
key?: string | number
|
||||
class?: string | string[]
|
||||
slot?: string
|
||||
style?: Partial<CSSStyleDeclaration> | string | object | object[]
|
||||
}
|
||||
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/core/types/shims-vue.d.ts
vendored
Normal file
8
src/core/types/shims-vue.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
1
src/core/utils/.pydio
Normal file
1
src/core/utils/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
23f23313-fd2c-4dfc-aeaa-6758f2f76ec2
|
||||
60
src/core/utils/index.utils.ts
Normal file
60
src/core/utils/index.utils.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2020. bmy
|
||||
*/
|
||||
|
||||
import { ConfigureConfig } from "@config/configure.config";
|
||||
import { GlobalMethod } from "@ann/register.annotation";
|
||||
|
||||
export class IndexUtils {
|
||||
|
||||
/**
|
||||
* 动态返回接口基地址
|
||||
* @constructor
|
||||
*/
|
||||
public static CheckAjaxUrl(): string {
|
||||
if(process.env.NODE_ENV === 'production') {
|
||||
return ConfigureConfig.AjaxConfig.ProdUrl;
|
||||
} else {
|
||||
return ConfigureConfig.AjaxConfig.DevUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法上打上 @GlobalMethod() 注解,这个方法会自动成为vue的全局方法
|
||||
* 组件中直接:this.$setToken() 即可
|
||||
*/
|
||||
@GlobalMethod
|
||||
public setToken(args: string): void {
|
||||
localStorage.setItem("token", args)
|
||||
}
|
||||
|
||||
@GlobalMethod
|
||||
public setStorage<T extends [] | {} | string>(key: string, data: T): void {
|
||||
if (data.constructor == Array || data.constructor == Object) {
|
||||
localStorage.setItem(`moehu_${key}`, JSON.stringify(data));
|
||||
} else {
|
||||
// @ts-ignore
|
||||
localStorage.setItem(`moehu_${key}`, data.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@GlobalMethod
|
||||
public getStorage(key: String): typeof JSON | boolean | string{
|
||||
let Storage: string | null = localStorage.getItem(`moehu_${key}`);
|
||||
if (Storage == null) {
|
||||
return false
|
||||
} else {
|
||||
try {
|
||||
return JSON.parse(Storage);
|
||||
} catch (e) {
|
||||
return Storage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GlobalMethod
|
||||
public isPhone(phone: string): boolean {
|
||||
return /^1[3-9]\d{9}$/.test(phone)
|
||||
}
|
||||
}
|
||||
37
src/core/utils/navigation-guards.utils.ts
Normal file
37
src/core/utils/navigation-guards.utils.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2023. bmy
|
||||
* Email:2271608011@qq.com
|
||||
* Github:https://github.com/helpcode
|
||||
*/
|
||||
import VueRouter from 'vue-router';
|
||||
|
||||
export default class NavigationGuardsUtils {
|
||||
|
||||
public beforeEach(Router: VueRouter) : void {
|
||||
Router.beforeEach((to, from, next) => {
|
||||
document.title = to.meta && to.meta.title;
|
||||
if (to.meta && to.meta.isLogin) {
|
||||
if (localStorage.getItem("moehu_token") != null) {
|
||||
next()
|
||||
} else {
|
||||
next({
|
||||
path: '/login'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (localStorage.getItem("moehu_token") != null
|
||||
&& to.path == "/login") {
|
||||
Router.back();
|
||||
}
|
||||
next()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public afterEach(Router: VueRouter) : void {
|
||||
Router.afterEach((to, from) => {
|
||||
console.log("Router.afterEach")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user