fmui-base 2.2.61 → 2.2.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/lib/form/form.js +100 -4
- package/lib/process_info/processInfo.js +8 -8
- package/lib/select_input/index.js +16 -0
- package/lib/select_input/selectInput.js +434 -0
- package/lib/select_input/selectInput.less +87 -0
- package/package.json +1 -1
package/README.md
CHANGED
package/lib/form/form.js
CHANGED
|
@@ -101,6 +101,10 @@ var _sign = require('../signature/sign');
|
|
|
101
101
|
|
|
102
102
|
var _sign2 = _interopRequireDefault(_sign);
|
|
103
103
|
|
|
104
|
+
var _select_input = require('../select_input');
|
|
105
|
+
|
|
106
|
+
var _select_input2 = _interopRequireDefault(_select_input);
|
|
107
|
+
|
|
104
108
|
require('./form.less');
|
|
105
109
|
|
|
106
110
|
var _db = require('../db/db');
|
|
@@ -739,6 +743,7 @@ var PageHome = function (_React$Component) {
|
|
|
739
743
|
value = form.title;
|
|
740
744
|
} else if (itemType == 'radio') {
|
|
741
745
|
//单选
|
|
746
|
+
itemParam.isinput = '0';
|
|
742
747
|
var selectItem = form.multiItems; //选项
|
|
743
748
|
var selectOptions = [];
|
|
744
749
|
if (selectItem) {
|
|
@@ -756,15 +761,26 @@ var PageHome = function (_React$Component) {
|
|
|
756
761
|
selectOptions.push(option);
|
|
757
762
|
}
|
|
758
763
|
});
|
|
764
|
+
for (var i = 0; i < selectItem.length; i++) {
|
|
765
|
+
if (selectItem[i].isinput && selectItem[i].isinput == "1" && (typeof selectItem[i].state == 'undefined' || selectItem[i].state == "1")) {
|
|
766
|
+
itemParam.isinput = '1';
|
|
767
|
+
}
|
|
768
|
+
}
|
|
759
769
|
}
|
|
760
770
|
}
|
|
761
771
|
if (value == "") {
|
|
762
772
|
value = null;
|
|
763
773
|
}
|
|
764
|
-
itemParam.
|
|
765
|
-
|
|
774
|
+
if (itemParam.isinput == '1') {
|
|
775
|
+
itemParam.selectOptions = selectItem;
|
|
776
|
+
itemParam.selectItem = selectItem;
|
|
777
|
+
} else {
|
|
778
|
+
itemParam.selectOptions = selectOptions;
|
|
779
|
+
itemParam.selectItem = selectOptions;
|
|
780
|
+
}
|
|
766
781
|
} else if (itemType == 'checkbox') {
|
|
767
782
|
//多选
|
|
783
|
+
itemParam.isinput = '0';
|
|
768
784
|
var selectItem = form.multiItems; //选项
|
|
769
785
|
var selectOptions = [];
|
|
770
786
|
if (selectItem) {
|
|
@@ -796,10 +812,20 @@ var PageHome = function (_React$Component) {
|
|
|
796
812
|
selectOptions.push(option);
|
|
797
813
|
}
|
|
798
814
|
});
|
|
815
|
+
for (var i = 0; i < selectItem.length; i++) {
|
|
816
|
+
if (selectItem[i].isinput && selectItem[i].isinput == "1" && (typeof selectItem[i].state == 'undefined' || selectItem[i].state == "1")) {
|
|
817
|
+
itemParam.isinput = '1';
|
|
818
|
+
}
|
|
819
|
+
}
|
|
799
820
|
}
|
|
800
821
|
}
|
|
801
|
-
itemParam.
|
|
802
|
-
|
|
822
|
+
if (itemParam.isinput == '1') {
|
|
823
|
+
itemParam.selectOptions = selectItem;
|
|
824
|
+
itemParam.selectItem = selectItem;
|
|
825
|
+
} else {
|
|
826
|
+
itemParam.selectOptions = selectOptions;
|
|
827
|
+
itemParam.selectItem = selectOptions;
|
|
828
|
+
}
|
|
803
829
|
} else if (itemType == 'select') {
|
|
804
830
|
//下拉选择
|
|
805
831
|
var selectItem = form.multiItems; //选项
|
|
@@ -2562,6 +2588,24 @@ var PageHome = function (_React$Component) {
|
|
|
2562
2588
|
this.props.onChange(data, itemParam);
|
|
2563
2589
|
}
|
|
2564
2590
|
}
|
|
2591
|
+
|
|
2592
|
+
//下拉可输入
|
|
2593
|
+
|
|
2594
|
+
}, {
|
|
2595
|
+
key: 'selectInputChange',
|
|
2596
|
+
value: function selectInputChange(code, value) {
|
|
2597
|
+
if (value) {
|
|
2598
|
+
var data = this.props.data;
|
|
2599
|
+
var selectValue = value;
|
|
2600
|
+
data = this.editData(code, selectValue, data);
|
|
2601
|
+
var itemParam = this.state.itemParam;
|
|
2602
|
+
itemParam.value = value;
|
|
2603
|
+
this.setState({
|
|
2604
|
+
itemParam: itemParam
|
|
2605
|
+
});
|
|
2606
|
+
this.props.onChange(data, itemParam);
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2565
2609
|
}, {
|
|
2566
2610
|
key: 'getWeekdaysByDate',
|
|
2567
2611
|
value: function getWeekdaysByDate(date) {
|
|
@@ -3605,6 +3649,32 @@ var PageHome = function (_React$Component) {
|
|
|
3605
3649
|
t.state.itemParam.isVerifySing == "1" ? _react2.default.createElement('i', { className: 'iconfont icon-checked t-PT10', style: { color: 'green' } }) : t.state.itemParam.isVerifySing == "2" ? _react2.default.createElement('i', { className: 'iconfont icon-close t-PT10', style: { color: 'red' } }) : ""
|
|
3606
3650
|
)
|
|
3607
3651
|
)
|
|
3652
|
+
) : this.state.itemParam.itemType == 'radio' && this.state.itemParam.isinput == '1' ? _react2.default.createElement(
|
|
3653
|
+
'div',
|
|
3654
|
+
{ className: t.state.itemParam.fieldId, style: t.state.itemParam.formStyleObj.contentStyle },
|
|
3655
|
+
_react2.default.createElement(
|
|
3656
|
+
_Group2.default.List,
|
|
3657
|
+
{ borderTopNone: true },
|
|
3658
|
+
_react2.default.createElement(
|
|
3659
|
+
'div',
|
|
3660
|
+
{ className: 't-FBH', id: t.state.prefixName + "_" + t.state.itemParam.key },
|
|
3661
|
+
_react2.default.createElement(
|
|
3662
|
+
'div',
|
|
3663
|
+
{ className: 't-W100' },
|
|
3664
|
+
_react2.default.createElement(_select_input2.default, {
|
|
3665
|
+
required: t.state.itemParam.required,
|
|
3666
|
+
label: t.state.itemParam.title,
|
|
3667
|
+
readOnly: t.state.itemParam.readOnly,
|
|
3668
|
+
options: t.state.itemParam.selectOptions,
|
|
3669
|
+
value: t.state.itemParam.value,
|
|
3670
|
+
multiLine: true,
|
|
3671
|
+
selectType: 'radio',
|
|
3672
|
+
onSelect: t.selectInputChange.bind(t, t.state.itemParam.key)
|
|
3673
|
+
})
|
|
3674
|
+
),
|
|
3675
|
+
t.state.itemParam.isVerifySing == "1" ? _react2.default.createElement('i', { className: 'iconfont icon-checked t-PT10', style: { color: 'green' } }) : t.state.itemParam.isVerifySing == "2" ? _react2.default.createElement('i', { className: 'iconfont icon-close t-PT10', style: { color: 'red' } }) : ""
|
|
3676
|
+
)
|
|
3677
|
+
)
|
|
3608
3678
|
) : this.state.itemParam.itemType == 'radio' ? _react2.default.createElement(
|
|
3609
3679
|
'div',
|
|
3610
3680
|
{ className: t.state.itemParam.fieldId, style: t.state.itemParam.formStyleObj.contentStyle },
|
|
@@ -3631,6 +3701,32 @@ var PageHome = function (_React$Component) {
|
|
|
3631
3701
|
t.state.itemParam.isVerifySing == "1" ? _react2.default.createElement('i', { className: 'iconfont icon-checked t-PT10', style: { color: 'green' } }) : t.state.itemParam.isVerifySing == "2" ? _react2.default.createElement('i', { className: 'iconfont icon-close t-PT10', style: { color: 'red' } }) : ""
|
|
3632
3702
|
)
|
|
3633
3703
|
)
|
|
3704
|
+
) : this.state.itemParam.itemType == 'checkbox' && this.state.itemParam.isinput == '1' ? _react2.default.createElement(
|
|
3705
|
+
'div',
|
|
3706
|
+
{ className: t.state.itemParam.fieldId, style: t.state.itemParam.formStyleObj.contentStyle },
|
|
3707
|
+
_react2.default.createElement(
|
|
3708
|
+
_Group2.default.List,
|
|
3709
|
+
{ borderTopNone: true },
|
|
3710
|
+
_react2.default.createElement(
|
|
3711
|
+
'div',
|
|
3712
|
+
{ className: 't-FBH', id: t.state.prefixName + "_" + t.state.itemParam.key },
|
|
3713
|
+
_react2.default.createElement(
|
|
3714
|
+
'div',
|
|
3715
|
+
{ className: 't-W100' },
|
|
3716
|
+
_react2.default.createElement(_select_input2.default, {
|
|
3717
|
+
required: t.state.itemParam.required,
|
|
3718
|
+
label: t.state.itemParam.title,
|
|
3719
|
+
readOnly: t.state.itemParam.readOnly,
|
|
3720
|
+
options: t.state.itemParam.selectOptions,
|
|
3721
|
+
value: t.state.itemParam.value,
|
|
3722
|
+
multiLine: true,
|
|
3723
|
+
selectType: 'checkbox',
|
|
3724
|
+
onSelect: t.selectInputChange.bind(t, t.state.itemParam.key)
|
|
3725
|
+
})
|
|
3726
|
+
),
|
|
3727
|
+
t.state.itemParam.isVerifySing == "1" ? _react2.default.createElement('i', { className: 'iconfont icon-checked t-PT10', style: { color: 'green' } }) : t.state.itemParam.isVerifySing == "2" ? _react2.default.createElement('i', { className: 'iconfont icon-close t-PT10', style: { color: 'red' } }) : ""
|
|
3728
|
+
)
|
|
3729
|
+
)
|
|
3634
3730
|
) : this.state.itemParam.itemType == 'checkbox' ? _react2.default.createElement(
|
|
3635
3731
|
'div',
|
|
3636
3732
|
{ className: t.state.itemParam.fieldId, style: t.state.itemParam.formStyleObj.contentStyle },
|
|
@@ -2151,11 +2151,11 @@ var PageHome = function (_React$Component) {
|
|
|
2151
2151
|
if (documentId) {
|
|
2152
2152
|
this.scrollToAnchor(documentId);
|
|
2153
2153
|
}
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2154
|
+
_Toast2.default.show({
|
|
2155
|
+
type: 'error',
|
|
2156
|
+
content: '意见不能为空!'
|
|
2157
|
+
});
|
|
2158
|
+
return false;
|
|
2159
2159
|
}
|
|
2160
2160
|
}
|
|
2161
2161
|
}
|
|
@@ -4970,8 +4970,8 @@ var PageHome = function (_React$Component) {
|
|
|
4970
4970
|
|
|
4971
4971
|
//操作回调
|
|
4972
4972
|
var type = 6;
|
|
4973
|
-
if (t.state.isStart && t.state.dataId == '') {
|
|
4974
|
-
//是不是起始节点
|
|
4973
|
+
if (t.state.isStart && (t.state.dataId == '' || t.state.isSub == '2')) {
|
|
4974
|
+
//是不是起始节点 或再次发起
|
|
4975
4975
|
type = 4;
|
|
4976
4976
|
}
|
|
4977
4977
|
if (t.state.isEnd) {
|
|
@@ -4979,7 +4979,7 @@ var PageHome = function (_React$Component) {
|
|
|
4979
4979
|
type = 1;
|
|
4980
4980
|
}
|
|
4981
4981
|
var dataId = t.state.dataId;
|
|
4982
|
-
if (dataId == "") {
|
|
4982
|
+
if (dataId == "" || t.state.isSub == '2') {
|
|
4983
4983
|
dataId = content.dataId;
|
|
4984
4984
|
t.setState({ dataId: dataId });
|
|
4985
4985
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
var _selectInput = require('./selectInput');
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, 'default', {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function get() {
|
|
12
|
+
return _interopRequireDefault(_selectInput).default;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = undefined;
|
|
7
|
+
|
|
8
|
+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
9
|
+
|
|
10
|
+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
11
|
+
|
|
12
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
13
|
+
|
|
14
|
+
var _react = require('react');
|
|
15
|
+
|
|
16
|
+
var _react2 = _interopRequireDefault(_react);
|
|
17
|
+
|
|
18
|
+
var _Field = require('saltui/lib/Field');
|
|
19
|
+
|
|
20
|
+
var _Field2 = _interopRequireDefault(_Field);
|
|
21
|
+
|
|
22
|
+
require('./selectInput.less');
|
|
23
|
+
|
|
24
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
25
|
+
|
|
26
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
27
|
+
|
|
28
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
29
|
+
|
|
30
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
31
|
+
|
|
32
|
+
// 单个选项值与输入框值之间的分隔符。
|
|
33
|
+
// 例如:c$#$#111 表示选中 value=c,且该项输入框内容为 111。
|
|
34
|
+
var KV_SEP = '$#$#';
|
|
35
|
+
|
|
36
|
+
// 多个选中项之间的分隔符。
|
|
37
|
+
// 例如:c$#$#111#$#$d$#$#222 表示同时选中 c、d 两项。
|
|
38
|
+
var PAIR_SEP = '#$#$';
|
|
39
|
+
|
|
40
|
+
var SelectInput = function (_React$Component) {
|
|
41
|
+
_inherits(SelectInput, _React$Component);
|
|
42
|
+
|
|
43
|
+
function SelectInput(props) {
|
|
44
|
+
_classCallCheck(this, SelectInput);
|
|
45
|
+
|
|
46
|
+
// 内部状态完全由外部 props 推导,不在 constructor 中手工拆分数据。
|
|
47
|
+
// 这样首次渲染与后续 props 更新可以共用同一套解析逻辑。
|
|
48
|
+
var _this = _possibleConstructorReturn(this, (SelectInput.__proto__ || Object.getPrototypeOf(SelectInput)).call(this, props));
|
|
49
|
+
|
|
50
|
+
_this.state = _this.buildStateFromProps(props);
|
|
51
|
+
return _this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
_createClass(SelectInput, [{
|
|
55
|
+
key: 'componentDidUpdate',
|
|
56
|
+
value: function componentDidUpdate(prevProps) {
|
|
57
|
+
var propsChanged = prevProps.value !== this.props.value || prevProps.options !== this.props.options || prevProps.selectType !== this.props.selectType;
|
|
58
|
+
|
|
59
|
+
if (propsChanged) {
|
|
60
|
+
// 外部 value 或选项变化后,重新同步内部选中态和输入值。
|
|
61
|
+
this.setState(this.buildStateFromProps(this.props));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}, {
|
|
65
|
+
key: 'getOptions',
|
|
66
|
+
value: function getOptions(props) {
|
|
67
|
+
// 统一标准化外部 options,屏蔽不同页面传值字段差异。
|
|
68
|
+
// 最终内部只使用:value、text、isInput、isDefault。
|
|
69
|
+
var options = props.options || [];
|
|
70
|
+
return options.map(function (item) {
|
|
71
|
+
var text = item.text || item.name || item.label || item.value;
|
|
72
|
+
var isInput = item.isinput === '1' || item.isinput === 1 || item.isInput === true;
|
|
73
|
+
var isDefault = item.isDefault === 1 || item.isDefault === '1';
|
|
74
|
+
return {
|
|
75
|
+
value: item.value,
|
|
76
|
+
text: text,
|
|
77
|
+
isInput: isInput,
|
|
78
|
+
isDefault: isDefault
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}, {
|
|
83
|
+
key: 'splitPair',
|
|
84
|
+
value: function splitPair(part) {
|
|
85
|
+
// 将单个“值 + 输入框内容”片段拆成结构化数据。
|
|
86
|
+
// 输入:c$#$#111
|
|
87
|
+
// 输出:{ selected: 'c', inputValue: '111' }
|
|
88
|
+
// 如果没有输入框值,例如只传 c,则 inputValue 为空字符串。
|
|
89
|
+
var index = part.indexOf(KV_SEP);
|
|
90
|
+
if (index === -1) {
|
|
91
|
+
return {
|
|
92
|
+
selected: part,
|
|
93
|
+
inputValue: ''
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
selected: part.substring(0, index),
|
|
98
|
+
inputValue: part.substring(index + KV_SEP.length)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}, {
|
|
102
|
+
key: 'parseValueByType',
|
|
103
|
+
value: function parseValueByType(value, selectType, options) {
|
|
104
|
+
// 解析外部传入的 value,转换成组件内部可直接渲染的状态:
|
|
105
|
+
// 1. inputValues: 各选项输入框值,格式如 { c: '111', d: '222' }
|
|
106
|
+
// 2. selectedRadio: 单选当前选中的 value
|
|
107
|
+
// 3. selectedMap: 多选当前选中项映射,格式如 { c: true, d: true }
|
|
108
|
+
var inputValues = {};
|
|
109
|
+
var selectedRadio = '';
|
|
110
|
+
var selectedMap = {};
|
|
111
|
+
|
|
112
|
+
if (selectType === 'radio') {
|
|
113
|
+
// 单选只维护一个 selectedRadio,输入框内容挂在对应 value 下。
|
|
114
|
+
// 支持两种格式:
|
|
115
|
+
// 1. 字符串:a 或 a$#$#备注
|
|
116
|
+
// 2. 对象:{ value: 'a', text: 'A' }
|
|
117
|
+
if (typeof value === 'string' && value !== '') {
|
|
118
|
+
var pair = this.splitPair(value);
|
|
119
|
+
selectedRadio = pair.selected;
|
|
120
|
+
if (pair.inputValue !== '') {
|
|
121
|
+
inputValues[pair.selected] = pair.inputValue;
|
|
122
|
+
}
|
|
123
|
+
} else if (value && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value.value !== undefined) {
|
|
124
|
+
selectedRadio = value.value;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!selectedRadio) {
|
|
128
|
+
// 没有传值时,回退到第一个默认选中且未禁用的选项。
|
|
129
|
+
// 这里的“默认选中”依赖 options[i].isDefault。
|
|
130
|
+
for (var i = 0; i < options.length; i++) {
|
|
131
|
+
if (options[i].isDefault) {
|
|
132
|
+
selectedRadio = options[i].value;
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} else {
|
|
138
|
+
// 多选统一转成 selectedMap,后续渲染时按 value 快速判断是否勾选。
|
|
139
|
+
// 支持三种 value 来源:
|
|
140
|
+
// 1. 编码字符串:c$#$#111#$#$d$#$#222
|
|
141
|
+
// 2. 普通字符串:a,b,c
|
|
142
|
+
// 3. 数组:['a', 'b', 'c']
|
|
143
|
+
var selectedValues = [];
|
|
144
|
+
if (typeof value === 'string' && value !== '') {
|
|
145
|
+
if (value.indexOf(KV_SEP) !== -1 || value.indexOf(PAIR_SEP) !== -1) {
|
|
146
|
+
// 支持 c$#$#111#$#$d$#$#222 这种“多项 + 输入框内容”格式。
|
|
147
|
+
var parts = value.split(PAIR_SEP);
|
|
148
|
+
for (var _i = 0; _i < parts.length; _i++) {
|
|
149
|
+
if (!parts[_i]) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
var _pair = this.splitPair(parts[_i]);
|
|
153
|
+
if (_pair.selected !== '') {
|
|
154
|
+
// 选中项单独存进 selectedValues,输入框值按 value 建索引。
|
|
155
|
+
selectedValues.push(_pair.selected);
|
|
156
|
+
inputValues[_pair.selected] = _pair.inputValue;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
// 兼容普通逗号分隔的多选值,例如 a,b,c。
|
|
161
|
+
selectedValues = value.split(',').filter(function (item) {
|
|
162
|
+
return item !== '';
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
} else if (Array.isArray(value)) {
|
|
166
|
+
selectedValues = value;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (selectedValues.length === 0) {
|
|
170
|
+
// 没有传值时,多选回退到所有默认选中且未禁用的项。
|
|
171
|
+
for (var _i2 = 0; _i2 < options.length; _i2++) {
|
|
172
|
+
if (options[_i2].isDefault) {
|
|
173
|
+
selectedValues.push(options[_i2].value);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
selectedValues.forEach(function (item) {
|
|
179
|
+
// selectedMap 用来支撑 render 时的 O(1) 勾选判断。
|
|
180
|
+
selectedMap[item] = true;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
inputValues: inputValues,
|
|
186
|
+
selectedRadio: selectedRadio,
|
|
187
|
+
selectedMap: selectedMap
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}, {
|
|
191
|
+
key: 'buildStateFromProps',
|
|
192
|
+
value: function buildStateFromProps(props) {
|
|
193
|
+
var selectType = props.selectType === 'checkbox' ? 'checkbox' : 'radio';
|
|
194
|
+
var options = this.getOptions(props);
|
|
195
|
+
// 每次都根据 props 重建内部状态,避免受旧 state 残留影响。
|
|
196
|
+
var parsed = this.parseValueByType(props.value, selectType, options);
|
|
197
|
+
|
|
198
|
+
// state 字段说明:
|
|
199
|
+
// selectType: 当前模式,radio 或 checkbox
|
|
200
|
+
// options: 标准化后的选项列表
|
|
201
|
+
// inputValues: 当前所有输入框内容
|
|
202
|
+
// selectedRadio: 单选模式下的已选 value
|
|
203
|
+
// selectedMap: 多选模式下的已选映射
|
|
204
|
+
return {
|
|
205
|
+
selectType: selectType,
|
|
206
|
+
options: options,
|
|
207
|
+
inputValues: parsed.inputValues,
|
|
208
|
+
selectedRadio: parsed.selectedRadio,
|
|
209
|
+
selectedMap: parsed.selectedMap
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}, {
|
|
213
|
+
key: 'getOptionByValue',
|
|
214
|
+
value: function getOptionByValue(value) {
|
|
215
|
+
// 根据 value 找到当前选项元数据,用于判断该选项是否带输入框等属性。
|
|
216
|
+
var options = this.state.options;
|
|
217
|
+
for (var i = 0; i < options.length; i++) {
|
|
218
|
+
if (options[i].value === value) {
|
|
219
|
+
return options[i];
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}, {
|
|
225
|
+
key: 'buildEmitValue',
|
|
226
|
+
value: function buildEmitValue(nextState) {
|
|
227
|
+
// 将内部状态重新编码成父页面需要的字符串格式。
|
|
228
|
+
// 这是组件对外唯一的数据输出协议。
|
|
229
|
+
var selectType = nextState.selectType;
|
|
230
|
+
var options = nextState.options;
|
|
231
|
+
|
|
232
|
+
if (selectType === 'radio') {
|
|
233
|
+
// 单选回传 value 或 value$#$#输入内容。
|
|
234
|
+
var selectedValue = nextState.selectedRadio;
|
|
235
|
+
if (!selectedValue) {
|
|
236
|
+
return '';
|
|
237
|
+
}
|
|
238
|
+
var option = this.getOptionByValue(selectedValue);
|
|
239
|
+
if (option && option.isInput) {
|
|
240
|
+
var text = nextState.inputValues[selectedValue] || '';
|
|
241
|
+
return selectedValue + KV_SEP + text;
|
|
242
|
+
}
|
|
243
|
+
return selectedValue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 多选按 options 原顺序拼接,保证回传值稳定。
|
|
247
|
+
// 这样即使用户先点 D 再点 C,最终输出仍可按 options 顺序固定下来。
|
|
248
|
+
var selectedValues = [];
|
|
249
|
+
for (var i = 0; i < options.length; i++) {
|
|
250
|
+
var _option = options[i];
|
|
251
|
+
if (nextState.selectedMap[_option.value]) {
|
|
252
|
+
if (_option.isInput) {
|
|
253
|
+
var _text = nextState.inputValues[_option.value] || '';
|
|
254
|
+
selectedValues.push(_option.value + KV_SEP + _text);
|
|
255
|
+
} else {
|
|
256
|
+
selectedValues.push(_option.value);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (selectedValues.length === 0) {
|
|
262
|
+
// 没有任何选中项时,对外统一返回空字符串。
|
|
263
|
+
return '';
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
var hasInputType = false;
|
|
267
|
+
for (var _i3 = 0; _i3 < options.length; _i3++) {
|
|
268
|
+
if (options[_i3].isInput) {
|
|
269
|
+
hasInputType = true;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (hasInputType) {
|
|
275
|
+
// 只要存在可输入选项,就按“值 + 输入内容”的协议回传。
|
|
276
|
+
// 即使某个已选项当前输入框为空,也会保留 value$#$# 的结构。
|
|
277
|
+
return selectedValues.join(PAIR_SEP);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// 所有项都不带输入框时,退回普通多选格式。
|
|
281
|
+
return selectedValues.join(',');
|
|
282
|
+
}
|
|
283
|
+
}, {
|
|
284
|
+
key: 'emitValue',
|
|
285
|
+
value: function emitValue(nextState) {
|
|
286
|
+
// 所有变更最终都通过 onSelect 向父页面抛出编码后的最终值。
|
|
287
|
+
// 父页面不需要感知内部 selectedMap / inputValues 的实现细节。
|
|
288
|
+
if (this.props.onSelect) {
|
|
289
|
+
this.props.onSelect(this.buildEmitValue(nextState));
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}, {
|
|
293
|
+
key: 'handleSelectChange',
|
|
294
|
+
value: function handleSelectChange(optionValue, checked) {
|
|
295
|
+
var _this2 = this;
|
|
296
|
+
|
|
297
|
+
if (this.props.readOnly) {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
var selectType = this.state.selectType;
|
|
302
|
+
if (selectType === 'radio') {
|
|
303
|
+
// 单选直接替换当前选中项。
|
|
304
|
+
// radio 模式下 checked 参数不参与判断,因为始终只有一个选中值。
|
|
305
|
+
var _nextState = _extends({}, this.state, {
|
|
306
|
+
selectedRadio: optionValue
|
|
307
|
+
});
|
|
308
|
+
this.setState(_nextState, function () {
|
|
309
|
+
_this2.emitValue(_this2.state);
|
|
310
|
+
});
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// 多选在 selectedMap 上增删当前项。
|
|
315
|
+
// checked=true 表示勾上,checked=false 表示取消。
|
|
316
|
+
var selectedMap = _extends({}, this.state.selectedMap);
|
|
317
|
+
|
|
318
|
+
if (checked) {
|
|
319
|
+
selectedMap[optionValue] = true;
|
|
320
|
+
} else {
|
|
321
|
+
delete selectedMap[optionValue];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
var nextState = _extends({}, this.state, {
|
|
325
|
+
selectedMap: selectedMap
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
this.setState(nextState, function () {
|
|
329
|
+
_this2.emitValue(_this2.state);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}, {
|
|
333
|
+
key: 'handleInputChange',
|
|
334
|
+
value: function handleInputChange(optionValue, value) {
|
|
335
|
+
if (this.props.readOnly) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// 输入框内容单独存储,提交时再与选中值一起编码。
|
|
340
|
+
// 注意:这里不改变选中状态,只更新某一项的附加输入内容。
|
|
341
|
+
// 根据交互要求,输入中只更新本地 state,不立即通知父组件。
|
|
342
|
+
var inputValues = _extends({}, this.state.inputValues);
|
|
343
|
+
inputValues[optionValue] = value;
|
|
344
|
+
|
|
345
|
+
var nextState = _extends({}, this.state, {
|
|
346
|
+
inputValues: inputValues
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
this.setState(nextState);
|
|
350
|
+
}
|
|
351
|
+
}, {
|
|
352
|
+
key: 'handleInputBlur',
|
|
353
|
+
value: function handleInputBlur() {
|
|
354
|
+
if (this.props.readOnly) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// 输入完成(blur)后再统一通知父组件。
|
|
359
|
+
this.emitValue(this.state);
|
|
360
|
+
}
|
|
361
|
+
}, {
|
|
362
|
+
key: 'renderOptions',
|
|
363
|
+
value: function renderOptions() {
|
|
364
|
+
var _this3 = this;
|
|
365
|
+
|
|
366
|
+
var readOnly = this.props.readOnly;
|
|
367
|
+
var selectType = this.state.selectType;
|
|
368
|
+
var options = this.state.options;
|
|
369
|
+
|
|
370
|
+
return options.map(function (option, index) {
|
|
371
|
+
var optionValue = option.value;
|
|
372
|
+
// 单选看 selectedRadio,多选看 selectedMap 是否包含当前 value。
|
|
373
|
+
var checked = selectType === 'radio' ? _this3.state.selectedRadio === optionValue : !!_this3.state.selectedMap[optionValue];
|
|
374
|
+
var showInput = option.isInput;
|
|
375
|
+
var optionClassName = checked ? 'dd-select-input-option checked' : 'dd-select-input-option';
|
|
376
|
+
var inputDisabled = readOnly || !showInput;
|
|
377
|
+
|
|
378
|
+
return _react2.default.createElement(
|
|
379
|
+
'label',
|
|
380
|
+
{ className: optionClassName, key: optionValue || index },
|
|
381
|
+
_react2.default.createElement('input', {
|
|
382
|
+
className: 'dd-select-input-native',
|
|
383
|
+
type: selectType,
|
|
384
|
+
checked: checked,
|
|
385
|
+
disabled: readOnly,
|
|
386
|
+
onChange: function onChange(e) {
|
|
387
|
+
_this3.handleSelectChange(optionValue, e.target.checked);
|
|
388
|
+
}
|
|
389
|
+
}),
|
|
390
|
+
_react2.default.createElement('span', { className: selectType === 'radio' ? 'dd-select-input-icon radio' : 'dd-select-input-icon checkbox' }),
|
|
391
|
+
_react2.default.createElement(
|
|
392
|
+
'span',
|
|
393
|
+
{ className: 'dd-select-input-option-text' },
|
|
394
|
+
option.text
|
|
395
|
+
),
|
|
396
|
+
showInput ? _react2.default.createElement('input', {
|
|
397
|
+
className: 'dd-select-input-text',
|
|
398
|
+
type: 'text',
|
|
399
|
+
value: _this3.state.inputValues[optionValue] || ''
|
|
400
|
+
// 输入框只有在当前项已选中且 readOnly=false 时才允许输入。
|
|
401
|
+
, disabled: inputDisabled,
|
|
402
|
+
onChange: function onChange(e) {
|
|
403
|
+
_this3.handleInputChange(optionValue, e.target.value);
|
|
404
|
+
},
|
|
405
|
+
onBlur: function onBlur() {
|
|
406
|
+
_this3.handleInputBlur();
|
|
407
|
+
}
|
|
408
|
+
}) : null
|
|
409
|
+
);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}, {
|
|
413
|
+
key: 'render',
|
|
414
|
+
value: function render() {
|
|
415
|
+
return _react2.default.createElement(
|
|
416
|
+
_Field2.default,
|
|
417
|
+
{
|
|
418
|
+
required: this.props.required,
|
|
419
|
+
label: this.props.label,
|
|
420
|
+
multiLine: this.props.multiLine
|
|
421
|
+
},
|
|
422
|
+
_react2.default.createElement(
|
|
423
|
+
'div',
|
|
424
|
+
{ className: 'dd-select-input-field' },
|
|
425
|
+
this.renderOptions()
|
|
426
|
+
)
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
}]);
|
|
430
|
+
|
|
431
|
+
return SelectInput;
|
|
432
|
+
}(_react2.default.Component);
|
|
433
|
+
|
|
434
|
+
exports.default = SelectInput;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
.dd-select-input-field {
|
|
2
|
+
width: 100%;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.dd-select-input-option {
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
margin: 8px 0;
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.dd-select-input-native {
|
|
13
|
+
position: absolute;
|
|
14
|
+
opacity: 0;
|
|
15
|
+
pointer-events: none;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.dd-select-input-icon {
|
|
19
|
+
position: relative;
|
|
20
|
+
flex: 0 0 18px;
|
|
21
|
+
width: 18px;
|
|
22
|
+
height: 18px;
|
|
23
|
+
margin-right: 8px;
|
|
24
|
+
border: 1px solid #c7ced9;
|
|
25
|
+
background: #fff;
|
|
26
|
+
transition: all .2s ease;
|
|
27
|
+
box-sizing: border-box;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.dd-select-input-icon.radio {
|
|
31
|
+
border-radius: 50%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.dd-select-input-icon.checkbox {
|
|
35
|
+
border-radius: 4px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.dd-select-input-option.checked .dd-select-input-icon {
|
|
39
|
+
border-color: #3480fb;
|
|
40
|
+
background: #3480fb;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.dd-select-input-option.checked .dd-select-input-icon.radio::after {
|
|
44
|
+
content: '';
|
|
45
|
+
position: absolute;
|
|
46
|
+
top: 50%;
|
|
47
|
+
left: 50%;
|
|
48
|
+
width: 8px;
|
|
49
|
+
height: 8px;
|
|
50
|
+
border-radius: 50%;
|
|
51
|
+
background: #fff;
|
|
52
|
+
transform: translate(-50%, -50%);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.dd-select-input-option.checked .dd-select-input-icon.checkbox::after {
|
|
56
|
+
content: '';
|
|
57
|
+
position: absolute;
|
|
58
|
+
left: 5px;
|
|
59
|
+
top: 1px;
|
|
60
|
+
width: 5px;
|
|
61
|
+
height: 10px;
|
|
62
|
+
border: solid #fff;
|
|
63
|
+
border-width: 0 2px 2px 0;
|
|
64
|
+
transform: rotate(45deg);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.dd-select-input-option-text {
|
|
68
|
+
margin-right: 8px;
|
|
69
|
+
min-width: 32px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.dd-select-input-text {
|
|
73
|
+
flex: 1;
|
|
74
|
+
min-width: 120px;
|
|
75
|
+
border: none;
|
|
76
|
+
border-bottom: 1px solid #ddd;
|
|
77
|
+
outline: none;
|
|
78
|
+
padding: 4px 2px;
|
|
79
|
+
font-size: 14px;
|
|
80
|
+
background-color: transparent;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.dd-select-input-text:disabled {
|
|
84
|
+
color: #333;
|
|
85
|
+
border-bottom-color: #eee;
|
|
86
|
+
cursor: not-allowed;
|
|
87
|
+
}
|