choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
1,068 lines (905 loc) • 29.7 kB
JavaScript
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _extends from "@babel/runtime/helpers/extends";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import { __decorate } from "tslib";
import { action, computed, get, isObservableObject, observable, remove, runInAction, set as _set, toJS } from 'mobx';
import raf from 'raf';
import isFunction from 'lodash/isFunction';
import isEqual from 'lodash/isEqual';
import isObject from 'lodash/isObject';
import merge from 'lodash/merge';
import defer from 'lodash/defer';
import unionBy from 'lodash/unionBy';
import { getConfig } from '../../../es/configure';
import warning from '../../../es/_util/warning';
import DataSet from './DataSet';
import Validator from '../validator/Validator';
import { DataSetEvents, DataSetSelection, FieldTrim, FieldType } from './enum';
import lookupStore from '../stores/LookupCodeStore';
import lovCodeStore from '../stores/LovCodeStore';
import localeContext from '../locale-context';
import { getBaseType, getLimit, processValue } from './utils';
import isSame from '../_util/isSame';
import PromiseQueue from '../_util/PromiseQueue';
import isSameLike from '../_util/isSameLike';
import { buildURLWithAxiosConfig } from '../axios/utils';
import { getDateFormatByField } from '../field/utils';
import { getLovPara } from '../stores/utils';
import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number-field/utils';
function isEqualDynamicProps(oldProps, newProps) {
if (newProps === oldProps) {
return true;
}
if (isObject(newProps) && isObject(oldProps) && Object.keys(newProps).length) {
if (Object.keys(newProps).length !== Object.keys(toJS(oldProps)).length) {
return false;
}
return Object.keys(newProps).every(function (key) {
var value = newProps[key];
var oldValue = oldProps[key];
if (oldValue === value) {
return true;
}
if (isFunction(value) && isFunction(oldValue)) {
return value.toString() === oldValue.toString();
}
return isEqual(oldValue, value);
});
}
return isEqual(newProps, oldProps);
}
function getPropsFromLovConfig(lovCode, propsName) {
if (lovCode) {
var config = lovCodeStore.getConfig(lovCode);
if (config) {
if (config[propsName]) {
return _defineProperty({}, propsName, config[propsName]);
}
}
}
return {};
}
var Field =
/*#__PURE__*/
function () {
function Field() {
var _this = this;
var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var dataSet = arguments.length > 1 ? arguments[1] : undefined;
var record = arguments.length > 2 ? arguments[2] : undefined;
_classCallCheck(this, Field);
this.lastDynamicProps = {};
this.validatorPropKeys = [];
this.isDynamicPropsComputing = false;
runInAction(function () {
_this.validator = new Validator(_this);
_this.pending = new PromiseQueue();
_this.dataSet = dataSet;
_this.record = record;
_this.dirtyProps = {};
_this.props = props; // 优化性能,没有动态属性时不用处理, 直接引用dsField; 有options时,也不处理
if (!_this.getProp('options') && (!record || _this.getProp('dynamicProps'))) {
raf(function () {
_this.fetchLookup();
_this.fetchLovConfig();
});
}
});
}
_createClass(Field, [{
key: "getProps",
/**
* 获取所有属性
* @return 属性对象
*/
value: function getProps() {
var dsField = this.findDataSetField();
var lovCode = this.get('lovCode');
return merge({
lookupUrl: getConfig('lookupUrl')
}, Field.defaultProps, getPropsFromLovConfig(lovCode, 'textField'), getPropsFromLovConfig(lovCode, 'valueField'), dsField && dsField.props, this.props);
}
/**
* 根据属性名获取属性值
* @param propsName 属性名
* @return {any}
*/
}, {
key: "get",
value: function get(propsName) {
var prop = this.getProp(propsName);
if (prop !== undefined) {
return prop;
}
return Field.defaultProps[propsName];
}
}, {
key: "getProp",
value: function getProp(propsName) {
if (propsName !== 'dynamicProps') {
var dynamicProps = this.get('dynamicProps');
if (dynamicProps) {
if (typeof dynamicProps === 'function') {
warning(false, " The dynamicProps hook will be deprecated. Please use dynamicProps map.\n For e.g,\n Bad case:\n dynamicProps({ record }) {\n return {\n bind: record.get('xx'),\n label: record.get('yy'),\n }\n }\n Good case:\n dynamicProps = {\n bind({ record }) {\n return record.get('xx')\n },\n label({ record }) {\n return record.get('yy'),\n }\n }");
var props = this.executeDynamicProps(dynamicProps);
if (props && propsName in props) {
var prop = props[propsName];
this.checkDynamicProp(propsName, prop);
return prop;
}
} else {
var dynamicProp = dynamicProps[propsName];
if (typeof dynamicProp === 'function') {
var _prop = this.executeDynamicProps(dynamicProp);
if (_prop !== undefined) {
this.checkDynamicProp(propsName, _prop);
return _prop;
}
}
}
this.checkDynamicProp(propsName, undefined);
}
}
var value = get(this.props, propsName);
if (value !== undefined) {
return value;
}
var dsField = this.findDataSetField();
if (dsField) {
var dsValue = dsField.getProp(propsName);
if (dsValue !== undefined) {
return dsValue;
}
}
if (propsName === 'textField' || propsName === 'valueField') {
var lovCode = this.get('lovCode');
var lovProps = getPropsFromLovConfig(lovCode, propsName);
if (propsName in lovProps) {
return lovProps[propsName];
}
}
if (propsName === 'lookupUrl') {
return getConfig(propsName);
}
if (['min', 'max'].includes(propsName)) {
if (this.get('type') === FieldType.number) {
if (propsName === 'max') {
return MAX_SAFE_INTEGER;
} else {
return MIN_SAFE_INTEGER;
}
}
}
return undefined;
}
/**
* 设置属性值
* @param propsName 属性名
* @param value 属性值
* @return {any}
*/
}, {
key: "set",
value: function set(propsName, value) {
var oldValue = this.get(propsName);
if (!isEqualDynamicProps(oldValue, value)) {
if (!(propsName in this.dirtyProps)) {
_set(this.dirtyProps, propsName, oldValue);
} else if (isSame(toJS(this.dirtyProps[propsName]), value)) {
remove(this.dirtyProps, propsName);
}
_set(this.props, propsName, value);
var record = this.record,
dataSet = this.dataSet,
name = this.name;
if (record && propsName === 'type') {
record.set(name, processValue(record.get(name), this));
}
if (dataSet) {
dataSet.fireEvent(DataSetEvents.fieldChange, {
dataSet: dataSet,
record: record,
name: name,
field: this,
propsName: propsName,
value: value,
oldValue: oldValue
});
}
this.handlePropChange(propsName, value, oldValue);
}
}
/**
* 根据lookup值获取lookup对象
* @param value lookup值
* @return {object}
*/
}, {
key: "getLookupData",
value: function getLookupData() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getValue();
var valueField = this.get('valueField');
var data = {};
if (this.lookup) {
return this.lookup.find(function (obj) {
return isSameLike(get(obj, valueField), value);
}) || data;
}
return data;
}
}, {
key: "getValue",
value: function getValue() {
var dataSet = this.dataSet,
name = this.name;
var record = this.record || dataSet && dataSet.current;
if (record) {
return record.get(name);
}
}
/**
* 可以根据lookup值获取含义
* @param value lookup值
* @param boolean showValueIfNotFound
* @return {string}
*/
}, {
key: "getLookupText",
value: function getLookupText() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getValue();
var showValueIfNotFound = arguments.length > 1 ? arguments[1] : undefined;
var textField = this.get('textField');
var valueField = this.get('valueField');
var lookup = this.lookup;
if (lookup) {
var found = lookup.find(function (obj) {
return isSameLike(get(obj, valueField), value);
});
if (found) {
return get(found, textField);
}
if (showValueIfNotFound) {
return value;
}
return undefined;
}
}
/**
* 可以根据options值获取含义
* @param value opions值
* @param boolean showValueIfNotFound
* @return {string}
*/
}, {
key: "getOptionsText",
value: function getOptionsText() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getValue();
var showValueIfNotFound = arguments.length > 1 ? arguments[1] : undefined;
var textField = this.get('textField');
var valueField = this.get('valueField');
var options = this.options;
if (options) {
var found = options.find(function (record) {
return isSameLike(record.get(valueField), value);
});
if (found) {
return found.get(textField);
}
if (showValueIfNotFound) {
return value;
}
return undefined;
}
}
/**
* 根据lookup值获取lookup含义
* @param value lookup值
* @param boolean showValueIfNotFound
* @return {string}
*/
}, {
key: "getText",
value: function getText() {
var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getValue();
var showValueIfNotFound = arguments.length > 1 ? arguments[1] : undefined;
var textField = this.get('textField');
var valueField = this.get('valueField');
var lookup = this.lookup,
options = this.options;
if (lookup && !isObject(value)) {
return this.getLookupText(value, showValueIfNotFound);
}
if (options) {
var found = options.find(function (record) {
return isSameLike(record.get(valueField), value);
});
if (found) {
return found.get(textField);
}
}
if (textField && isObject(value)) {
if (isObservableObject(value)) {
return get(value, textField);
}
return value[textField];
}
return value;
}
}, {
key: "setOptions",
value: function setOptions(options) {
this.set('options', options);
}
}, {
key: "getOptions",
value: function getOptions() {
return this.options;
}
/**
* 重置设置的属性
*/
}, {
key: "reset",
value: function reset() {
_extends(this.props, this.dirtyProps);
this.dirtyProps = {};
}
}, {
key: "commit",
value: function commit() {
this.validator.reset();
}
/**
* 是否必选
* @return true | false
*/
}, {
key: "setLovPara",
/**
* 设置Lov的查询参数
* @param {String} name
* @param {Object} value
*/
value: function setLovPara(name, value) {
var p = toJS(this.get('lovPara')) || {};
if (value === null) {
delete p[name];
} else {
p[name] = value;
}
this.set('lovPara', p);
}
}, {
key: "getValidatorProps",
value: function getValidatorProps() {
var record = this.record,
dataSet = this.dataSet,
name = this.name,
type = this.type,
required = this.required;
if (record) {
var baseType = getBaseType(type);
var customValidator = this.get('validator');
var max = this.get('max');
var min = this.get('min');
var format = this.get('format') || getDateFormatByField(this, this.type);
var pattern = this.get('pattern');
var step = this.get('step');
var nonStrictStep = this.get('nonStrictStep') === undefined ? getConfig('numberFieldNonStrictStep') : this.get('nonStrictStep');
var minLength = baseType !== FieldType.string ? undefined : this.get('minLength');
var maxLength = baseType !== FieldType.string ? undefined : this.get('maxLength');
var label = this.get('label');
var range = this.get('range');
var multiple = this.get('multiple');
var unique = this.get('unique');
var defaultValidationMessages = this.get('defaultValidationMessages');
var validatorProps = {
type: type,
required: required,
record: record,
dataSet: dataSet,
name: name,
unique: unique,
customValidator: customValidator,
pattern: pattern,
max: getLimit(max, record),
min: getLimit(min, record),
step: step,
nonStrictStep: nonStrictStep,
minLength: minLength,
maxLength: maxLength,
label: label,
range: range,
multiple: multiple,
format: format,
defaultValidationMessages: defaultValidationMessages
};
if (!this.validatorPropKeys.length) {
this.validatorPropKeys = Object.keys(validatorProps);
}
return validatorProps;
}
}
/**
* 校验字段值
* 只有通过record.getField()获取的field才能校验
* @return true | false
*/
}, {
key: "checkValidity",
value: function () {
var _checkValidity = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee() {
var valid, record, validator, name, value;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
valid = true;
record = this.record, validator = this.validator, name = this.name;
if (!record) {
_context.next = 8;
break;
}
validator.reset();
value = record.get(name);
_context.next = 7;
return validator.checkValidity(value);
case 7:
valid = _context.sent;
case 8:
return _context.abrupt("return", valid);
case 9:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
function checkValidity() {
return _checkValidity.apply(this, arguments);
}
return checkValidity;
}()
/**
* 请求lookup值, 如有缓存值直接获得。
* @param noCache default: undefined
* @return Promise<object[]>
*/
}, {
key: "fetchLookup",
value: function () {
var _fetchLookup = _asyncToGenerator(
/*#__PURE__*/
_regeneratorRuntime.mark(function _callee2() {
var _this2 = this;
var noCache,
batch,
lookupCode,
lovPara,
dsField,
result,
axiosConfig,
dsConfig,
_args2 = arguments;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
noCache = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : undefined;
batch = this.get('lookupBatchAxiosConfig') || getConfig('lookupBatchAxiosConfig');
lookupCode = this.get('lookupCode');
lovPara = getLovPara(this, this.record);
dsField = this.findDataSetField();
if (!(batch && lookupCode && Object.keys(lovPara).length === 0)) {
_context2.next = 14;
break;
}
if (!(dsField && dsField.get('lookupCode') === lookupCode)) {
_context2.next = 9;
break;
}
this.set('lookup', undefined);
return _context2.abrupt("return", dsField.get('lookup'));
case 9:
_context2.next = 11;
return this.pending.add(lookupStore.fetchLookupDataInBatch(lookupCode, batch));
case 11:
result = _context2.sent;
_context2.next = 24;
break;
case 14:
axiosConfig = lookupStore.getAxiosConfig(this, noCache);
if (!(dsField && noCache === false)) {
_context2.next = 20;
break;
}
dsConfig = lookupStore.getAxiosConfig(dsField);
if (!(dsConfig.url && buildURLWithAxiosConfig(dsConfig) === buildURLWithAxiosConfig(axiosConfig))) {
_context2.next = 20;
break;
}
this.set('lookup', undefined);
return _context2.abrupt("return", dsField.get('lookup'));
case 20:
if (!axiosConfig.url) {
_context2.next = 24;
break;
}
_context2.next = 23;
return this.pending.add(lookupStore.fetchLookupData(axiosConfig));
case 23:
result = _context2.sent;
case 24:
if (result) {
runInAction(function () {
var lookup = _this2.lookup;
_this2.set('lookup', result);
var value = _this2.getValue();
var valueField = _this2.get('valueField');
if (value && valueField && lookup) {
var _ref2;
var values = _this2.get('multiple') ? (_ref2 = []).concat.apply(_ref2, _toConsumableArray(value)) : [].concat(value);
_this2.set('lookupData', values.reduce(function (lookupData, v) {
var found = lookup.find(function (item) {
return isSameLike(item[valueField], v);
});
if (found) {
lookupData.push(found);
}
return lookupData;
}, []));
}
});
}
return _context2.abrupt("return", result);
case 26:
case "end":
return _context2.stop();
}
}
}, _callee2, this);
}));
function fetchLookup() {
return _fetchLookup.apply(this, arguments);
}
return fetchLookup;
}()
}, {
key: "fetchLovConfig",
value: function fetchLovConfig() {
var lovCode = this.get('lovCode');
if (lovCode) {
this.pending.add(lovCodeStore.fetchConfig(lovCode, this));
}
}
}, {
key: "isValid",
value: function isValid() {
return this.valid;
}
}, {
key: "getValidationMessage",
value: function getValidationMessage() {
return this.validator.validationMessage;
}
}, {
key: "getValidityState",
value: function getValidityState() {
return this.validator.validity;
}
}, {
key: "getValidationErrorValues",
value: function getValidationErrorValues() {
return this.validator.validationResults;
}
}, {
key: "ready",
value: function ready() {
// const { options } = this;
// return Promise.all([this.pending.ready(), options && options.ready()]);
return this.pending.ready();
}
}, {
key: "findDataSetField",
value: function findDataSetField() {
var dataSet = this.dataSet,
name = this.name,
record = this.record;
if (record && dataSet && name) {
return dataSet.getField(name);
}
}
}, {
key: "checkDynamicProp",
value: function checkDynamicProp(propsName, newProp) {
var _this3 = this;
var oldProp = this.lastDynamicProps[propsName];
if (!isEqualDynamicProps(oldProp, newProp)) {
defer(action(function () {
if (_this3.validatorPropKeys.includes(propsName) || propsName === 'validator') {
_this3.validator.reset();
}
_this3.handlePropChange(propsName, newProp, oldProp);
}));
}
this.lastDynamicProps[propsName] = newProp;
}
}, {
key: "handlePropChange",
value: function handlePropChange(propsName, newProp, oldProp) {
if (propsName === 'bind' && this.type !== FieldType.intl) {
var record = this.record;
if (record && !this.dirty) {
if (newProp && oldProp) {
record.init(newProp, record.get(oldProp));
}
if (oldProp) {
record.init(oldProp, undefined);
}
}
return;
}
if (['type', 'lookupUrl', 'lookupCode', 'lookupAxiosConfig', 'lovCode', 'lovQueryAxiosConfig', 'lovPara', 'cascadeMap', 'lovQueryUrl', 'optionsProps'].includes(propsName)) {
this.set('lookupData', undefined);
this.fetchLookup();
}
if (['lovCode', 'lovDefineAxiosConfig', 'lovDefineUrl', 'optionsProps'].includes(propsName)) {
this.fetchLovConfig();
}
}
}, {
key: "executeDynamicProps",
value: function executeDynamicProps(dynamicProps) {
var dataSet = this.dataSet,
name = this.name,
record = this.record;
if (this.isDynamicPropsComputing) {
warning(false, "Cycle dynamicProps execution of field<".concat(name, ">."));
} else if (dataSet && record) {
this.isDynamicPropsComputing = true;
var props = dynamicProps({
dataSet: dataSet,
record: record,
name: name
});
this.isDynamicPropsComputing = false;
return props;
}
}
}, {
key: "pristineProps",
get: function get() {
return _objectSpread({}, this.props, {}, this.dirtyProps);
},
set: function set(props) {
var _this4 = this;
runInAction(function () {
var dirtyProps = _this4.dirtyProps;
var dirtyKeys = Object.keys(dirtyProps);
if (dirtyKeys.length) {
var newProps = {};
dirtyKeys.forEach(function (key) {
var item = _this4.props[key];
newProps[key] = item;
if (isSame(item, props[key])) {
delete dirtyProps[key];
} else {
dirtyProps[key] = props[key];
}
});
_this4.props = _objectSpread({}, props, {}, newProps);
} else {
_this4.props = props;
}
});
}
}, {
key: "lookup",
get: function get() {
var lookup = this.get('lookup');
var valueField = this.get('valueField');
if (lookup) {
var lookupData = this.get('lookupData') || [];
return unionBy(lookup.concat(lookupData), valueField);
}
return undefined;
}
}, {
key: "options",
get: function get() {
var options = this.get('options');
if (options) {
return options;
} // 确保 lookup 相关配置介入观察
lookupStore.getAxiosConfig(this);
var optionsProps = this.get('optionsProps');
var lookup = this.lookup,
type = this.type;
if (lookup) {
var parentField = this.get('parentField');
var idField = this.get('idField') || this.get('valueField');
var selection = this.get('multiple') ? DataSetSelection.multiple : DataSetSelection.single;
return new DataSet(_objectSpread({
data: lookup,
paging: false,
selection: selection,
idField: idField,
parentField: parentField
}, optionsProps));
}
var lovCode = this.get('lovCode');
if (lovCode) {
if (type === FieldType.object || type === FieldType.auto) {
return lovCodeStore.getLovDataSet(lovCode, this, optionsProps);
}
}
return undefined;
}
}, {
key: "intlFields",
get: function get() {
var record = this.record,
type = this.type,
name = this.name;
var tlsKey = getConfig('tlsKey');
if (type === FieldType.intl && record && record.get(tlsKey)) {
return Object.keys(localeContext.supports).reduce(function (arr, lang) {
var field = record.getField("".concat(tlsKey, ".").concat(name, ".").concat(lang));
if (field) {
arr.push(field);
}
return arr;
}, []);
}
return [];
}
}, {
key: "dirty",
get: function get() {
var record = this.record,
name = this.name,
intlFields = this.intlFields;
if (intlFields.length) {
return intlFields.some(function (langField) {
return langField.dirty;
});
}
if (record) {
var dirtyData = record.dirtyData;
return _toConsumableArray(dirtyData.keys()).some(function (key) {
return key === name || key.startsWith("".concat(name, "."));
});
}
return false;
}
}, {
key: "name",
get: function get() {
return this.props.name;
}
}, {
key: "order",
get: function get() {
return this.get('order');
},
set: function set(order) {
this.set('order', order);
}
}, {
key: "valid",
get: function get() {
var intlFields = this.intlFields,
valid = this.validator.validity.valid;
if (valid && intlFields.length) {
return intlFields.every(function (field) {
return field.valid;
});
}
return valid;
}
}, {
key: "validationMessage",
get: function get() {
return this.validator.validationMessage;
}
}, {
key: "required",
get: function get() {
return this.get('required');
}
/**
* 设置是否必选
* @param required 是否必选
*/
,
set: function set(required) {
this.set('required', required);
}
/**
* 是否只读
* @return true | false
*/
}, {
key: "readOnly",
get: function get() {
return this.get('readOnly');
}
/**
* 是否禁用
* @return true | false
*/
,
/**
* 设置是否只读
* @param readOnly 是否只读
*/
set: function set(readOnly) {
this.set('readOnly', readOnly);
}
/**
* 设置是否禁用
* @param disabled 是否禁用
*/
}, {
key: "disabled",
get: function get() {
return this.get('disabled');
},
set: function set(disabled) {
this.set('disabled', disabled);
}
/**
* 获取字段类型
* @return 获取字段类型
*/
}, {
key: "type",
get: function get() {
return this.get('type');
}
/**
* 设置字段类型
* @param type 字段类型
*/
,
set: function set(type) {
this.set('type', type);
}
}]);
return Field;
}();
export { Field as default };
Field.defaultProps = {
type: FieldType.auto,
required: false,
readOnly: false,
disabled: false,
group: false,
textField: 'meaning',
valueField: 'value',
trueValue: true,
falseValue: false,
trim: FieldTrim.both
};
__decorate([observable], Field.prototype, "props", void 0);
__decorate([observable], Field.prototype, "dirtyProps", void 0);
__decorate([computed], Field.prototype, "pristineProps", null);
__decorate([computed], Field.prototype, "lookup", null);
__decorate([computed], Field.prototype, "options", null);
__decorate([computed], Field.prototype, "intlFields", null);
__decorate([computed], Field.prototype, "dirty", null);
__decorate([computed], Field.prototype, "valid", null);
__decorate([computed], Field.prototype, "validationMessage", null);
__decorate([action], Field.prototype, "set", null);
__decorate([action], Field.prototype, "reset", null);
__decorate([action], Field.prototype, "commit", null);
__decorate([action], Field.prototype, "setLovPara", null);
__decorate([action], Field.prototype, "checkValidity", null);
//# sourceMappingURL=Field.js.map