@v2coding/ui 0.1.0

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.
Files changed (49) hide show
  1. package/README.md +6 -0
  2. package/dist/v2coding-ui.esm.js +10840 -0
  3. package/dist/v2coding-ui.min.js +1 -0
  4. package/dist/v2coding-ui.ssr.js +10747 -0
  5. package/package.json +54 -0
  6. package/src/components/dialog/dialog.vue +179 -0
  7. package/src/components/drawer/drawer.vue +523 -0
  8. package/src/components/exports/index.vue +53 -0
  9. package/src/components/exports/remote-exports-dialog.vue +202 -0
  10. package/src/components/field/field.autocomplete.vue +21 -0
  11. package/src/components/field/field.calendar.vue +117 -0
  12. package/src/components/field/field.cascade.vue +233 -0
  13. package/src/components/field/field.checkbox.vue +134 -0
  14. package/src/components/field/field.color.vue +24 -0
  15. package/src/components/field/field.date.vue +145 -0
  16. package/src/components/field/field.icons.vue +123 -0
  17. package/src/components/field/field.number.vue +43 -0
  18. package/src/components/field/field.radio.vue +100 -0
  19. package/src/components/field/field.rate.vue +37 -0
  20. package/src/components/field/field.rich.vue +165 -0
  21. package/src/components/field/field.select.vue +210 -0
  22. package/src/components/field/field.slider.vue +66 -0
  23. package/src/components/field/field.switch.vue +14 -0
  24. package/src/components/field/field.text.vue +66 -0
  25. package/src/components/field/field.timepicker.vue +70 -0
  26. package/src/components/field/field.timeselect.vue +24 -0
  27. package/src/components/field/field.trigger.dialog.vue +50 -0
  28. package/src/components/field/field.trigger.popover.vue +63 -0
  29. package/src/components/field/field.upload.file.vue +241 -0
  30. package/src/components/field/field.upload.image.vue +125 -0
  31. package/src/components/field/field.upload.portrait.vue +304 -0
  32. package/src/components/fill-view/index.vue +43 -0
  33. package/src/components/form/form.dialog.vue +174 -0
  34. package/src/components/form/form.drawer.vue +246 -0
  35. package/src/components/form/form.fieldset.vue +110 -0
  36. package/src/components/form/form.item.vue +213 -0
  37. package/src/components/form/form.vue +293 -0
  38. package/src/components/head-menu/index.vue +188 -0
  39. package/src/components/head-menu/menu-item.vue +84 -0
  40. package/src/components/history/index.vue +360 -0
  41. package/src/components/icon/icon.vue +63 -0
  42. package/src/components/minimize/index.vue +342 -0
  43. package/src/components/page/page.vue +43 -0
  44. package/src/components/provider/provider.vue +15 -0
  45. package/src/components/scroll-view/scroll-view.vue +384 -0
  46. package/src/components/table/column.vue +262 -0
  47. package/src/components/table/table.pagination.vue +71 -0
  48. package/src/components/table/table.select.vue +165 -0
  49. package/src/components/table/table.vue +805 -0
