@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,213 @@
1
+ <template>
2
+ <el-form-item v-bind="$attrs" :prop="name" :rules="realRules" class="ui-form-item" ref="formItem" :class="{'hidden-item': type === 'hidden'}">
3
+ <div v-if="$scopedSlots.prefix" class="ui-form-item-prefix">
4
+ <slot name="prefix"></slot>
5
+ </div>
6
+ <template slot="label" v-if="showLabel && label">
7
+ {{ label }}
8
+ <el-tooltip effect="dark" :content="info">
9
+ <i v-if="info" class="el-icon-info info"></i>
10
+ </el-tooltip>
11
+ {{realColon ? ':' : ''}}
12
+ </template>
13
+ <form-field v-bind="$attrs" :name="name" v-model="fieldValue" :locked-value.sync="lockedValue" :type="type" :disabled="realDisabled" :placeholder="realPlaceHolder" :ignore="ignore" v-on="listeners">
14
+ <slot></slot>
15
+ </form-field>
16
+ <div v-if="$scopedSlots.suffix" class="ui-form-item-suffix">
17
+ <slot name="suffix"></slot>
18
+ </div>
19
+ </el-form-item>
20
+ </template>
21
+
22
+ <script>
23
+ import VType, { getInputTypeText } from './vtype';
24
+ import FormField from './form.field';
25
+
26
+ export default {
27
+ name: 'ui-form-item',
28
+ inheritAttrs: false,
29
+ inject: ['uiForm'],
30
+ components: { FormField },
31
+ props: {
32
+ value: null,
33
+ defaultValue: {
34
+ default: undefined,
35
+ },
36
+ name: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ prop: String, // ignore prop. 强制要求使用 name 配置
41
+ label: {
42
+ type: String,
43
+ default: '',
44
+ },
45
+ type: {
46
+ type: String,
47
+ default: 'text',
48
+ },
49
+ showLabel: {
50
+ type: Boolean,
51
+ default: true,
52
+ },
53
+ placeholder: String,
54
+ vtype: [String, Array, Function],
55
+ info: String,
56
+ rules: null,
57
+ /**
58
+ * 是否显示 label 后面的冒号
59
+ * 默认显示
60
+ */
61
+ colon: {
62
+ type: Boolean,
63
+ default: undefined,
64
+ },
65
+ disabled: {
66
+ type: Boolean,
67
+ default: undefined,
68
+ },
69
+ ignore: {
70
+ type: Boolean,
71
+ default: false,
72
+ },
73
+ message: String,
74
+ },
75
+ data () {
76
+ return {
77
+ fieldValue: this.defaultValue,
78
+ lockedValue: this.defaultValue,
79
+ };
80
+ },
81
+ computed: {
82
+ realRules () {
83
+ if (this.ignore) {
84
+ return null;
85
+ }
86
+ if (this.rules) {
87
+ return this.rules;
88
+ }
89
+ if (typeof this.vtype === 'function') {
90
+ // this.vtype(rule, value, callback)
91
+ return { validator: this.vtype };
92
+ }
93
+ let vtypes = [];
94
+ if (typeof this.vtype === 'string') {
95
+ vtypes = this.vtype.replace(/\s/g, '').split(',').filter(Boolean);
96
+ } else if (Array.isArray(this.vtype) && this.vtype.length) {
97
+ vtypes = this.vtype.filter(Boolean);
98
+ }
99
+ return vtypes.reduce((rules, vtype) => {
100
+ let rule = vtype;
101
+ if (typeof vtype === 'string') {
102
+ const [type, ...args] = vtype.split(':');
103
+ rule = VType[type](this.$props, ...args);
104
+ }
105
+ rule && rules.push(rule);
106
+ return rules;
107
+ }, []);
108
+ },
109
+ realPlaceHolder () {
110
+ if (this.placeholder) {
111
+ return this.placeholder;
112
+ }
113
+ let input = getInputTypeText(this.type);
114
+ return `请${input}${this.label}`;
115
+ },
116
+ realColon () {
117
+ if (!this.label) {
118
+ return false;
119
+ }
120
+ if (!Object.is(undefined, this.colon)) {
121
+ return this.colon;
122
+ }
123
+ if (!Object.is(undefined, this.uiForm.colon)) {
124
+ return this.uiForm.colon;
125
+ }
126
+ return true;
127
+ },
128
+ realDisabled () {
129
+ if (this.uiForm) {
130
+ return this.uiForm.disabled || this.disabled;
131
+ }
132
+ return this.disabled;
133
+ },
134
+ listeners () {
135
+ // eslint-disable-next-line
136
+ const { change, input, ...listeners } = this.$listeners;
137
+ return listeners;
138
+ },
139
+ },
140
+ watch: {
141
+ value (v) {
142
+ this.fieldValue = v;
143
+ },
144
+ fieldValue (v) {
145
+ this.uiForm.trigger('change', this.name, v, this);
146
+ this.$emit('input', v);
147
+ this.$emit('change', v);
148
+ },
149
+ },
150
+ created () {
151
+ this.registeredField();
152
+ },
153
+ methods: {
154
+ registeredField () {
155
+ if (this.ignore) {
156
+ return;
157
+ }
158
+ this.uiForm.addField(this.name, this.fieldValue, this);
159
+ },
160
+ resetField (...args) {
161
+ if (args.length > 0) {
162
+ this.fieldValue = args[0];
163
+ } else if (this.fieldValue !== this.defaultValue) {
164
+ this.fieldValue = this.defaultValue;
165
+ }
166
+ this.lockedValue = this.fieldValue;
167
+ this.$refs.formItem && this.$refs.formItem.$once('el.form.change', () => {
168
+ this.$refs.formItem && this.$refs.formItem.clearValidate();
169
+ });
170
+ },
171
+ },
172
+ };
173
+ </script>
174
+
175
+ <style lang="less" scoped>
176
+ .ui-form-item {
177
+ ::v-deep .el-form-item__content {
178
+ display: flex;
179
+ flex-direction: row;
180
+ align-items: center;
181
+
182
+ > div {
183
+ flex: 1;
184
+ display: flex;
185
+ align-items: center;
186
+ }
187
+
188
+ .ui-form-item-prefix,
189
+ .ui-form-item-suffix {
190
+ flex: none;
191
+ }
192
+ }
193
+
194
+ .info {
195
+ color: #909399;
196
+ cursor: pointer;
197
+ margin-left: 4px;
198
+ }
199
+
200
+ &.hidden-item {
201
+ display: none;
202
+ }
203
+ }
204
+
205
+ .el-form--inline .ui-form-item ::v-deep .el-form-item__label {
206
+ flex: none;
207
+ white-space: nowrap;
208
+ }
209
+
210
+ .el-form--inline .ui-form-item ::v-deep .el-form-item__content {
211
+ display: inline-flex;
212
+ }
213
+ </style>
@@ -0,0 +1,293 @@
1
+ <template>
2
+ <el-form v-bind="$attrs" ref="form" :model="model" :label-width="labelWidth" v-on="listeners" @submit.native.prevent="onSubmit">
3
+ <component v-for="(field, i) in fields" v-bind="field" v-on="field.listeners" :key="i" :is="field.componentName || 'ui-form-item'"></component>
4
+ <slot></slot>
5
+ </el-form>
6
+ </template>
7
+
8
+ <script>
9
+ import throttle from 'lodash.throttle';
10
+ import Objects from '../../util/objects';
11
+
12
+ export default {
13
+ name: 'ui-form',
14
+ inheritAttrs: false,
15
+ provide() {
16
+ return {
17
+ uiForm: this,
18
+ };
19
+ },
20
+ props: {
21
+ disabled: Boolean,
22
+ labelWidth: {
23
+ type: String,
24
+ default: '105px',
25
+ },
26
+ fields: Array,
27
+ url: String,
28
+ method: {
29
+ type: String,
30
+ validator: (val) => ['get', 'post', 'put'].includes(val),
31
+ default: 'post',
32
+ },
33
+ /**
34
+ * 是否显示 label 后面的冒号
35
+ */
36
+ colon: {
37
+ type: Boolean,
38
+ default: undefined,
39
+ },
40
+ beforeSubmit: {
41
+ type: Function,
42
+ default: () => void 0,
43
+ },
44
+ submitting: {
45
+ type: Boolean,
46
+ default: false,
47
+ },
48
+ /**
49
+ * listeners:
50
+ * ready 所有表单项都准备好后触发
51
+ * submit 触发提交事件
52
+ * after-submit 配置 url 后触发submit事件时触发提交数据完成事件
53
+ * validate 任一表单项被校验后触发
54
+ **/
55
+ },
56
+ data() {
57
+ this.fieldStatus = []; // [{name,status,componentInstance}, ...]
58
+ return {
59
+ fieldList: [],// [[name, value], ...]
60
+ };
61
+ },
62
+ created() {
63
+ },
64
+ computed: {
65
+ model() {
66
+ return Object.fromEntries(this.fieldList);
67
+ },
68
+ listeners() {
69
+ // eslint-disable-next-line
70
+ const {submit, ready, ...listeners} = this.$listeners;
71
+ return listeners;
72
+ },
73
+ },
74
+ mounted() {
75
+ this.$el.addEventListener('reset', this.onReset);
76
+ this.checkFieldsReady();
77
+ },
78
+ beforeDestroy() {
79
+ this.$el.removeEventListener('reset', this.onReset);
80
+ },
81
+ methods: {
82
+ /**
83
+ * @public
84
+ */
85
+ validate(...args) {
86
+ return this.$refs.form.validate(...args);
87
+ },
88
+ /**
89
+ * @public
90
+ */
91
+ validateField(...args) {
92
+ return this.$refs.form.validateField(...args);
93
+ },
94
+ /**
95
+ * @public
96
+ */
97
+ clearValidate(...args) {
98
+ return this.$refs.form.clearValidate(...args);
99
+ },
100
+ /**
101
+ * @public
102
+ */
103
+ resetValues(values) {
104
+ if (!Objects.isObject(values)) {
105
+ values = {};
106
+ }
107
+ this.fieldList.slice().forEach(([name, , field]) => {
108
+ if (Object.prototype.hasOwnProperty.call(values, name)) {
109
+ field.resetField(values[name]);
110
+ } else {
111
+ field.resetField();
112
+ }
113
+ });
114
+ },
115
+ /**
116
+ * @public
117
+ */
118
+ setValues(values) {
119
+ if (!values || !Objects.isObject(values)) {
120
+ return;
121
+ }
122
+ Object.entries(values).forEach(([fieldName, fieldValue]) => {
123
+ const fieldItem = this.fieldList.find(([name]) => name === fieldName);
124
+ if (!fieldItem) {
125
+ return;
126
+ }
127
+ fieldItem[2].fieldValue = fieldValue;
128
+ });
129
+ },
130
+ /**
131
+ * @public
132
+ */
133
+ getValues() {
134
+ return Object.fromEntries(this.fieldList);
135
+ },
136
+ /**
137
+ * @private
138
+ */
139
+ addField(name, defaultValue = '', instance) {
140
+ if (!Object.hasOwnProperty.call(this.model, name)) {
141
+ this.onFieldChange(name, defaultValue, instance);
142
+ }
143
+ },
144
+
145
+ /**
146
+ * (函数节流. 600ms内只执行一次, 防止 form 表单多次提交)
147
+ * @private
148
+ */
149
+ onSubmit: throttle(
150
+ function() {
151
+ let formData = this.getValues();
152
+ const allow = this.beforeSubmit(formData);
153
+ if (typeof allow === 'boolean' && allow === false) {
154
+ return;
155
+ }
156
+ if (typeof allow === 'object') {
157
+ formData = allow;
158
+ }
159
+ this.validate((valid) => {
160
+ if (!valid) {
161
+ return;
162
+ }
163
+ this.$emit('submit', formData);
164
+ this.doAction(formData);
165
+ });
166
+ },
167
+ 600,
168
+ {trailing: false},
169
+ ),
170
+ doAction(data) {
171
+ if (!this.url) {
172
+ return;
173
+ }
174
+ let def;
175
+ this.$emit('update:submitting', true);
176
+ if (this.method === 'get') {
177
+ def = this.getWithMessage(this.url, {params: data});
178
+ } else {
179
+ def = this.postWithMessage(this.url, data);
180
+ }
181
+ def.then((...args) => {
182
+ this.$emit('update:submitting', false);
183
+ this.$emit('after-submit', ...args);
184
+ }).catch((...args) => {
185
+ this.$emit('update:submitting', false);
186
+ return Promise.reject(...args);
187
+ });
188
+ },
189
+ /**
190
+ * @private
191
+ */
192
+ onReset(e) {
193
+ e.preventDefault();
194
+ this.resetValues();
195
+ this.$emit('reset');
196
+ },
197
+ /**
198
+ * @private
199
+ */
200
+ trigger(event, ...args) {
201
+ if (typeof event !== 'string') {
202
+ return;
203
+ }
204
+ const e = event.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
205
+ if (!this[`onField${e}`]) {
206
+ return;
207
+ }
208
+ this[`onField${e}`](...args);
209
+ },
210
+ getAllFields() {
211
+ const getFormFields = (components) => {
212
+ if (!Array.isArray(components) || !components.length) {
213
+ return [];
214
+ }
215
+ return components.reduce((total, component) => {
216
+ // ui-table-select-item mixins ui-form-item
217
+ if (['ui-form-item', 'ui-table-select-item'].includes(component.$options.name)) {
218
+ !component.ignore && component.name && total.push(component.name);
219
+ } else {
220
+ total.push(...getFormFields(component.$children));
221
+ }
222
+ return total;
223
+ }, []);
224
+ };
225
+ this.formFields = getFormFields(this.$children);
226
+ return this.formFields;
227
+ },
228
+ /**
229
+ * @private
230
+ */
231
+ onFieldPending(component) {
232
+ if(component.name) {
233
+ this.fieldStatus.push({name: component.name, status: false, instance: component});
234
+ }
235
+ },
236
+ /**
237
+ * @private
238
+ */
239
+ onFieldDestroy(component) {
240
+ if (component.name) {
241
+ const index = this.fieldStatus.findIndex(item => item.name === component.name);
242
+ index !== -1 && this.fieldStatus.splice(index, 1);
243
+
244
+ const i = this.fieldList.findIndex(item => item[0] === component.name);
245
+ this.fieldList.splice(i, 1);
246
+ }
247
+ const formFields = this.getAllFields();
248
+ if (formFields.length === this.fieldStatus.length) {
249
+ this.checkFieldsReady();
250
+ }
251
+ },
252
+ /**
253
+ * @private
254
+ */
255
+ onFieldDone(component) {
256
+ if (!component.name) {
257
+ return;
258
+ }
259
+ const index = this.fieldStatus.findIndex(item => item.name === component.name);
260
+ if (index === -1) {
261
+ this.fieldStatus.push({name: component.name, status: true, instance: component});
262
+ } else {
263
+ this.fieldStatus.splice(index, 1, {name: component.name, status: true, instance: component});
264
+ }
265
+ const formFields = this.getAllFields();
266
+ if (formFields.length === this.fieldStatus.length) {
267
+ this.checkFieldsReady();
268
+ }
269
+ },
270
+ onFieldChange(fieldName, fieldValue, instance) {
271
+ const index = this.fieldList.findIndex(item => item[0] === fieldName);
272
+ const current = Object.freeze([fieldName, fieldValue, instance]);
273
+ if (index === -1) {
274
+ this.fieldList.push(current);
275
+ } else {
276
+ this.fieldList.splice(index, 1, current);
277
+ }
278
+ },
279
+ checkFieldsReady() {
280
+ const isPending = this.fieldStatus.some(item => !item.status);
281
+ if (!isPending) {
282
+ this.$emit('ready');
283
+ }
284
+ },
285
+ },
286
+ };
287
+ </script>
288
+
289
+ <style scoped>
290
+ .el-form--inline ::v-deep .el-form-item {
291
+ display: inline-flex;
292
+ }
293
+ </style>
@@ -0,0 +1,188 @@
1
+ <template>
2
+ <el-menu
3
+ class="head-menu"
4
+ v-bind="$attrs"
5
+ v-on="$listeners"
6
+ :mode="mode"
7
+ :router="router"
8
+ :default-active="active"
9
+ >
10
+ <menu-item v-for="item in displayMenus" :item="item" :key="item.id"/>
11
+ </el-menu>
12
+ </template>
13
+
14
+ <script>
15
+ import {mapState} from 'vuex';
16
+ import MenuItem from './menu-item';
17
+
18
+ export default {
19
+ name: 'head-menu',
20
+ components: {MenuItem},
21
+ provide() {
22
+ return {
23
+ headMenu: this,
24
+ };
25
+ },
26
+ props: {
27
+ router: {
28
+ type: Boolean,
29
+ default: true,
30
+ },
31
+ defaultActive: String,
32
+ mode: {
33
+ default: 'horizontal',
34
+ },
35
+ },
36
+ data() {
37
+ return {
38
+ packUpWidth: 0,
39
+ };
40
+ },
41
+ computed: {
42
+ ...mapState(['menus']),
43
+ headMenu() {
44
+ // eslint-disable-next-line
45
+ return this.menus.filter(menu => [1, 2].includes(menu.type)).map(({children, ...menu}) => menu);
46
+ },
47
+ active() {
48
+ if (!this.router) {
49
+ return this.defaultActive;
50
+ }
51
+ const currentPath = this.$route.path;
52
+ const isHeadRoute = this.headMenu.some(menu => menu.url === currentPath);
53
+ if (isHeadRoute) {
54
+ return currentPath;
55
+ }
56
+ const currentHeadMenu = this.getCurrentHeadMenu(currentPath, this.menus);
57
+ return currentHeadMenu && (currentHeadMenu.path || currentHeadMenu.url);
58
+ },
59
+ menuWidth() {
60
+ return this.headMenu.reduce((total, item) => {
61
+ return total + (item.name || '').split('').length * 16 + 25 * 2; // 16:字体大小值; 25:左右padding/margin值
62
+ }, 60); // 100:菜单左边的margin值
63
+ },
64
+ packUpIndex() {
65
+ if (this.packUpWidth <= 0) {
66
+ return -1;
67
+ }
68
+ let index = -1;
69
+ let width = this.packUpWidth + 130; // 50:更多下拉菜单所占宽度
70
+ for(let i = this.headMenu.length - 1; i >= 0; i--) {
71
+ const item = this.headMenu[i];
72
+ const currentWidth = (item.name || '').split('').length * 16 + 25 * 2;
73
+ if (currentWidth >= width) {
74
+ index = i - 1;
75
+ break;
76
+ }
77
+ width = width - currentWidth;
78
+ }
79
+ return Math.max(0, index);
80
+ },
81
+ displayMenus() {
82
+ if (this.packUpIndex === -1) {
83
+ return this.headMenu;
84
+ }
85
+ const menus = this.headMenu.slice(0, this.packUpIndex);
86
+ const moreMenus = this.headMenu.slice(this.packUpIndex);
87
+ menus.push({
88
+ id: 'more',
89
+ name: '更多菜单',
90
+ children: moreMenus,
91
+ });
92
+ return menus;
93
+ },
94
+ },
95
+ mounted() {
96
+ window.addEventListener('resize', this.onResize);
97
+ this.onResize();
98
+
99
+ const logo = document.querySelector('.page-header > .logo');
100
+ logo && logo.addEventListener('load', () => this.onResize());
101
+ },
102
+ beforeDestroy() {
103
+ window.removeEventListener('resize', this.onResize);
104
+ },
105
+ methods: {
106
+ onResize() {
107
+ clearTimeout(this.timer);
108
+ this.timer = setTimeout(() => {
109
+ const headerWidth = document.documentElement.clientWidth;
110
+ const logoEl = document.querySelector('.page-header > .logo');
111
+ const titleEl = document.querySelector('.page-header > .title');
112
+ const messageEl = document.querySelector('.page-header > .screen');
113
+ const usernameEl = document.querySelector('.page-header > .username');
114
+ const logoWidth = (logoEl && logoEl.offsetWidth || 0) + 20; // 20 margin
115
+ const titleWidth = titleEl && titleEl.offsetWidth || 0;
116
+ const messageElWidth = messageEl && messageEl.offsetWidth || 0;
117
+ const usernameWidth = usernameEl && usernameEl.offsetWidth || 0;
118
+ const allowedMenuWidth = headerWidth - 60 - logoWidth - titleWidth - messageElWidth - usernameWidth;
119
+ this.packUpWidth = Math.max(0, this.menuWidth - allowedMenuWidth);
120
+ }, 50);
121
+ },
122
+ getCurrentHeadMenu(path, menus) {
123
+ if (!Array.isArray(menus) || menus.length <= 0) {
124
+ return undefined;
125
+ }
126
+ return menus.find(menu => {
127
+ const isMatched = (menu.children || []).some(childMenu => (childMenu.path || childMenu.url) === path);
128
+ if (isMatched) {
129
+ return true;
130
+ }
131
+ return this.getCurrentHeadMenu(path, menu.children);
132
+ });
133
+ },
134
+ },
135
+ };
136
+ </script>
137
+
138
+ <style lang="scss">
139
+
140
+ .head-menu.el-menu {
141
+ background-color: transparent;
142
+ border-bottom: none;
143
+
144
+ > .el-menu-item,
145
+ > .el-submenu .el-submenu__title {
146
+ font-size: 16px;
147
+ font-weight: 400;
148
+ color: inherit;
149
+ height: var(--header-height);
150
+ line-height: var(--header-height);
151
+ padding: 0 25px;
152
+ border: none;
153
+ box-sizing: border-box;
154
+ transition: all 0.2s ease-in-out;
155
+
156
+ span {
157
+ vertical-align: unset;
158
+ }
159
+
160
+ i {
161
+ width: 20px;
162
+ font-size: 14px;
163
+ }
164
+ }
165
+
166
+ > .el-menu-item:not(.is-disabled):not(.is-active):hover,
167
+ > .el-menu-item:not(.is-disabled):not(.is-active):focus,
168
+ > .el-submenu:not(.is-disabled):not(.is-active):hover .el-submenu__title,
169
+ > .el-submenu:not(.is-disabled):not(.is-active):focus .el-submenu__title {
170
+ color: inherit;
171
+ background-color: rgba(0, 146, 63, 0.3);
172
+ }
173
+
174
+ > .el-menu-item.is-active,
175
+ > .el-submenu.is-active .el-submenu__title {
176
+ color: inherit;
177
+ background-color: rgba(0, 146, 63, 0.6);
178
+ }
179
+
180
+ .el-submenu__title i {
181
+ color: inherit;
182
+ }
183
+
184
+ .el-menu--popup {
185
+
186
+ }
187
+ }
188
+ </style>