sh-view 2.9.18 → 2.9.20
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/package.json +1 -1
- package/packages/components/index.js +2 -0
- package/packages/components/sh-card/index.vue +17 -6
- package/packages/components/sh-date/index.vue +11 -5
- package/packages/components/sh-form/form.vue +2 -2
- package/packages/components/sh-form/query.vue +3 -3
- package/packages/components/sh-header/index.vue +6 -3
- package/packages/components/sh-modal/index.vue +2 -2
- package/packages/components/sh-signature/index.vue +168 -0
- package/packages/components/sh-table/css/index.scss +9 -0
- package/packages/components/sh-table/grid.vue +3 -3
- package/packages/components/sh-table/js/props.js +19 -1
- package/packages/components/sh-table/js/useTable.js +35 -4
- package/packages/components/sh-table/table.vue +6 -3
- package/packages/components/sh-tabs/index.vue +4 -3
- package/packages/components/sh-tag/index.vue +5 -3
- package/packages/components/sh-toolbar/index.vue +13 -7
- package/packages/components/sh-tree/components/table-tree.vue +1 -0
- package/packages/css/animated.scss +0 -29
- package/packages/utils/resize.js +2 -2
- package/packages/vxeTable/css/index.scss +7 -3
- package/packages/vxeTable/index.js +16 -1
- package/packages/vxeTable/render/filters/vxe-filter-complex.vue +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sh-view",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.20",
|
|
4
4
|
"description": "基于vxe-table二次封装,更包含Alert,Badge,Card,CodeEditor,Col,Corner,CountTo,Drawer,Empty,Form,Header,Icon,List,Loading,Modal,Noticebar,Poptip,Progress,PullRefresh,Query,Result,Row,Split,Grid,Table,Tabs,Tag,Toolbar,Tree,Upload,WaterFall,WaterMark等丰富组件库",
|
|
5
5
|
"main": "packages/index.js",
|
|
6
6
|
"typings": "types/index.d.ts",
|
|
@@ -23,6 +23,7 @@ import ShPullRefresh from './sh-pull-refresh/index.vue'
|
|
|
23
23
|
import ShQuery from './sh-form/query.vue'
|
|
24
24
|
import ShResult from './sh-result/index.vue'
|
|
25
25
|
import ShRow from './sh-row/index.vue'
|
|
26
|
+
import ShSignature from './sh-signature/index.vue'
|
|
26
27
|
import ShSplit from './sh-split/index.vue'
|
|
27
28
|
import ShGrid from './sh-table/grid.vue'
|
|
28
29
|
import ShTable from './sh-table/table.vue'
|
|
@@ -59,6 +60,7 @@ const components = {
|
|
|
59
60
|
ShQuery,
|
|
60
61
|
ShResult,
|
|
61
62
|
ShRow,
|
|
63
|
+
ShSignature,
|
|
62
64
|
ShSplit,
|
|
63
65
|
ShGrid,
|
|
64
66
|
ShTable,
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</template>
|
|
20
20
|
|
|
21
21
|
<script>
|
|
22
|
-
import { defineComponent, computed } from 'vue'
|
|
22
|
+
import { defineComponent, computed, getCurrentInstance } from 'vue'
|
|
23
23
|
export default defineComponent({
|
|
24
24
|
name: 'ShCard',
|
|
25
25
|
props: {
|
|
@@ -32,8 +32,7 @@ export default defineComponent({
|
|
|
32
32
|
default: false
|
|
33
33
|
},
|
|
34
34
|
padding: {
|
|
35
|
-
type: Number
|
|
36
|
-
default: 10
|
|
35
|
+
type: Number
|
|
37
36
|
},
|
|
38
37
|
title: {
|
|
39
38
|
type: String
|
|
@@ -51,22 +50,33 @@ export default defineComponent({
|
|
|
51
50
|
},
|
|
52
51
|
size: {
|
|
53
52
|
type: String,
|
|
54
|
-
default: '
|
|
53
|
+
default: '' // large / medium / small / mini
|
|
55
54
|
}
|
|
56
55
|
},
|
|
57
56
|
setup(props, context) {
|
|
57
|
+
const { proxy } = getCurrentInstance()
|
|
58
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
58
59
|
const { slots } = context
|
|
59
60
|
|
|
61
|
+
const vmSize = computed(() => props.size || $vUiSetup.size)
|
|
60
62
|
const classes = computed(() => {
|
|
61
63
|
return {
|
|
62
64
|
border: props.border,
|
|
63
65
|
shadow: props.shadow,
|
|
64
|
-
[
|
|
66
|
+
[vmSize.value]: vmSize.value
|
|
65
67
|
}
|
|
66
68
|
})
|
|
67
69
|
const styles = computed(() => {
|
|
70
|
+
let paddingValue = 10
|
|
71
|
+
if (props.padding) {
|
|
72
|
+
paddingValue = props.padding
|
|
73
|
+
} else if (vmSize.value === 'small') {
|
|
74
|
+
paddingValue = 7
|
|
75
|
+
} else if (vmSize.value === 'mini') {
|
|
76
|
+
paddingValue = 5
|
|
77
|
+
}
|
|
68
78
|
return {
|
|
69
|
-
padding: `${
|
|
79
|
+
padding: `${paddingValue}px`
|
|
70
80
|
}
|
|
71
81
|
})
|
|
72
82
|
|
|
@@ -115,6 +125,7 @@ export default defineComponent({
|
|
|
115
125
|
}
|
|
116
126
|
.sh-card-body {
|
|
117
127
|
display: block;
|
|
128
|
+
overflow: auto;
|
|
118
129
|
border-top: 1px solid var(--border-color);
|
|
119
130
|
}
|
|
120
131
|
.sh-card-foot {
|
|
@@ -104,31 +104,37 @@ export default defineComponent({
|
|
|
104
104
|
],
|
|
105
105
|
setup(props, context) {
|
|
106
106
|
const { proxy } = getCurrentInstance()
|
|
107
|
-
const { $vUtils } = proxy
|
|
107
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
108
108
|
const { emit, slots } = context
|
|
109
109
|
|
|
110
110
|
const pulldownValue = ref(false)
|
|
111
111
|
const inputValue = ref(props.modelValue)
|
|
112
112
|
const rangeValue = ref(Array.isArray(props.modelValue) ? props.modelValue : [])
|
|
113
113
|
|
|
114
|
-
const vmConfig = computed(() => ({ size: props.size }))
|
|
114
|
+
const vmConfig = computed(() => ({ size: props.size || $vUiSetup.size }))
|
|
115
115
|
const inputConfig = computed(() => {
|
|
116
116
|
let defaultProps = {}
|
|
117
117
|
let vxeProps = $vUtils.omit(props, (val, key) => {
|
|
118
118
|
return omitProps.includes(key) || $vUtils.isNone(val)
|
|
119
119
|
})
|
|
120
120
|
let shProps = {}
|
|
121
|
-
return Object.assign(defaultProps, vxeProps, shProps, vmConfig)
|
|
121
|
+
return Object.assign(defaultProps, vxeProps, shProps, vmConfig.value)
|
|
122
122
|
})
|
|
123
123
|
const pulldownConfig = computed(() => {
|
|
124
|
-
return Object.assign({ transfer: true }, props.pulldown, vmConfig)
|
|
124
|
+
return Object.assign({ transfer: true }, props.pulldown, vmConfig.value)
|
|
125
125
|
})
|
|
126
126
|
const calendarFormat = computed(() => {
|
|
127
127
|
if (props.type === 'month') return 'yyyy-MM'
|
|
128
128
|
else if (props.type === 'year') return 'yyyy'
|
|
129
129
|
return props.format || 'yyyy-MM-dd'
|
|
130
130
|
})
|
|
131
|
-
const rangeInputConfig = computed(() =>
|
|
131
|
+
const rangeInputConfig = computed(() => {
|
|
132
|
+
let returnConfig = { type: 'text', readonly: true }
|
|
133
|
+
if (vmConfig.value.size) {
|
|
134
|
+
returnConfig.class = [`size--${vmConfig.value.size}`]
|
|
135
|
+
}
|
|
136
|
+
return returnConfig
|
|
137
|
+
})
|
|
132
138
|
const startInputConfig = computed(() => {
|
|
133
139
|
let startValue = rangeValue.value[0] || ''
|
|
134
140
|
let startLabel = $vUtils.toDateString(startValue, calendarFormat.value)
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
</div>
|
|
18
18
|
<div class="sh-common-footer-right">
|
|
19
19
|
<slot name="formRight"></slot>
|
|
20
|
-
<vxe-button
|
|
20
|
+
<vxe-button type="submit" status="primary" :size="size" :disabled="disabled || loading">
|
|
21
21
|
{{ globalConfig?.submitBtnText || '确认' }}
|
|
22
22
|
</vxe-button>
|
|
23
|
-
<vxe-button
|
|
23
|
+
<vxe-button type="reset" :size="size">{{ globalConfig?.resetBtnText || '重置' }}</vxe-button>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
<template v-for="slot in Object.keys(slots)" #[slot]="scope">
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
<div class="sh-query-buttons-left"><slot name="footLeft"></slot></div>
|
|
17
17
|
<div class="sh-query-buttons-right">
|
|
18
18
|
<slot name="footRight"></slot>
|
|
19
|
-
<vxe-button
|
|
20
|
-
<vxe-button
|
|
21
|
-
<vxe-button v-if="formToggleBtnShow"
|
|
19
|
+
<vxe-button type="submit" status="primary" :size="size" icon="vxe-icon-search">{{ globalConfig?.submitBtnText || '查询' }}</vxe-button>
|
|
20
|
+
<vxe-button type="reset" :size="size" icon="vxe-icon-repeat">{{ globalConfig?.resetBtnText || '重置' }}</vxe-button>
|
|
21
|
+
<vxe-button v-if="formToggleBtnShow" :size="size" :icon="formCollapsed ? 'vxe-icon-caret-up' : 'vxe-icon-caret-down'" @click="formBtnCollapsed(!formCollapsed, true)">
|
|
22
22
|
{{ formCollapsed ? '收起' : '展开全部' }}
|
|
23
23
|
</vxe-button>
|
|
24
24
|
</div>
|
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
</template>
|
|
25
25
|
|
|
26
26
|
<script>
|
|
27
|
-
import { defineComponent, computed } from 'vue'
|
|
27
|
+
import { defineComponent, computed, getCurrentInstance } from 'vue'
|
|
28
28
|
export default defineComponent({
|
|
29
29
|
name: 'ShHeader',
|
|
30
30
|
props: {
|
|
31
31
|
size: {
|
|
32
32
|
type: String,
|
|
33
|
-
default: '
|
|
33
|
+
default: ''
|
|
34
34
|
},
|
|
35
35
|
color: {
|
|
36
36
|
type: String,
|
|
@@ -83,6 +83,8 @@ export default defineComponent({
|
|
|
83
83
|
},
|
|
84
84
|
emits: ['back'],
|
|
85
85
|
setup(props, context) {
|
|
86
|
+
const { proxy } = getCurrentInstance()
|
|
87
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
86
88
|
const { emit, slots } = context
|
|
87
89
|
|
|
88
90
|
let sizeMap = {
|
|
@@ -93,6 +95,7 @@ export default defineComponent({
|
|
|
93
95
|
mini: '12px'
|
|
94
96
|
}
|
|
95
97
|
|
|
98
|
+
const vmSize = computed(() => props.size || $vUiSetup.size)
|
|
96
99
|
const styles = computed(() => {
|
|
97
100
|
return {
|
|
98
101
|
backgroundColor: props.color
|
|
@@ -106,7 +109,7 @@ export default defineComponent({
|
|
|
106
109
|
[`sh-pageheader-theme-${props.theme}`]: props.theme,
|
|
107
110
|
'has-footer': slots.footer,
|
|
108
111
|
[`sh-pageheader-type-${props.type}`]: props.type,
|
|
109
|
-
[`${
|
|
112
|
+
[`${vmSize.value}`]: vmSize.value
|
|
110
113
|
}
|
|
111
114
|
})
|
|
112
115
|
const titleStyle = computed(() => {
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
<div class="sh-modal-footer-left"><slot name="footerLeft"></slot></div>
|
|
10
10
|
<div class="sh-modal-footer-right">
|
|
11
11
|
<slot name="footerRightLeft"></slot>
|
|
12
|
-
<vxe-button
|
|
13
|
-
<vxe-button v-if="!readonly"
|
|
12
|
+
<vxe-button :content="cancelButtonText" @click="onModalClose"></vxe-button>
|
|
13
|
+
<vxe-button v-if="!readonly" status="primary" :content="confirmButtonText" @click="onModalConfirm"></vxe-button>
|
|
14
14
|
<slot name="footerRight"></slot>
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="wrapRef" class="sh-signature" :class="wrapClass" :style="wrapStyle">
|
|
3
|
+
<canvas ref="canvasRef" v-bind="canvasConfig"></canvas>
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
import { ref, reactive, defineComponent, computed, getCurrentInstance, onMounted } from 'vue'
|
|
9
|
+
export default defineComponent({
|
|
10
|
+
name: 'ShSignature',
|
|
11
|
+
props: {
|
|
12
|
+
border: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: true
|
|
15
|
+
},
|
|
16
|
+
width: {
|
|
17
|
+
type: String,
|
|
18
|
+
default: ''
|
|
19
|
+
},
|
|
20
|
+
height: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: '200px'
|
|
23
|
+
},
|
|
24
|
+
line: {
|
|
25
|
+
type: Number,
|
|
26
|
+
default: 3
|
|
27
|
+
},
|
|
28
|
+
color: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: '#000'
|
|
31
|
+
},
|
|
32
|
+
type: {
|
|
33
|
+
type: String,
|
|
34
|
+
default: 'png'
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
emits: ['start', 'signing', 'end', 'confirm', 'clear'],
|
|
38
|
+
setup(props, context) {
|
|
39
|
+
const { proxy } = getCurrentInstance()
|
|
40
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
41
|
+
const { slots, emit } = context
|
|
42
|
+
|
|
43
|
+
const wrapRef = ref(null)
|
|
44
|
+
const canvasRef = ref(null)
|
|
45
|
+
let canvasCtx = null
|
|
46
|
+
const isTouch = 'ontouchstart' in window
|
|
47
|
+
const canvasEvents = isTouch ? ['touchstart', 'touchmove', 'touchend', 'touchleave'] : ['mousedown', 'mousemove', 'mouseup', 'mouseleave']
|
|
48
|
+
|
|
49
|
+
const wrapClass = computed(() => {
|
|
50
|
+
return {
|
|
51
|
+
border: props.border
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
const wrapStyle = computed(() => {
|
|
55
|
+
return {
|
|
56
|
+
width: props.width || '100%',
|
|
57
|
+
height: props.height
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
const canvasConfig = reactive({ width: 0, height: 0 })
|
|
61
|
+
|
|
62
|
+
const initCanvas = () => {
|
|
63
|
+
if (!isCanvasSupported()) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
canvasCtx = canvasRef.value.getContext('2d')
|
|
67
|
+
canvasConfig.width = wrapRef.value.offsetWidth
|
|
68
|
+
canvasConfig.height = wrapRef.value.offsetHeight
|
|
69
|
+
addEvent()
|
|
70
|
+
}
|
|
71
|
+
const isCanvasSupported = () => {
|
|
72
|
+
let elem = document.createElement('canvas')
|
|
73
|
+
return !!(elem.getContext && elem.getContext('2d'))
|
|
74
|
+
}
|
|
75
|
+
const addEvent = () => {
|
|
76
|
+
canvasRef.value.addEventListener(canvasEvents[0], startEventHandler, false)
|
|
77
|
+
}
|
|
78
|
+
const startEventHandler = event => {
|
|
79
|
+
event.preventDefault()
|
|
80
|
+
canvasCtx.beginPath()
|
|
81
|
+
canvasCtx.lineWidth = props.line
|
|
82
|
+
canvasCtx.strokeStyle = props.color
|
|
83
|
+
emit('start')
|
|
84
|
+
canvasRef.value.addEventListener(canvasEvents[1], moveEventHandler, false)
|
|
85
|
+
canvasRef.value.addEventListener(canvasEvents[2], endEventHandler, false)
|
|
86
|
+
canvasRef.value.addEventListener(canvasEvents[3], leaveEventHandler, false)
|
|
87
|
+
}
|
|
88
|
+
const moveEventHandler = event => {
|
|
89
|
+
event.preventDefault()
|
|
90
|
+
let evt = isTouch ? event.touches[0] : event
|
|
91
|
+
let coverPos = canvasRef.value.getBoundingClientRect()
|
|
92
|
+
let mouseX = evt.clientX - coverPos.left
|
|
93
|
+
let mouseY = evt.clientY - coverPos.top
|
|
94
|
+
canvasCtx.lineTo(mouseX, mouseY)
|
|
95
|
+
canvasCtx.stroke()
|
|
96
|
+
emit('signing', evt)
|
|
97
|
+
}
|
|
98
|
+
const endEventHandler = event => {
|
|
99
|
+
event.preventDefault()
|
|
100
|
+
emit('end')
|
|
101
|
+
canvasRef.value.removeEventListener(canvasEvents[1], moveEventHandler, false)
|
|
102
|
+
canvasRef.value.removeEventListener(canvasEvents[2], endEventHandler, false)
|
|
103
|
+
}
|
|
104
|
+
const leaveEventHandler = event => {
|
|
105
|
+
event.preventDefault()
|
|
106
|
+
canvasRef.value.removeEventListener(canvasEvents[1], moveEventHandler, false)
|
|
107
|
+
canvasRef.value.removeEventListener(canvasEvents[2], endEventHandler, false)
|
|
108
|
+
}
|
|
109
|
+
const clear = () => {
|
|
110
|
+
canvasRef.value.addEventListener(canvasEvents[2], endEventHandler, false)
|
|
111
|
+
canvasCtx.clearRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight)
|
|
112
|
+
canvasCtx.closePath()
|
|
113
|
+
emit('clear')
|
|
114
|
+
}
|
|
115
|
+
const isCanvasBlank = canvas2 => {
|
|
116
|
+
if (!canvas2) {
|
|
117
|
+
return true
|
|
118
|
+
}
|
|
119
|
+
var blank = document.createElement('canvas')
|
|
120
|
+
blank.width = canvas2.width
|
|
121
|
+
blank.height = canvas2.height
|
|
122
|
+
return (canvas2 == null ? void 0 : canvas2.toDataURL()) == blank.toDataURL()
|
|
123
|
+
}
|
|
124
|
+
const confirm = () => {
|
|
125
|
+
let dataurl
|
|
126
|
+
let canvasIn = canvasRef.value
|
|
127
|
+
switch (props.type) {
|
|
128
|
+
case 'png':
|
|
129
|
+
dataurl = canvasIn.toDataURL('image/png')
|
|
130
|
+
break
|
|
131
|
+
case 'jpg':
|
|
132
|
+
dataurl = canvasIn.toDataURL('image/jpeg', 0.8)
|
|
133
|
+
break
|
|
134
|
+
}
|
|
135
|
+
const _canvas = isCanvasBlank(canvasIn) ? '请绘制' : canvasIn
|
|
136
|
+
const _filePath = isCanvasBlank(canvasIn) ? '' : dataurl
|
|
137
|
+
emit('confirm', _canvas, _filePath)
|
|
138
|
+
}
|
|
139
|
+
onMounted(() => {
|
|
140
|
+
initCanvas()
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
slots,
|
|
145
|
+
wrapRef,
|
|
146
|
+
canvasRef,
|
|
147
|
+
wrapClass,
|
|
148
|
+
wrapStyle,
|
|
149
|
+
canvasConfig,
|
|
150
|
+
confirm,
|
|
151
|
+
clear
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
</script>
|
|
156
|
+
|
|
157
|
+
<style lang="scss" scoped>
|
|
158
|
+
.sh-signature {
|
|
159
|
+
display: block;
|
|
160
|
+
text-align: center;
|
|
161
|
+
&.border {
|
|
162
|
+
border: 1px solid var(--border-color);
|
|
163
|
+
}
|
|
164
|
+
canvas {
|
|
165
|
+
display: block;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
</style>
|
|
@@ -30,6 +30,15 @@
|
|
|
30
30
|
background-color: transparent;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
&.is--maximize {
|
|
34
|
+
position: fixed;
|
|
35
|
+
top: 0;
|
|
36
|
+
left: 0;
|
|
37
|
+
width: 100%;
|
|
38
|
+
height: 100%;
|
|
39
|
+
padding: 0.5em 1em;
|
|
40
|
+
background-color: var(--bg-layout-color);
|
|
41
|
+
}
|
|
33
42
|
.sh-table-footer{
|
|
34
43
|
height: 40px;
|
|
35
44
|
padding: 5px;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="sh-vxe-table"
|
|
2
|
+
<div class="sh-vxe-table" v-bind="wrapBind">
|
|
3
3
|
<vxe-grid
|
|
4
4
|
ref="tableRef"
|
|
5
5
|
:class="{ 'is--hasfooter': showFooter }"
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
<div v-if="slots.toolbarRight" class="sh-table-toolbar-item">
|
|
57
57
|
<slot name="toolbarRight"></slot>
|
|
58
58
|
</div>
|
|
59
|
+
<div v-if="tableMoneyConfig.enabled" @click.stop class="sh-table-toolbar-item">单位:<vxe-select v-model="tableMoneyUnit" v-bind="tableMoneyConfig" /></div>
|
|
59
60
|
<div class="sh-table-toolbar-item" v-for="(tool, toolIndex) in tableTools" :key="toolIndex">
|
|
60
|
-
<vxe-button
|
|
61
|
+
<vxe-button :size="size" v-bind="tool" @click="handleTableTool(tool)"></vxe-button>
|
|
61
62
|
</div>
|
|
62
|
-
<div v-if="tableMoneyConfig.enabled" @click.stop class="sh-table-toolbar-item">单位:<vxe-select v-model="tableMoneyUnit" v-bind="tableMoneyConfig" /></div>
|
|
63
63
|
</template>
|
|
64
64
|
</vxe-toolbar>
|
|
65
65
|
</div>
|
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
},
|
|
48
48
|
size: {
|
|
49
49
|
type: String,
|
|
50
|
-
default: '
|
|
50
|
+
default: '' // medium / small / mini
|
|
51
51
|
},
|
|
52
52
|
loading: {
|
|
53
53
|
type: Boolean,
|
|
@@ -133,6 +133,24 @@ export default {
|
|
|
133
133
|
return {}
|
|
134
134
|
}
|
|
135
135
|
},
|
|
136
|
+
cellConfig: {
|
|
137
|
+
type: Object,
|
|
138
|
+
default() {
|
|
139
|
+
return {}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
headerCellConfig: {
|
|
143
|
+
type: Object,
|
|
144
|
+
default() {
|
|
145
|
+
return {}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
footerCellConfig: {
|
|
149
|
+
type: Object,
|
|
150
|
+
default() {
|
|
151
|
+
return {}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
136
154
|
seqConfig: {
|
|
137
155
|
type: Object,
|
|
138
156
|
default() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { computed, onMounted, reactive, ref, watch, nextTick } from 'vue'
|
|
2
2
|
import { seqMethod, columnDefaultFilterMethod, tableFooterCompute, getTransfarFields, formulaReplaceAll } from './tableMethods'
|
|
3
|
+
import domZindex from 'dom-zindex'
|
|
3
4
|
|
|
4
5
|
// 记录自定义参数,传给vxe要过滤掉
|
|
5
6
|
let omitProps = [
|
|
@@ -80,7 +81,7 @@ const columnsMapDefault = {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
export default function (props, context, proxy, isGrid) {
|
|
83
|
-
const { $vUtils, $vTableSetup, $vxePluginNames, $route } = proxy
|
|
84
|
+
const { $vUtils, $vUiSetup, $vTableSetup, $vxePluginNames, $route } = proxy
|
|
84
85
|
const { emit, slots } = context
|
|
85
86
|
|
|
86
87
|
const tableRef = ref()
|
|
@@ -95,10 +96,28 @@ export default function (props, context, proxy, isGrid) {
|
|
|
95
96
|
const tableEditRules = ref({}) // 表格根据表头自动生成验证规则
|
|
96
97
|
const tableFilterText = ref('') // 全局过滤关键字
|
|
97
98
|
const tableCurrentRowData = ref(null) // 表格当前高亮行
|
|
99
|
+
const tZindex = ref(0)
|
|
100
|
+
const zoomStatus = ref(false)
|
|
98
101
|
|
|
99
102
|
const wrapHeight = computed(() => ([100, '100%', 'auto'].includes(props.height) ? '100%' : 'auto'))
|
|
103
|
+
const wrapBind = computed(() => {
|
|
104
|
+
const { ghost, loading } = tableGlobalConfig.value
|
|
105
|
+
let warpClass = { 'sh-table-ghost': ghost }
|
|
106
|
+
let warpStyle = { height: wrapHeight.value }
|
|
107
|
+
if (!isGrid) {
|
|
108
|
+
if (zoomStatus.value) {
|
|
109
|
+
warpStyle.zIndex = tZindex.value
|
|
110
|
+
}
|
|
111
|
+
warpClass['is--loading'] = loading
|
|
112
|
+
warpClass['is--maximize'] = zoomStatus.value
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
class: warpClass,
|
|
116
|
+
style: warpStyle
|
|
117
|
+
}
|
|
118
|
+
})
|
|
100
119
|
const hasTree = computed(() => props.columns.some(_ => _.treeNode))
|
|
101
|
-
const tableVmConfig = computed(() => ({ size: props.size }))
|
|
120
|
+
const tableVmConfig = computed(() => ({ size: props.size || $vUiSetup.size }))
|
|
102
121
|
const tableGlobalConfig = computed(() => Object.assign({}, globalConfigDefault, props.globalConfig))
|
|
103
122
|
const tableTools = computed(() => {
|
|
104
123
|
let tools = props.globalConfig?.tools || []
|
|
@@ -118,7 +137,7 @@ export default function (props, context, proxy, isGrid) {
|
|
|
118
137
|
const tableColumnObjConfig = computed(() => Object.assign({}, columnObjDefault, props.columnObj))
|
|
119
138
|
const tableColumnConfig = computed(() => Object.assign({ isHover: true, resizable: true }, props.columnConfig))
|
|
120
139
|
const tablePagerConfig = computed(() =>
|
|
121
|
-
Object.assign({ enabled: Boolean(props.pagerConfig), total: 0, className: 'sh-table-footer', slots: { left: 'pagerLeft', right: 'pagerRight' } }, props.pagerConfig)
|
|
140
|
+
Object.assign({ enabled: Boolean(props.pagerConfig), total: 0, className: 'sh-table-footer', slots: { left: 'pagerLeft', right: 'pagerRight' } }, props.pagerConfig, tableVmConfig.value)
|
|
122
141
|
)
|
|
123
142
|
const tableCheckboxConfig = computed(() => {
|
|
124
143
|
return Object.assign({ range: !hasTree.value }, props.checkboxConfig)
|
|
@@ -220,7 +239,7 @@ export default function (props, context, proxy, isGrid) {
|
|
|
220
239
|
const toolbarFg = tableToolbarConfig.value
|
|
221
240
|
const toolsFg = tableTools.value
|
|
222
241
|
const globalTool = globalFg.title || globalFg.globalFilter
|
|
223
|
-
const toolbarTool = toolbarFg.import || toolbarFg.export || toolbarFg.print || toolbarFg.refresh || toolbarFg.custom
|
|
242
|
+
const toolbarTool = toolbarFg.import || toolbarFg.export || toolbarFg.print || toolbarFg.refresh || toolbarFg.zoom || toolbarFg.custom
|
|
224
243
|
const slotsTool = slots.toolbar || slots.toolbarLeft || slots.toolbarRight
|
|
225
244
|
return globalTool || toolbarTool || slotsTool || toolsFg.length > 0 || tableMoneyConfig.value.enabled
|
|
226
245
|
})
|
|
@@ -517,6 +536,9 @@ export default function (props, context, proxy, isGrid) {
|
|
|
517
536
|
case 'print':
|
|
518
537
|
handleTablePrintBtn()
|
|
519
538
|
break
|
|
539
|
+
case 'zoom':
|
|
540
|
+
handleTableZoomBtn()
|
|
541
|
+
break
|
|
520
542
|
}
|
|
521
543
|
emit('toolbar-btn-click', code)
|
|
522
544
|
}
|
|
@@ -538,6 +560,13 @@ export default function (props, context, proxy, isGrid) {
|
|
|
538
560
|
}
|
|
539
561
|
return tableRef.value.openPrint(options)
|
|
540
562
|
}
|
|
563
|
+
// 缩放按钮事件
|
|
564
|
+
const handleTableZoomBtn = () => {
|
|
565
|
+
zoomStatus.value = !zoomStatus.value
|
|
566
|
+
if (tZindex.value < domZindex.getCurrent()) {
|
|
567
|
+
tZindex.value = domZindex.getNext()
|
|
568
|
+
}
|
|
569
|
+
}
|
|
541
570
|
// 关联toolbar
|
|
542
571
|
const connectToolbar = () => {
|
|
543
572
|
nextTick(() => {
|
|
@@ -633,7 +662,9 @@ export default function (props, context, proxy, isGrid) {
|
|
|
633
662
|
slots,
|
|
634
663
|
tableRef,
|
|
635
664
|
toolbarRef,
|
|
665
|
+
zoomStatus,
|
|
636
666
|
wrapHeight,
|
|
667
|
+
wrapBind,
|
|
637
668
|
tableGlobalConfig,
|
|
638
669
|
tablePrevColumns,
|
|
639
670
|
tableColumns,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div ref="tableWrapRef" v-resize="handleResize" class="sh-vxe-table"
|
|
2
|
+
<div ref="tableWrapRef" v-resize="handleResize" class="sh-vxe-table" v-bind="wrapBind">
|
|
3
3
|
<div v-if="isTopSlot" ref="topSlotRef" v-resize="handleResize" class="sh-table-top"><slot name="top"></slot></div>
|
|
4
4
|
<div v-if="isFormSlot" ref="formSlotRef" v-resize="handleResize" class="sh-table-form">
|
|
5
5
|
<slot name="form">
|
|
@@ -31,10 +31,13 @@
|
|
|
31
31
|
<div v-if="slots.toolbarRight" class="sh-table-toolbar-item">
|
|
32
32
|
<slot name="toolbarRight"></slot>
|
|
33
33
|
</div>
|
|
34
|
+
<div v-if="tableMoneyConfig.enabled" @click.stop class="sh-table-toolbar-item">单位:<vxe-select v-model="tableMoneyUnit" v-bind="tableMoneyConfig" /></div>
|
|
34
35
|
<div class="sh-table-toolbar-item" v-for="(tool, toolIndex) in tableTools" :key="toolIndex">
|
|
35
|
-
<vxe-button
|
|
36
|
+
<vxe-button :size="size" v-bind="tool" @click="handleTableTool(tool)"></vxe-button>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="sh-table-toolbar-item" v-if="tableToolbarConfig.zoom">
|
|
39
|
+
<vxe-button :size="size" circle :icon="zoomStatus ? 'vxe-table-icon-minimize' : 'vxe-table-icon-fullscreen'" @click="handleTableTool({ code: 'zoom' })"></vxe-button>
|
|
36
40
|
</div>
|
|
37
|
-
<div v-if="tableMoneyConfig.enabled" @click.stop class="sh-table-toolbar-item">单位:<vxe-select v-model="tableMoneyUnit" v-bind="tableMoneyConfig" /></div>
|
|
38
41
|
</template>
|
|
39
42
|
</vxe-toolbar>
|
|
40
43
|
</slot>
|
|
@@ -67,7 +67,7 @@ export default defineComponent({
|
|
|
67
67
|
},
|
|
68
68
|
size: {
|
|
69
69
|
type: String,
|
|
70
|
-
default: '
|
|
70
|
+
default: '' // medium / small / mini
|
|
71
71
|
},
|
|
72
72
|
animated: {
|
|
73
73
|
type: Boolean,
|
|
@@ -93,7 +93,7 @@ export default defineComponent({
|
|
|
93
93
|
emits: ['update:modelValue', 'close', 'change'],
|
|
94
94
|
setup(props, context) {
|
|
95
95
|
const { proxy } = getCurrentInstance()
|
|
96
|
-
const { $vUtils } = proxy
|
|
96
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
97
97
|
const { emit, slots } = context
|
|
98
98
|
|
|
99
99
|
const navRef = ref()
|
|
@@ -107,12 +107,13 @@ export default defineComponent({
|
|
|
107
107
|
|
|
108
108
|
const isHorizontal = computed(() => ['left', 'right'].includes(props.placement))
|
|
109
109
|
const hasContent = computed(() => props.isContent && activeKey.value && props.options.map(item => item[props.labelKey]).includes(activeKey.value))
|
|
110
|
+
const vmSize = computed(() => props.size || $vUiSetup.size)
|
|
110
111
|
const tabClass = computed(() => {
|
|
111
112
|
return {
|
|
112
113
|
'sh-tabs-card': props.type === 'card',
|
|
113
114
|
'sh-tabs-tab': props.type === 'tab',
|
|
114
115
|
'sh-tabs-reverse': ['bottom', 'right'].includes(props.placement),
|
|
115
|
-
[`sh-tabs-size-${
|
|
116
|
+
[`sh-tabs-size-${vmSize.value}`]: true,
|
|
116
117
|
[isHorizontal.value ? 'sh-tabs-horizontal' : 'sh-tabs-vertical']: true
|
|
117
118
|
}
|
|
118
119
|
})
|
|
@@ -50,7 +50,7 @@ export default defineComponent({
|
|
|
50
50
|
},
|
|
51
51
|
size: {
|
|
52
52
|
type: String,
|
|
53
|
-
default: '
|
|
53
|
+
default: '' // medium / small / mini
|
|
54
54
|
},
|
|
55
55
|
opacity: {
|
|
56
56
|
type: Number,
|
|
@@ -60,10 +60,12 @@ export default defineComponent({
|
|
|
60
60
|
emits: ['change', 'close'],
|
|
61
61
|
setup(props, context) {
|
|
62
62
|
const { proxy } = getCurrentInstance()
|
|
63
|
-
const { $vUtils } = proxy
|
|
63
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
64
64
|
const { emit, slots } = context
|
|
65
65
|
|
|
66
66
|
const isChecked = ref(props.checked)
|
|
67
|
+
|
|
68
|
+
const vmSize = computed(() => props.size || $vUiSetup.size)
|
|
67
69
|
const colorIn = computed(() => props.color || 'default')
|
|
68
70
|
const colorRgb = computed(() => colorMap[colorIn.value] || $vUtils.lighten(colorIn.value))
|
|
69
71
|
const isCustom = computed(() => !!colorMap[colorIn.value])
|
|
@@ -79,7 +81,7 @@ export default defineComponent({
|
|
|
79
81
|
})
|
|
80
82
|
const classes = computed(() => {
|
|
81
83
|
return {
|
|
82
|
-
[`${
|
|
84
|
+
[`${vmSize.value}`]: !!vmSize.value,
|
|
83
85
|
[`${props.type}`]: !!props.type,
|
|
84
86
|
[`closable`]: props.closable,
|
|
85
87
|
[`checked`]: isChecked.value,
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
<slot name="left"></slot>
|
|
5
5
|
<template v-if="isTool">
|
|
6
6
|
<template v-for="(toolBtn, toolBtnIndex) in toolBtns" :key="toolBtnIndex">
|
|
7
|
-
<vxe-button
|
|
7
|
+
<vxe-button :size="vmSize" v-bind="toolBtn" @click="handleToolBtn(toolBtn)"></vxe-button>
|
|
8
8
|
</template>
|
|
9
9
|
</template>
|
|
10
10
|
<vxe-radio-group v-else v-model="leftActive" @change="handleLeftBtn">
|
|
11
11
|
<template v-for="(leftBtn, leftBtnIndex) in leftBtns" :key="leftBtnIndex">
|
|
12
|
-
<vxe-radio-button
|
|
12
|
+
<vxe-radio-button :size="vmSize" v-bind="leftBtn" :label="leftBtn.value"></vxe-radio-button>
|
|
13
13
|
</template>
|
|
14
14
|
</vxe-radio-group>
|
|
15
15
|
<slot name="leftr"></slot>
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div class="toolbar-right">
|
|
18
18
|
<slot name="rightl"></slot>
|
|
19
19
|
<template v-for="(rightBtn, rightBtnIndex) in rightBtns" :key="rightBtnIndex">
|
|
20
|
-
<vxe-button
|
|
20
|
+
<vxe-button :size="vmSize" v-bind="rightBtn" @click="handleRightBtn(rightBtn)"></vxe-button>
|
|
21
21
|
</template>
|
|
22
22
|
<slot name="right"></slot>
|
|
23
23
|
</div>
|
|
@@ -87,16 +87,21 @@ export default defineComponent({
|
|
|
87
87
|
{ code: 'batch-detail', content: '查看', status: '', icon: 'vxe-icon-information' }
|
|
88
88
|
]
|
|
89
89
|
}
|
|
90
|
+
},
|
|
91
|
+
size: {
|
|
92
|
+
type: String,
|
|
93
|
+
default: '' // medium / small / mini
|
|
90
94
|
}
|
|
91
95
|
},
|
|
92
|
-
emits: ['update:modelValue', 'left', 'right', 'tool'],
|
|
96
|
+
emits: ['update:modelValue', 'input', 'left', 'right', 'tool'],
|
|
93
97
|
setup(props, context) {
|
|
94
98
|
const { proxy } = getCurrentInstance()
|
|
95
|
-
const { $vUtils } = proxy
|
|
99
|
+
const { $vUtils, $vUiSetup } = proxy
|
|
96
100
|
const { emit, slots } = context
|
|
97
101
|
|
|
98
102
|
const leftActive = ref(props.modelValue)
|
|
99
103
|
|
|
104
|
+
const vmSize = computed(() => props.size || $vUiSetup.size)
|
|
100
105
|
const leftBtns = computed(() => {
|
|
101
106
|
let lBtns = []
|
|
102
107
|
if (props.leftContain && Array.isArray(props.leftContain)) {
|
|
@@ -125,7 +130,7 @@ export default defineComponent({
|
|
|
125
130
|
|
|
126
131
|
const handleLeftBtn = ({ label }) => {
|
|
127
132
|
let btnObj = props.leftConfig.find(item => item.value === label)
|
|
128
|
-
emitValue()
|
|
133
|
+
emitValue(btnObj)
|
|
129
134
|
emit('left', label, btnObj)
|
|
130
135
|
}
|
|
131
136
|
const handleRightBtn = btn => {
|
|
@@ -134,7 +139,8 @@ export default defineComponent({
|
|
|
134
139
|
const handleToolBtn = btn => {
|
|
135
140
|
emit('tool', btn)
|
|
136
141
|
}
|
|
137
|
-
const emitValue =
|
|
142
|
+
const emitValue = btnObj => {
|
|
143
|
+
emit('input', leftActive.value, btnObj)
|
|
138
144
|
emit('update:modelValue', leftActive.value)
|
|
139
145
|
}
|
|
140
146
|
|
|
@@ -37,6 +37,7 @@ const tableConfigDefault = {
|
|
|
37
37
|
showFooter: false,
|
|
38
38
|
showOverflow: true,
|
|
39
39
|
resizeConfig: { refreshDelay: 100 },
|
|
40
|
+
cellConfig: { padding: false, height: 32, verticalAlign: 'center' },
|
|
40
41
|
columnConfig: { width: 120 },
|
|
41
42
|
virtualXConfig: { enabled: true, gt: 20 },
|
|
42
43
|
virtualYConfig: { enabled: true, gt: 20 }
|
|
@@ -1,33 +1,4 @@
|
|
|
1
1
|
/* 设置持续时间和动画函数 */
|
|
2
|
-
.sh-pop-in-enter-active,
|
|
3
|
-
.sh-pop-in-leave-active,
|
|
4
|
-
.sh-pop-out-enter-active,
|
|
5
|
-
.sh-pop-out-leave-active,{
|
|
6
|
-
will-change: transform;
|
|
7
|
-
transform-origin: center;
|
|
8
|
-
transition: all 0.1s;
|
|
9
|
-
backface-visibility: hidden;
|
|
10
|
-
perspective: 1000px;
|
|
11
|
-
width: 100%;
|
|
12
|
-
height: 100%;
|
|
13
|
-
position: absolute;
|
|
14
|
-
}
|
|
15
|
-
.sh-pop-in-enter-from, .sh-pop-out-leave-to {
|
|
16
|
-
transform: translateX(50%);
|
|
17
|
-
opacity: 0;
|
|
18
|
-
}
|
|
19
|
-
.sh-pop-in-enter-to {
|
|
20
|
-
transform: translateX(0);
|
|
21
|
-
opacity: 1;
|
|
22
|
-
}
|
|
23
|
-
.sh-pop-out-enter-from, .sh-pop-in-leave-to {
|
|
24
|
-
transform: translateX(-50%);
|
|
25
|
-
opacity: 0;
|
|
26
|
-
}
|
|
27
|
-
.sh-pop-out-enter-to {
|
|
28
|
-
transform: translateX(0);
|
|
29
|
-
opacity: 1;
|
|
30
|
-
}
|
|
31
2
|
$animation-time: .3s;
|
|
32
3
|
$animation-time-quick: .15s;
|
|
33
4
|
$transition-time: .2s;
|
package/packages/utils/resize.js
CHANGED
|
@@ -15,7 +15,7 @@ function eventHandle() {
|
|
|
15
15
|
const rHeight = clientHeight && heighe !== clientHeight
|
|
16
16
|
if (rWidth || rHeight) {
|
|
17
17
|
observer.width = clientWidth
|
|
18
|
-
observer.
|
|
18
|
+
observer.height = clientHeight
|
|
19
19
|
setTimeout(item.callback)
|
|
20
20
|
}
|
|
21
21
|
})
|
|
@@ -42,7 +42,7 @@ export class XEResizeObserver {
|
|
|
42
42
|
tarList.push({
|
|
43
43
|
target,
|
|
44
44
|
width: target.clientWidth,
|
|
45
|
-
|
|
45
|
+
height: target.clientHeight
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
if (!eventStore.length) {
|
|
@@ -153,9 +153,13 @@ button:focus, .vxe-button.type--button:not(.is--disabled):focus{
|
|
|
153
153
|
font-family: inherit;
|
|
154
154
|
color: inherit;
|
|
155
155
|
.vxe-table--render-wrapper{
|
|
156
|
-
.vxe-
|
|
157
|
-
padding
|
|
158
|
-
|
|
156
|
+
.vxe-body--column{
|
|
157
|
+
&.is--padding{
|
|
158
|
+
.vxe-cell{
|
|
159
|
+
padding-left: 2px;
|
|
160
|
+
padding-right: 2px;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
159
163
|
}
|
|
160
164
|
.vxe-header--column{
|
|
161
165
|
.vxe-cell{
|
|
@@ -20,6 +20,7 @@ import { utils } from 'sh-tools'
|
|
|
20
20
|
import { publicRenders, extraRenders, filterRenders, publicRendersNames } from './render/globalRenders.jsx'
|
|
21
21
|
|
|
22
22
|
let uiOptions = {
|
|
23
|
+
size: 'small',
|
|
23
24
|
input: {
|
|
24
25
|
controls: false,
|
|
25
26
|
clearable: true
|
|
@@ -46,7 +47,7 @@ let uiOptions = {
|
|
|
46
47
|
{ label: '500条', value: 500 },
|
|
47
48
|
{ label: '1000条', value: 1000 },
|
|
48
49
|
{ label: '10000条', value: 10000 },
|
|
49
|
-
{ label: '
|
|
50
|
+
{ label: '全部', value: 999999999 }
|
|
50
51
|
],
|
|
51
52
|
align: 'right',
|
|
52
53
|
border: true,
|
|
@@ -93,6 +94,19 @@ let tableOptions = {
|
|
|
93
94
|
drag: false,
|
|
94
95
|
resizable: false
|
|
95
96
|
},
|
|
97
|
+
headerCellConfig: {
|
|
98
|
+
padding: false,
|
|
99
|
+
height: 40
|
|
100
|
+
},
|
|
101
|
+
cellConfig: {
|
|
102
|
+
padding: true,
|
|
103
|
+
height: 40,
|
|
104
|
+
verticalAlign: 'center'
|
|
105
|
+
},
|
|
106
|
+
footerCellConfig: {
|
|
107
|
+
padding: true,
|
|
108
|
+
height: 40
|
|
109
|
+
},
|
|
96
110
|
columnConfig: {
|
|
97
111
|
useKey: true,
|
|
98
112
|
isHover: true,
|
|
@@ -257,6 +271,7 @@ const index = {
|
|
|
257
271
|
Vue.config.globalProperties.$vModal = VXEUI.modal
|
|
258
272
|
Vue.config.globalProperties.$vUi = VXEUI
|
|
259
273
|
Vue.config.globalProperties.$vTable = VXETable
|
|
274
|
+
Vue.config.globalProperties.$vUiSetup = vuiOption
|
|
260
275
|
Vue.config.globalProperties.$vTableSetup = vtableOption
|
|
261
276
|
Vue.config.globalProperties.$vxePluginNames = publicRendersNames
|
|
262
277
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="vxe-filter--top">
|
|
4
4
|
<vxe-radio-group v-model="renderOption.data.type">
|
|
5
5
|
<template v-for="filterType in filterTypes" :key="filterType.value">
|
|
6
|
-
<vxe-radio-button
|
|
6
|
+
<vxe-radio-button :label="filterType.value" size="mini">{{ filterType.label }}</vxe-radio-button>
|
|
7
7
|
</template>
|
|
8
8
|
</vxe-radio-group>
|
|
9
9
|
</div>
|