@@ -0,0 +1,210 @@
1
+ <template>
2
+ <div class="ui-field-select">
3
+ <el-select ref="select" v-if="!refresh" v-bind="$attrs" v-on="_listeners" :value="pickerValue" :clearable="clearable" :multiple="multiple" :filterable="filterable" :filter-method="filterMethod" @input="onChange" @blur="onBlur" v-loading="realLoading" element-loading-spinner="el-icon-loading">
4
+ <el-option v-bind="item" v-for="item in displayOptions" :key="item.value">
5
+ <span v-html="item.label"></span>
6
+ </el-option>
7
+ <el-option v-if="isEmpty" value="__error__" disabled class="empty" label="重新加载" @click="init">
8
+ 暂无数据!&emsp;
9
+ <el-button v-show="realError" type="text" @click="init">重新加载</el-button>
10
+ </el-option>
11
+ </el-select>
12
+ <div v-if="refresh" class="el-input-group el-input-group--append">
13
+ <el-select ref="refreshSelect" v-bind="$attrs" v-on="_listeners" :value="pickerValue" :clearable="clearable" :multiple="multiple" :filterable="filterable" :filter-method="filterMethod" @input="onChange" @blur="onBlur" v-loading="realLoading" element-loading-spinner="el-icon-loading">
14
+ <el-option v-bind="item" v-for="item in displayOptions" :key="item.value">
15
+ <span v-html="item.label"></span>
16
+ </el-option>
17
+ <el-option v-if="isEmpty" value="__error__" disabled class="empty" label="重新加载" @click="init">
18
+ 暂无数据!&emsp;
19
+ <el-button v-show="realError" type="text" @click="init">重新加载</el-button>
20
+ </el-option>
21
+ </el-select>
22
+ <div class="el-input-group__append">
23
+ <el-button @click="onRefresh" icon="el-icon-refresh"></el-button>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </template>
28
+
29
+ <script>
30
+ import FieldMixin from './field.mixin';
31
+ import DataMixin from './field.data.mixin';
32
+ import Objects from '../../util/objects';
33
+ // 简体中文 https://github.com/xmflswood/pinyin-match/issues
34
+ import PinyinMatch from 'pinyin-match';
35
+
36
+ export default {
37
+ name: 'ui-field-select',
38
+ mixins: [FieldMixin, DataMixin],
39
+ inheritAttrs: false,
40
+ props: {
41
+ // 是否初始选中
42
+ startNull: {
43
+ type: Boolean,
44
+ default: true,
45
+ },
46
+ clearable: {
47
+ type: Boolean,
48
+ default: true,
49
+ },
50
+ multiple: Boolean,
51
+ refresh: Boolean,
52
+ filterable: {
53
+ type: Boolean,
54
+ default: true,
55
+ },
56
+ },
57
+ data() {
58
+ return {
59
+ query: '',
60
+ };
61
+ },
62
+ computed: {
63
+ isEmpty() {
64
+ return !this.depends && !this.displayOptions.length;
65
+ },
66
+ pickerValue() {
67
+ return this.getPickerValue(this.value);
68
+ },
69
+ displayOptions({realData, query}) {
70
+ if (!query) {
71
+ return realData;
72
+ }
73
+ return realData.filter(option => PinyinMatch.match(option.label, query));
74
+ },
75
+ },
76
+ watch: {
77
+ displayOptions(data, o) {
78
+ if (!Objects.isEquals(data, o)) {
79
+ this.initDefaultValue(data);
80
+ }
81
+ },
82
+ },
83
+ methods: {
84
+ onRefresh() {
85
+ this.$emit('refresh');
86
+ },
87
+ async init() {
88
+ if (this.startNull) {
89
+ this.done();
90
+ }
91
+ await this.getData();
92
+ this.validateValue(String(this.value));
93
+ if (!this.startNull) {
94
+ this.initDefaultValue(this.realData);
95
+ await this.$nextTick();
96
+ this.done();
97
+ }
98
+ },
99
+ initDefaultValue(data) {
100
+ if (this.lockedValue) {
101
+ if (this.value !== this.lockedValue) {
102
+ this.onChange(this.lockedValue, true);
103
+ }
104
+ return;
105
+ }
106
+ const isSelect = data.some(item => this.value === item.value);
107
+ if (isSelect) {
108
+ return;
109
+ }
110
+ if (data.length <= 0 || this.startNull || this.multiple) {
111
+ this.onChange(undefined, true);
112
+ return;
113
+ }
114
+ const first = data.find(Boolean);
115
+ first && first.value !== this.value && this.onChange(first.value, true);
116
+ },
117
+ getPickerValue(value) {
118
+ if (this.multiple) {
119
+ const arr = value ? value.split(',') : [];
120
+ return arr.filter(v => this.validatePickerValue(v));
121
+ }
122
+ const v = String(value);
123
+ return this.validatePickerValue(v) ? v : undefined;
124
+ },
125
+ validateValue(value) {
126
+ if (this.multiple) {
127
+ const arr = value ? value.split(',') : [];
128
+ const validateValue = arr.filter(v => this.validatePickerValue(v)).join(',');
129
+ if (validateValue !== value) {
130
+ this.emitChange(validateValue);
131
+ }
132
+ // } else {
133
+ // const isValid = this.validatePickerValue(value);
134
+ // if (!isValid) {
135
+ // this.emitChange();
136
+ // }
137
+ }
138
+ },
139
+ validatePickerValue(value) {
140
+ return (this.realData || []).some(item => item.value === value);
141
+ },
142
+ getRealValue(value) {
143
+ if (this.multiple) {
144
+ return (value || []).join(',');
145
+ }
146
+ return value || '';
147
+ },
148
+ onChange(val, isInit) {
149
+ if (val === '__error__') {
150
+ return;
151
+ }
152
+ if (this.multiple && Array.isArray(val)) {
153
+ const index = val.indexOf('__error__');
154
+ if (index !== -1) {
155
+ if (val.length === 1 ) {
156
+ return;
157
+ }
158
+ val.splice(index, 1);
159
+ }
160
+ }
161
+ val = this.getRealValue(val);
162
+ if (isInit !== true) {
163
+ this.$emit('update:lockedValue', val);
164
+ }
165
+ this.emitChange(val);
166
+ },
167
+ resetValue() {
168
+ this.onChange(this.multiple ? [] : '');
169
+ },
170
+ focus() {
171
+ const select = this.$refs.select;
172
+ const refreshSelect = this.$refs.refreshSelect;
173
+ if (select) {
174
+ select.focus();
175
+ } else if (refreshSelect) {
176
+ refreshSelect.focus();
177
+ }
178
+ },
179
+ filterMethod(query) {
180
+ this.query = query;
181
+ },
182
+ onBlur() {
183
+ this.query = '';
184
+ },
185
+ },
186
+ };
187
+ </script>
188
+
189
+ <style lang="less">
190
+ .ui-field-select {
191
+ .el-select {
192
+ width: 100%;
193
+ }
194
+
195
+ .el-input-group--append .el-select .el-input.is-focus .el-input__inner {
196
+ border-color: var(--color-primary);
197
+ }
198
+
199
+ .empty {
200
+ font-size: 12px;
201
+ color: #909399;
202
+ display: flex;
203
+ align-items: center;
204
+ }
205
+
206
+ .el-loading-mask .el-loading-spinner {
207
+ margin-top: -14px;
208
+ }
209
+ }
210
+ </style>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <el-slider v-bind="$attrs" v-on="_listeners" v-model="v" :min="min" :max="max" :range="range" @input="onInput"></el-slider>
3
+ </template>
4
+
5
+ <script>
6
+ import debounce from 'lodash.debounce';
7
+ import FieldMixin from './field.mixin';
8
+
9
+ export default {
10
+ name: 'ui-field-slider',
11
+ mixins: [FieldMixin],
12
+ props: {
13
+ range: Boolean,
14
+ min: {
15
+ type: Number,
16
+ default: 0,
17
+ },
18
+ max: {
19
+ type: Number,
20
+ default: 100,
21
+ },
22
+ },
23
+ data() {
24
+ return {
25
+ v: this.getPickerValue(this.value),
26
+ };
27
+ },
28
+ watch: {
29
+ value() {
30
+ this.v = this.getPickerValue(this.value);
31
+ },
32
+ },
33
+ methods: {
34
+ getPickerValue(value) {
35
+ if (this.range) {
36
+ let [start, end] = value ? value.split(',') : [this.min, this.max];
37
+ start = Math.max(Number(start), this.min);
38
+ end = Math.min(Number(end), this.max);
39
+ if (isNaN(start)) {
40
+ start = this.min;
41
+ }
42
+ if (isNaN(end)) {
43
+ end = this.max;
44
+ }
45
+ start = Math.min(start, end);
46
+ end = Math.max(start, end);
47
+ return [start, end];
48
+ }
49
+ const num = Number(value);
50
+ return isNaN(num) ? this.min : num;
51
+ },
52
+ getRealValue(value) {
53
+ if (this.range) {
54
+ return value.join(',');
55
+ }
56
+ return value || '';
57
+ },
58
+ onInput: debounce(function(value) {
59
+ const _value = this.getRealValue(value);
60
+ this.emitChange(_value);
61
+ }, 200, {leading: true}),
62
+ },
63
+ };
64
+ </script>
65
+
66
+ <style scoped></style>
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <el-switch v-bind="$attrs" :value="value" v-on="$listeners"></el-switch>
3
+ </template>
4
+
5
+ <script>
6
+ import FieldMixin from './field.mixin';
7
+
8
+ export default {
9
+ name: 'ui-field-switch',
10
+ mixins: [FieldMixin],
11
+ };
12
+ </script>
13
+
14
+ <style scoped></style>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <el-input v-bind="$attrs" v-on="$listeners" :value="value" :type="type" :maxlength="maxlength" :clearable="clearable" :rows="rows" :autosize="autosize" :show-word-limit="showWordLimit"/>
3
+ </template>
4
+
5
+ <script>
6
+ import FieldMixin from './field.mixin';
7
+
8
+ export default {
9
+ name: 'ui-field-text',
10
+ inheritAttrs: false,
11
+ mixins: [FieldMixin],
12
+ props: {
13
+ type: {
14
+ type: String,
15
+ default: 'text',
16
+ },
17
+ maxlength: {
18
+ type: Number,
19
+ default() {
20
+ if (this.type === 'text') {
21
+ return 40;
22
+ }
23
+ return undefined;
24
+ },
25
+ },
26
+ clearable: {
27
+ type: Boolean,
28
+ default: true,
29
+ },
30
+ rows: {
31
+ type: Number,
32
+ default: 3,
33
+ },
34
+ autosize: {
35
+ type: [Boolean, Object],
36
+ default: () => ({minRows: 3, maxRows: 5}),
37
+ },
38
+ showWordLimit: {
39
+ type: Boolean,
40
+ default: true,
41
+ },
42
+ },
43
+ };
44
+ </script>
45
+
46
+ <style lang="less">
47
+
48
+
49
+ .el-input__suffix-inner {
50
+ display: flex;
51
+ align-items: center;
52
+ height: 100%;
53
+ }
54
+
55
+ .el-input--large .el-input__count .el-input__count-inner {
56
+ line-height: 38px;
57
+ }
58
+
59
+ .el-input--medium .el-input__count .el-input__count-inner {
60
+ line-height: 34px;
61
+ }
62
+
63
+ .el-input--mini .el-input__count .el-input__count-inner {
64
+ line-height: 26px;
65
+ }
66
+ </style>
@@ -0,0 +1,70 @@
1
+ <template>
2
+ <el-time-picker v-bind="$attrs" v-on="_listeners" :value="pickerValue" :is-range="isRange" :value-format="valueFormat" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder" @input="onChange" class="ui-timepicker-field"></el-time-picker>
3
+ </template>
4
+
5
+ <script>
6
+ import FieldMixin from './field.mixin';
7
+
8
+ export default {
9
+ name: 'ui-field-timepicker',
10
+ mixins: [FieldMixin],
11
+ props: {
12
+ isRange: Boolean,
13
+ valueFormat: {
14
+ type: String,
15
+ default: 'HH:mm:ss',
16
+ },
17
+ startPlaceholder: {
18
+ type: String,
19
+ default: '开始时间',
20
+ },
21
+ endPlaceholder: {
22
+ type: String,
23
+ default: '结束时间',
24
+ },
25
+ },
26
+ // data() {
27
+ // return {
28
+ // v: this.getPickerValue(this.value),
29
+ // };
30
+ // },
31
+ computed: {
32
+ pickerValue() {
33
+ return this.getPickerValue(this.value);
34
+ },
35
+ },
36
+ // watch: {
37
+ // value() {
38
+ // this.v = this.getPickerValue(this.value);
39
+ // },
40
+ // },
41
+ methods: {
42
+ getPickerValue(value) {
43
+ if (this.isRange) {
44
+ return value ? value.split(',') : ['', ''];
45
+ }
46
+ return value;
47
+ },
48
+ getRealValue(value) {
49
+ if (this.isRange && Array.isArray(value)) {
50
+ return value.map((item) => item || '').join(',');
51
+ }
52
+ return value || '';
53
+ },
54
+ onChange(value) {
55
+ const _value = this.getRealValue(value);
56
+ this.emitChange(_value);
57
+ },
58
+ focus() {
59
+ const timepicker = this.$children[0];
60
+ timepicker && timepicker.focus();
61
+ },
62
+ },
63
+ };
64
+ </script>
65
+
66
+ <style lang="less" scoped>
67
+ .ui-timepicker-field.el-date-editor {
68
+ width: 100%;
69
+ }
70
+ </style>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <el-time-select v-bind="$attrs" v-on="$listeners" :value="value" class="ui-timeselect-field"></el-time-select>
3
+ </template>
4
+
5
+ <script>
6
+ import FieldMixin from './field.mixin';
7
+
8
+ export default {
9
+ name: 'ui-field-timeselect',
10
+ mixins: [FieldMixin],
11
+ methods: {
12
+ focus() {
13
+ const timeselect = this.$children[0];
14
+ timeselect && timeselect.focus();
15
+ },
16
+ },
17
+ };
18
+ </script>
19
+
20
+ <style lang="less" scoped>
21
+ .ui-timeselect-field.el-date-editor {
22
+ width: 100%;
23
+ }
24
+ </style>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <div class="ui-field-trigger-dialog">
3
+ <el-input :placeholder="placeholder" :value="value" readonly @focus="show">
4
+ <el-button slot="append" :icon="icon" @click="show"></el-button>
5
+ </el-input>
6
+ <ui-dialog :title="placeholder" v-bind="dialog" v-on="$listeners" :visible.sync="visible" :cancel="cancel" :confirm="confirm">
7
+ <slot></slot>
8
+ </ui-dialog>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import FieldMixin from './field.mixin';
14
+
15
+ export default {
16
+ name: 'ui-field-trigger-dialog',
17
+ mixins: [FieldMixin],
18
+ props: {
19
+ placeholder: String,
20
+ cancel: {
21
+ type: Function,
22
+ default: (hide) => hide(),
23
+ },
24
+ confirm: {
25
+ type: Function,
26
+ default: (hide) => hide(),
27
+ },
28
+ icon: {
29
+ type: String,
30
+ default: 'el-icon-search',
31
+ },
32
+ dialog: [Object, String],
33
+ },
34
+ data() {
35
+ return {
36
+ visible: false,
37
+ };
38
+ },
39
+ methods: {
40
+ show() {
41
+ this.visible = true;
42
+ },
43
+ },
44
+ };
45
+ </script>
46
+
47
+ <style lang="less" scoped>
48
+ .ui-field-trigger-dialog {
49
+ }
50
+ </style>
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <el-popover v-bind="popover" v-on="$listeners" v-model="show" ref="popover" :width="popoverWidth" class="ui-field-trigger-popover" trigger="click">
3
+ <slot></slot>
4
+ <el-input slot="reference" :placeholder="placeholder" :value="value" readonly ref="trigger">
5
+ <template slot="prepend">
6
+ <ui-icon :name="prefixIcon"/>
7
+ </template>
8
+ <el-button slot="append" :icon="icon"></el-button>
9
+ </el-input>
10
+ </el-popover>
11
+ </template>
12
+
13
+ <script>
14
+ import debounce from 'lodash.debounce';
15
+ import FieldMixin from './field.mixin';
16
+
17
+ export default {
18
+ name: 'ui-field-trigger-popover',
19
+ mixins: [FieldMixin],
20
+ props: {
21
+ placeholder: String,
22
+ icon: {
23
+ type: String,
24
+ default: 'el-icon-search',
25
+ },
26
+ popover: [Object, String],
27
+ visible: Boolean,
28
+ prefixIcon: String,
29
+ },
30
+ data() {
31
+ return {
32
+ show: this.visible,
33
+ popoverWidth: undefined,
34
+ };
35
+ },
36
+ watch: {
37
+ visible() {
38
+ this.show = this.visible;
39
+ },
40
+ show() {
41
+ this.$emit('update:visible', this.show);
42
+ },
43
+ },
44
+ mounted() {
45
+ this.computedPopoverWidth();
46
+ },
47
+ updated() {
48
+ this.computedPopoverWidth();
49
+ },
50
+ methods: {
51
+ computedPopoverWidth: debounce(function() {
52
+ this.popoverWidth = this.$refs.trigger.$el.offsetWidth;
53
+ this.$refs.popover.popperJS && this.$refs.popover.updatePopper();
54
+ }, 200),
55
+ },
56
+ };
57
+ </script>
58
+
59
+ <style lang="less" scoped>
60
+ .ui-field-trigger-popover {
61
+ width: 100%;
62
+ }
63
+ </style>