@truenewx/tnxcore
Version:
互联网技术解决方案:Web核心扩展支持
186 lines (169 loc) • 5.37 kB
JavaScript
/**
* 枚举类型<br/>
* 注意1:子类声明后务必确保init()被调用一次,方可正常使用
* 注意2:由于枚举常量作为对象可能被代理,所以枚举常量的比较不要使用===操作符,而应该用equals()方法
*/
const DEFAULT_KEYS = ['ordinal', 'name', 'caption', 'scenes'];
export default class Enum {
ordinal = 0;
name = '';
caption = '';
scenes = {}; // {sceneName: sceneCaption}
/**
* @param caption 显示名称
* @param {Object|Array=} [scenes] 场景集
*/
constructor(caption, scenes) {
this.caption = caption;
if (scenes) {
if (Array.isArray(scenes)) {
for (let scene of scenes) {
this.scenes[scene] = this.caption;
}
} else if (typeof scenes === 'object') {
Object.assign(this.scenes, scenes);
}
}
}
/**
* @param {?Object} [tnx] tnx
*/
static init(tnx) {
let sceneNameSet = new Set();
this.forEach((constant, ordinal, name) => {
constant.ordinal = ordinal;
constant.name = name;
Object.keys(constant.scenes).forEach(sceneName => sceneNameSet.add(sceneName));
});
if (tnx && tnx.app && tnx.app.rpc && typeof tnx.app.rpc.addEnumType === 'function') {
tnx.app.rpc.addEnumType({
name: this.name,
items: this.getItems(),
});
// 加入场景子类型
for (let sceneName of sceneNameSet) {
tnx.app.rpc.addEnumType({
name: this.name,
subname: sceneName,
items: this.getItems(sceneName),
});
}
}
}
static forEach(consumer) {
let names = Object.keys(this);
let ordinal = 0;
for (let name of names) {
const constant = this[name];
if (constant.constructor === this) {
consumer(constant, ordinal++, name);
}
}
}
/**
* @param {?String} [sceneName] 场景名称
*/
static values(sceneName) {
let values = [];
this.forEach(constant => {
if (!sceneName || constant.scenes[sceneName]) {
values.push(constant);
}
});
return values;
}
static valueOf(name) {
let result = undefined;
this.forEach(constant => {
if (constant.name === name) {
result = constant;
}
});
return result;
}
/**
* 校验指定常量合法性
* @param {String|Enum} constant 常量或常量名
* @param {?String} [sceneName] 场景名称
* @return {Enum} 常量
*/
static validate(constant, sceneName) {
let result = undefined;
if (constant) {
if (typeof constant === 'string') {
result = this.valueOf(constant);
} else if (constant.constructor === this) {
result = constant;
}
if (result && sceneName) {
if (!result.scenes[sceneName]) {
result = undefined;
}
}
}
if (!result) {
let message = `无效的 ${this.name} 常量: ${constant}`;
if (sceneName) {
message += `,于场景 ${sceneName} 中`;
}
throw new Error(message);
}
return result;
}
static caption(name) {
let constant = this.values(name);
return constant ? constant.caption : undefined;
}
/**
* @param {?String} [sceneName] 场景名称
*/
static getItems(sceneName) {
let items = [];
this.forEach(constant => {
let caption = constant.caption;
if (sceneName) {
let sceneCaption = constant.scenes[sceneName];
if (sceneCaption) {
caption = sceneCaption;
} else {
return;
}
}
let item = {
key: constant.name,
caption: caption,
};
Object.keys(constant).forEach(key => {
if (!DEFAULT_KEYS.includes(key)) {
item[key] = constant[key];
}
});
items.push(item);
});
return items;
}
toString() {
return this.name;
}
equals(other) {
return !!(other && other.constructor === this.constructor && other.name === this.name);
}
clone() {
const constant = new Enum(this.caption, this.scenes);
constant.ordinal = this.ordinal;
constant.name = this.name;
return constant;
}
supports(sceneName) {
return !!this.scenes[sceneName];
}
localeCompare(other) {
if (this.ordinal < other.ordinal) {
return -1;
} else if (this.ordinal > other.ordinal) {
return 1;
} else {
return 0;
}
}
}