UNPKG

choerodon-ui

Version:

An enterprise-class UI design language and React-based implementation

1,068 lines (905 loc) 29.7 kB
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