gyyg-components 0.1.6
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 +24 -0
- package/babel.config.js +12 -0
- package/jsconfig.json +19 -0
- package/lib/demo.html +8 -0
- package/lib/gyyg-components.common.js +2045 -0
- package/lib/gyyg-components.umd.js +2055 -0
- package/lib/gyyg-components.umd.min.js +2055 -0
- package/package.json +50 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +17 -0
- package/src/App.vue +30 -0
- package/src/assets/images/down.png +0 -0
- package/src/components/GyygLayout/GyygLayout.js +5 -0
- package/src/components/GyygLayout/GyygLayout.vue +396 -0
- package/src/components/GyygModal/GyygModal.js +5 -0
- package/src/components/GyygModal/GyygModal.vue +327 -0
- package/src/components/GyygTable/GyygTable.js +5 -0
- package/src/components/GyygTable/GyygTable.vue +78 -0
- package/src/directive/el-drag-dialog/drag.js +64 -0
- package/src/directive/el-drag-dialog/index.js +13 -0
- package/src/directive/feeInput.js +48 -0
- package/src/directive/numberInput.js +32 -0
- package/src/icons/SvgIcon.vue +61 -0
- package/src/icons/index.js +9 -0
- package/src/icons/svg/down.svg +1 -0
- package/src/icons/svg/up.svg +1 -0
- package/src/icons/svgo.yml +22 -0
- package/src/index.js +45 -0
- package/src/main.js +15 -0
- package/src/utils/common.js +25 -0
- package/vue.config.js +24 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/** * 公共模态框组件 author:lijihao Date:2024.11 支持关闭时,el-form表单清空 **/
|
|
2
|
+
<template>
|
|
3
|
+
<div class="gyyg-modal">
|
|
4
|
+
<el-dialog
|
|
5
|
+
:class="dialogClass"
|
|
6
|
+
v-el-drag-dialog
|
|
7
|
+
:type="type"
|
|
8
|
+
:width="width"
|
|
9
|
+
:custom-class="customClass"
|
|
10
|
+
:fullscreen="fullscreen"
|
|
11
|
+
:title="title"
|
|
12
|
+
:close-on-click-modal="closeOnClickModal"
|
|
13
|
+
:append-to-body="appendToBody"
|
|
14
|
+
:visible.sync="visible"
|
|
15
|
+
:before-close="beforeClose"
|
|
16
|
+
:show-close="showClose"
|
|
17
|
+
v-if="visible"
|
|
18
|
+
@closed="closed"
|
|
19
|
+
@close="closeMethod"
|
|
20
|
+
:destroy-on-close="destroyOnClose"
|
|
21
|
+
:modal="modal"
|
|
22
|
+
>
|
|
23
|
+
<div>
|
|
24
|
+
<slot name="body" class="gyyg-modal-body" />
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div v-if="footer" slot="footer" class="dialog-footer">
|
|
28
|
+
<slot name="footer" />
|
|
29
|
+
</div>
|
|
30
|
+
</el-dialog>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
import elDragDialog from '@/directive/el-drag-dialog' // 引入拖拽指令
|
|
36
|
+
export default {
|
|
37
|
+
name: 'GyygModal',
|
|
38
|
+
directives: { elDragDialog },
|
|
39
|
+
props: {
|
|
40
|
+
// 是否嵌套
|
|
41
|
+
appendToBody: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false,
|
|
44
|
+
},
|
|
45
|
+
// 是否可以点击关闭
|
|
46
|
+
closeOnClickModal: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: false,
|
|
49
|
+
},
|
|
50
|
+
// 是否显示底部
|
|
51
|
+
footer: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: true,
|
|
54
|
+
},
|
|
55
|
+
// title
|
|
56
|
+
title: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: '',
|
|
59
|
+
},
|
|
60
|
+
type: {
|
|
61
|
+
type: [String,Number],
|
|
62
|
+
default: "",
|
|
63
|
+
}, // 对话框类型:1.基础表单[gyyg-modal-form] 2.表格[gyyg-modal-table] 3.全屏 [gyyg-modal-fullscreen]
|
|
64
|
+
// 对话框宽度(默认50%)
|
|
65
|
+
width: {
|
|
66
|
+
type: [String,Number],
|
|
67
|
+
default: '',
|
|
68
|
+
},
|
|
69
|
+
//对话框高度(默认90%)
|
|
70
|
+
height: {
|
|
71
|
+
type: [String,Number],
|
|
72
|
+
default: '',
|
|
73
|
+
},
|
|
74
|
+
//关闭后销毁
|
|
75
|
+
destroyOnClose: {
|
|
76
|
+
type: Boolean,
|
|
77
|
+
default: true,
|
|
78
|
+
},
|
|
79
|
+
// 关闭回调函数
|
|
80
|
+
beforeClose: Function,
|
|
81
|
+
//弹框class
|
|
82
|
+
dialogClass: {
|
|
83
|
+
type: String,
|
|
84
|
+
default: '',
|
|
85
|
+
},
|
|
86
|
+
// 是否显示叉号
|
|
87
|
+
showClose: {
|
|
88
|
+
default: true,
|
|
89
|
+
type: Boolean,
|
|
90
|
+
},
|
|
91
|
+
//是否需要遮罩层
|
|
92
|
+
modal: {
|
|
93
|
+
default: true,
|
|
94
|
+
type: Boolean,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
data() {
|
|
98
|
+
return {
|
|
99
|
+
visible: false,
|
|
100
|
+
fullscreen: false,
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
computed: {
|
|
104
|
+
customClass() {
|
|
105
|
+
let className = "";
|
|
106
|
+
switch (this.type) {
|
|
107
|
+
case "form":
|
|
108
|
+
className = "gyyg-modal-form";
|
|
109
|
+
break;
|
|
110
|
+
case "table":
|
|
111
|
+
className = "gyyg-modal-table";
|
|
112
|
+
break;
|
|
113
|
+
case "fullscreen":
|
|
114
|
+
className = "gyyg-modal-fullscreen";
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
return className;
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
created() {
|
|
121
|
+
this.type === "fullscreen" && (this.fullscreen = true);
|
|
122
|
+
},
|
|
123
|
+
methods: {
|
|
124
|
+
//弹框打开
|
|
125
|
+
open() {
|
|
126
|
+
this.visible = true
|
|
127
|
+
if (this.height) {
|
|
128
|
+
this.$nextTick(() => {
|
|
129
|
+
document.getElementsByClassName('gyyg-modal')[0].getElementsByClassName('el-dialog')[0].style.height = this.height
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
close() {
|
|
134
|
+
let db = document.getElementsByClassName('el-dialog__body')
|
|
135
|
+
//表单清空显示
|
|
136
|
+
if (db && db[0] && db[0].getElementsByClassName('el-form') && db[0].getElementsByClassName('el-form').length > 0) {
|
|
137
|
+
let arr = Array.prototype.slice.call(db[0].getElementsByClassName('el-form'))
|
|
138
|
+
arr.forEach(item => {
|
|
139
|
+
if (item.__vue__) {
|
|
140
|
+
let obj = item.__vue__.$options.propsData.model
|
|
141
|
+
for (let key in obj) {
|
|
142
|
+
if (obj.hasOwnProperty(key)) {
|
|
143
|
+
if (obj[key] instanceof Array) {
|
|
144
|
+
obj[key] = []
|
|
145
|
+
} else if (obj[key] instanceof Object) {
|
|
146
|
+
obj[key] = {}
|
|
147
|
+
} else {
|
|
148
|
+
obj[key] = ''
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
//组件清空显示(组件里必须要加class='subcomponents',才能找到,清空)
|
|
156
|
+
if (db && db[0] && db[0].getElementsByClassName('subcomponents') && db[0].getElementsByClassName('subcomponents').length > 0) {
|
|
157
|
+
let arr = Array.prototype.slice.call(db[0].getElementsByClassName('subcomponents'))
|
|
158
|
+
arr.forEach(item => {
|
|
159
|
+
if (item.__vue__) {
|
|
160
|
+
//组件清空数据的方法
|
|
161
|
+
if (item.__vue__.clearHandle) {
|
|
162
|
+
item.__vue__.clearHandle()
|
|
163
|
+
} else if (item.__vue__.clearInput) {
|
|
164
|
+
item.__vue__.clearInput()
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
this.visible = false
|
|
170
|
+
},
|
|
171
|
+
closed() {
|
|
172
|
+
this.close()
|
|
173
|
+
this.$emit('closed')
|
|
174
|
+
},
|
|
175
|
+
//弹框关闭
|
|
176
|
+
closeMethod() {
|
|
177
|
+
this.close()
|
|
178
|
+
this.$emit('close')
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
</script>
|
|
183
|
+
|
|
184
|
+
<style lang="less">
|
|
185
|
+
.el-dialog__wrapper {
|
|
186
|
+
overflow: hidden;
|
|
187
|
+
display: flex;
|
|
188
|
+
justify-content: center;
|
|
189
|
+
align-items: center;
|
|
190
|
+
.el-dialog {
|
|
191
|
+
display: flex;
|
|
192
|
+
flex-direction: column;
|
|
193
|
+
border-radius: 8px;
|
|
194
|
+
margin: 0;
|
|
195
|
+
margin-top: 0 !important;
|
|
196
|
+
max-height: 95%;
|
|
197
|
+
.el-dialog__header {
|
|
198
|
+
text-align: left;
|
|
199
|
+
background-color: #efefef;
|
|
200
|
+
height: 48px;
|
|
201
|
+
line-height: 48px;
|
|
202
|
+
padding: 0 20px;
|
|
203
|
+
color: #fff;
|
|
204
|
+
border-top-left-radius: 8px;
|
|
205
|
+
border-top-right-radius: 8px;
|
|
206
|
+
font-weight: bold;
|
|
207
|
+
|
|
208
|
+
.el-dialog__title {
|
|
209
|
+
font-size: 16px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.el-dialog__headerbtn {
|
|
213
|
+
top: 12px;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.el-dialog__body {
|
|
218
|
+
flex: 1;
|
|
219
|
+
overflow: auto;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.el-dialog__footer {
|
|
223
|
+
padding: 10px;
|
|
224
|
+
border: none;
|
|
225
|
+
background-color: #efefef;
|
|
226
|
+
border-bottom-left-radius: 8px;
|
|
227
|
+
border-bottom-right-radius: 8px;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.gyyg-modal-form {
|
|
232
|
+
height: auto;
|
|
233
|
+
|
|
234
|
+
.el-dialog__body {
|
|
235
|
+
padding: 20px 20px 0 20px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.el-dialog__footer {
|
|
239
|
+
border: none;
|
|
240
|
+
background-color: #efefef;
|
|
241
|
+
border-bottom-left-radius: 8px;
|
|
242
|
+
border-bottom-right-radius: 8px;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.custom-table {
|
|
246
|
+
// 取消表格下边线
|
|
247
|
+
tbody tr:last-child td {
|
|
248
|
+
border-bottom: none !important;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.gyyg-modal-table {
|
|
254
|
+
height: 90vh;
|
|
255
|
+
margin-top: 5vh !important;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.gyyg-modal-fullscreen {
|
|
259
|
+
height: 100vh;
|
|
260
|
+
width: 100vw;
|
|
261
|
+
|
|
262
|
+
.el-dialog__body {
|
|
263
|
+
padding: 10px;
|
|
264
|
+
}
|
|
265
|
+
.el-dialog__footer {
|
|
266
|
+
padding: 10px;
|
|
267
|
+
border: none;
|
|
268
|
+
background-color: #efefef;
|
|
269
|
+
border-bottom-left-radius: 8px;
|
|
270
|
+
border-bottom-right-radius: 8px;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.gyyg-modal {
|
|
276
|
+
text-align: left;
|
|
277
|
+
}
|
|
278
|
+
::v-deep .gyyg-modal .el-dialog__wrapper {
|
|
279
|
+
overflow: hidden;
|
|
280
|
+
display: flex !important;
|
|
281
|
+
justify-content: center;
|
|
282
|
+
align-items: center;
|
|
283
|
+
.el-dialog {
|
|
284
|
+
display: flex;
|
|
285
|
+
flex-direction: column;
|
|
286
|
+
border-radius: 8px;
|
|
287
|
+
margin: 0;
|
|
288
|
+
margin-top: 0 !important;
|
|
289
|
+
.el-dialog__header {
|
|
290
|
+
text-align: left;
|
|
291
|
+
background-color: #efefef;
|
|
292
|
+
height: 48px;
|
|
293
|
+
line-height: 48px;
|
|
294
|
+
padding: 0 20px;
|
|
295
|
+
color: #fff;
|
|
296
|
+
border-top-left-radius: 8px;
|
|
297
|
+
border-top-right-radius: 8px;
|
|
298
|
+
font-weight: bold;
|
|
299
|
+
|
|
300
|
+
.el-dialog__title {
|
|
301
|
+
font-size: 16px;
|
|
302
|
+
// font-weight: bold;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.el-dialog__headerbtn {
|
|
306
|
+
top: 12px;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.el-dialog__body {
|
|
311
|
+
flex: 1;
|
|
312
|
+
overflow: auto;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.el-dialog__footer {
|
|
316
|
+
flex-shrink: 0;
|
|
317
|
+
box-sizing: content-box;
|
|
318
|
+
height: 32px;
|
|
319
|
+
padding: 10px;
|
|
320
|
+
border: none;
|
|
321
|
+
background-color: #efefef;
|
|
322
|
+
border-bottom-left-radius: 8px;
|
|
323
|
+
border-bottom-right-radius: 8px;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
</style>
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/** el-table组件 */
|
|
2
|
+
<template>
|
|
3
|
+
<el-table class='simpleTableClass' ref="simpleTableRef" :data="data" :row-key="rowKey" :row-style="selectedRowStyle" highlight-current-row element-loading-text="加载中" @selection-change="handleSelectionChange" :height='height' @row-click="clickOne" border style="width: 100%">
|
|
4
|
+
<slot name="content" />
|
|
5
|
+
</el-table>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
export default {
|
|
10
|
+
name:'GyygTable',
|
|
11
|
+
data() {
|
|
12
|
+
return {
|
|
13
|
+
simpleMultipleSelection:this.multipleSelection
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
props: {
|
|
17
|
+
//列表数据
|
|
18
|
+
data: {
|
|
19
|
+
type: Array,
|
|
20
|
+
default: () =>{
|
|
21
|
+
return []
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
//行的唯一标识
|
|
25
|
+
rowKey: {
|
|
26
|
+
type: [String,Number],
|
|
27
|
+
default: 'id',
|
|
28
|
+
},
|
|
29
|
+
//选择的行
|
|
30
|
+
multipleSelection: {
|
|
31
|
+
type: Array,
|
|
32
|
+
default: () =>{
|
|
33
|
+
return []
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
// 高度
|
|
37
|
+
height: {
|
|
38
|
+
type: [String,Number],
|
|
39
|
+
default: '100%',
|
|
40
|
+
},
|
|
41
|
+
// 点击单行,是否只选中当前行
|
|
42
|
+
toggleRow: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: true,
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
methods: {
|
|
48
|
+
// 列表选中加粗
|
|
49
|
+
selectedRowStyle({ row }) {
|
|
50
|
+
const idArr = this.simpleMultipleSelection.map(row => row[this.rowKey])
|
|
51
|
+
if (idArr.includes(row[this.rowKey])) {
|
|
52
|
+
return { 'font-weight': '700' }
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
// 列表选中的当前行
|
|
56
|
+
handleSelectionChange(row) {
|
|
57
|
+
this.simpleMultipleSelection = row
|
|
58
|
+
this.$emit('update:multipleSelection',this.simpleMultipleSelection)
|
|
59
|
+
},
|
|
60
|
+
// 选中单条数据
|
|
61
|
+
clickOne(row) {
|
|
62
|
+
if(this.toggleRow){
|
|
63
|
+
this.$refs.simpleTableRef.clearSelection()
|
|
64
|
+
this.$refs.simpleTableRef.toggleRowSelection(row)
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<style>
|
|
72
|
+
.simpleTableClass thead tr th {
|
|
73
|
+
background-color:#F5F7FA !important;
|
|
74
|
+
}
|
|
75
|
+
.simpleTableClass td.el-table__cell{
|
|
76
|
+
border-right:none;
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
bind(el, binding, vnode) {
|
|
3
|
+
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
|
4
|
+
const dragDom = el.querySelector('.el-dialog')
|
|
5
|
+
dialogHeaderEl.style.cssText += ';cursor:move;'
|
|
6
|
+
|
|
7
|
+
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
|
8
|
+
const getStyle = (function() {
|
|
9
|
+
if (window.document.currentStyle) {
|
|
10
|
+
return (dom, attr) => dom.currentStyle[attr]
|
|
11
|
+
} else {
|
|
12
|
+
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
|
13
|
+
}
|
|
14
|
+
})()
|
|
15
|
+
|
|
16
|
+
dialogHeaderEl.onmousedown = (e) => {
|
|
17
|
+
// 鼠标按下,计算当前元素距离可视区的距离
|
|
18
|
+
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
|
19
|
+
const disY = e.clientY - dialogHeaderEl.offsetTop
|
|
20
|
+
|
|
21
|
+
// 获取到的值带px 正则匹配替换
|
|
22
|
+
let styL = getStyle(dragDom, 'left')
|
|
23
|
+
let styT = getStyle(dragDom, 'top')
|
|
24
|
+
|
|
25
|
+
if (styL.includes('%')) {
|
|
26
|
+
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
|
27
|
+
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
|
28
|
+
} else {
|
|
29
|
+
styL = +styL.replace(/\px/g, '')
|
|
30
|
+
styT = +styT.replace(/\px/g, '')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
document.onmousemove = function(e) {
|
|
34
|
+
// 通过事件委托,计算移动的距离
|
|
35
|
+
let left = e.clientX - disX
|
|
36
|
+
let top = e.clientY - disY
|
|
37
|
+
|
|
38
|
+
// 边界处理
|
|
39
|
+
// if (-(left) > minDragDomLeft) {
|
|
40
|
+
// left = -minDragDomLeft
|
|
41
|
+
// } else if (left > maxDragDomLeft) {
|
|
42
|
+
// left = maxDragDomLeft
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
// if (-(top) > minDragDomTop) {
|
|
46
|
+
// top = -minDragDomTop
|
|
47
|
+
// } else if (top > maxDragDomTop) {
|
|
48
|
+
// top = maxDragDomTop
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
// 移动当前元素
|
|
52
|
+
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
|
53
|
+
|
|
54
|
+
// emit onDrag event
|
|
55
|
+
vnode.child.$emit('dragDialog')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
document.onmouseup = function(e) {
|
|
59
|
+
document.onmousemove = null
|
|
60
|
+
document.onmouseup = null
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import drag from "./drag";
|
|
2
|
+
|
|
3
|
+
const install = function (Vue) {
|
|
4
|
+
Vue.directive("el-drag-dialog", drag);
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
if (window.Vue) {
|
|
8
|
+
window["el-drag-dialog"] = drag;
|
|
9
|
+
Vue.use(install); // eslint-disable-line
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
drag.install = install;
|
|
13
|
+
export default drag;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// input金额指令(数字,且保留两位小数,blur自动增加.00)
|
|
2
|
+
import Vue from 'vue'
|
|
3
|
+
|
|
4
|
+
Vue.directive('feeInput', {
|
|
5
|
+
bind(el, binding, vnode) {
|
|
6
|
+
const input = el.getElementsByTagName('input')[0]
|
|
7
|
+
input.addEventListener('compositionstart', () => {
|
|
8
|
+
vnode.inputLocking = true
|
|
9
|
+
})
|
|
10
|
+
input.addEventListener('compositionend', () => {
|
|
11
|
+
vnode.inputLocking = false
|
|
12
|
+
input.dispatchEvent(new Event('input'))
|
|
13
|
+
})
|
|
14
|
+
input.addEventListener('input', () => {
|
|
15
|
+
if (vnode.inputLocking) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
const oldValue = input.value
|
|
19
|
+
let newValue = input.value
|
|
20
|
+
newValue = newValue.replace(/[^\d.]/g, '')
|
|
21
|
+
newValue = newValue.replace(/^\./g, '')
|
|
22
|
+
newValue = newValue.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
|
|
23
|
+
newValue = newValue.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
|
|
24
|
+
if (newValue) {
|
|
25
|
+
const arr = newValue.split('.')
|
|
26
|
+
newValue = Number(arr[0]) + (arr[1] === undefined ? '' : '.' + arr[1]) // 去掉开头多余的0
|
|
27
|
+
}
|
|
28
|
+
// 判断是否需要更新,避免进入死循环
|
|
29
|
+
if (newValue !== oldValue) {
|
|
30
|
+
input.value = newValue
|
|
31
|
+
input.dispatchEvent(new Event('input')) // 通知v-model更新
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
// input 事件无法处理小数点后面全是零的情况 因为无法确定用户输入的0是否真的应该清除,如3.02。放在blur中去处理
|
|
35
|
+
input.addEventListener('blur', () => {
|
|
36
|
+
const oldValue = input.value
|
|
37
|
+
let newValue = input.value
|
|
38
|
+
if (newValue) {
|
|
39
|
+
newValue = Number(newValue).toFixed(2)
|
|
40
|
+
}
|
|
41
|
+
// 判断是否需要更新,避免进入死循环
|
|
42
|
+
if (newValue !== oldValue) {
|
|
43
|
+
input.value = newValue
|
|
44
|
+
input.dispatchEvent(new Event('input')) // 通知v-model更新
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// 数量指令(数字)
|
|
2
|
+
import Vue from 'vue'
|
|
3
|
+
|
|
4
|
+
Vue.directive('numberInput', {
|
|
5
|
+
bind(el, binding, vnode) {
|
|
6
|
+
const input = el.getElementsByTagName('input')[0]
|
|
7
|
+
input.addEventListener('compositionstart', () => {
|
|
8
|
+
vnode.inputLocking = true
|
|
9
|
+
})
|
|
10
|
+
input.addEventListener('compositionend', () => {
|
|
11
|
+
vnode.inputLocking = false
|
|
12
|
+
input.dispatchEvent(new Event('input'))
|
|
13
|
+
})
|
|
14
|
+
input.addEventListener('input', () => {
|
|
15
|
+
if (vnode.inputLocking) {
|
|
16
|
+
return
|
|
17
|
+
}
|
|
18
|
+
const oldValue = input.value
|
|
19
|
+
let newValue = input.value
|
|
20
|
+
newValue = newValue.replace(/[^\d]/g,'').replace(/^00*(\d)([0-9]*)/g,'$1$2')
|
|
21
|
+
if (newValue) {
|
|
22
|
+
const arr = newValue.split('.')
|
|
23
|
+
newValue = Number(arr[0]) + (arr[1] === undefined ? '' : '.' + arr[1]) // 去掉开头多余的0
|
|
24
|
+
}
|
|
25
|
+
// 判断是否需要更新,避免进入死循环
|
|
26
|
+
if (newValue !== oldValue) {
|
|
27
|
+
input.value = newValue
|
|
28
|
+
input.dispatchEvent(new Event('input')) // 通知v-model更新
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
})
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
|
|
3
|
+
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
|
|
4
|
+
<use :xlink:href="iconName" />
|
|
5
|
+
</svg>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script>
|
|
9
|
+
import { isExternal } from '@/utils/common.js'
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
name: 'SvgIcon',
|
|
13
|
+
props: {
|
|
14
|
+
iconClass: {
|
|
15
|
+
type: String,
|
|
16
|
+
required: true
|
|
17
|
+
},
|
|
18
|
+
className: {
|
|
19
|
+
type: String,
|
|
20
|
+
default: ''
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
computed: {
|
|
24
|
+
isExternal() {
|
|
25
|
+
return isExternal(this.iconClass)
|
|
26
|
+
},
|
|
27
|
+
iconName() {
|
|
28
|
+
return `#icon-${this.iconClass}`
|
|
29
|
+
},
|
|
30
|
+
svgClass() {
|
|
31
|
+
if (this.className) {
|
|
32
|
+
return 'svg-icon ' + this.className
|
|
33
|
+
} else {
|
|
34
|
+
return 'svg-icon'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
styleExternalIcon() {
|
|
38
|
+
return {
|
|
39
|
+
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
|
|
40
|
+
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style scoped>
|
|
48
|
+
.svg-icon {
|
|
49
|
+
width: 1em;
|
|
50
|
+
height: 1em;
|
|
51
|
+
vertical-align: -0.15em;
|
|
52
|
+
fill: currentColor;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.svg-external-icon {
|
|
57
|
+
background-color: currentColor;
|
|
58
|
+
mask-size: cover!important;
|
|
59
|
+
display: inline-block;
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import SvgIcon from './SvgIcon.vue'// svg component
|
|
3
|
+
|
|
4
|
+
// register globally
|
|
5
|
+
Vue.component('svg-icon', SvgIcon)
|
|
6
|
+
|
|
7
|
+
const req = require.context('./svg', false, /\.svg$/)
|
|
8
|
+
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
|
9
|
+
requireAll(req)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1678944914954" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3728" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M726.62 470.62L545.94 651.31c-18.72 18.72-49.16 18.72-67.88 0L297.38 470.62c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L512 594.75l169.38-169.38c12.5-12.5 32.75-12.5 45.25 0 6.25 6.25 9.38 14.44 9.38 22.62s-3.13 16.39-9.39 22.63zM523.31 606.38v-0.31 0.31z" fill="#409EFF" p-id="3729"></path><path d="M128 512c0-211.74 172.26-384 384-384s384 172.26 384 384-172.26 384-384 384-384-172.26-384-384m-64 0c0 247.42 200.58 448 448 448s448-200.58 448-448S759.42 64 512 64 64 264.58 64 512z" fill="#409EFF" p-id="3730"></path></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1678945148529" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4763" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M297.38 553.38l180.69-180.69c18.72-18.72 49.16-18.72 67.88 0l180.69 180.69c12.5 12.5 12.5 32.75 0 45.25s-32.75 12.5-45.25 0L512 429.25 342.62 598.62c-12.5 12.5-32.75 12.5-45.25 0-6.25-6.25-9.38-14.44-9.38-22.62s3.13-16.38 9.39-22.62z m203.31-135.76v0.31-0.31z" fill="#409EFF" p-id="4764"></path><path d="M896 512c0 211.74-172.26 384-384 384S128 723.74 128 512s172.26-384 384-384 384 172.26 384 384m64 0c0-247.42-200.58-448-448-448S64 264.58 64 512s200.58 448 448 448 448-200.58 448-448z" fill="#409EFF" p-id="4765"></path></svg>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# replace default config
|
|
2
|
+
|
|
3
|
+
# multipass: true
|
|
4
|
+
# full: true
|
|
5
|
+
|
|
6
|
+
plugins:
|
|
7
|
+
|
|
8
|
+
# - name
|
|
9
|
+
#
|
|
10
|
+
# or:
|
|
11
|
+
# - name: false
|
|
12
|
+
# - name: true
|
|
13
|
+
#
|
|
14
|
+
# or:
|
|
15
|
+
# - name:
|
|
16
|
+
# param1: 1
|
|
17
|
+
# param2: 2
|
|
18
|
+
|
|
19
|
+
- removeAttrs:
|
|
20
|
+
attrs:
|
|
21
|
+
- 'fill'
|
|
22
|
+
- 'fill-rule'
|