sh-view 2.1.0 → 2.2.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.
- package/package.json +9 -13
- package/packages/components/global-components/sh-alert/index.vue +175 -173
- package/packages/components/global-components/sh-badge/index.vue +57 -43
- package/packages/components/global-components/sh-card/index.vue +24 -16
- package/packages/components/global-components/sh-code-editor/index.vue +250 -260
- package/packages/components/global-components/sh-col/index.vue +44 -36
- package/packages/components/global-components/sh-corner/index.vue +230 -228
- package/packages/components/global-components/sh-count-to/index.vue +60 -51
- package/packages/components/global-components/sh-drawer/index.vue +209 -182
- package/packages/components/global-components/sh-drawer/scrollbar.js +44 -42
- package/packages/components/global-components/sh-empty/index.vue +0 -1
- package/packages/components/global-components/sh-form/form.vue +110 -0
- package/packages/components/global-components/sh-form/js/props.js +76 -63
- package/packages/components/global-components/sh-form/js/useForm.js +236 -0
- package/packages/components/global-components/sh-form/query.vue +70 -0
- package/packages/components/global-components/sh-header/index.vue +35 -50
- package/packages/components/global-components/sh-icon/css/index.scss +44 -0
- package/packages/components/global-components/sh-icon/index.vue +24 -11
- package/packages/components/global-components/sh-image/index.vue +47 -38
- package/packages/components/global-components/sh-list/index.vue +42 -37
- package/packages/components/global-components/sh-loading/index.vue +12 -8
- package/packages/components/global-components/sh-modal/index.vue +49 -40
- package/packages/components/global-components/sh-noticebar/index.vue +68 -54
- package/packages/components/global-components/sh-poptip/index.vue +247 -130
- package/packages/components/global-components/sh-progress/index.vue +71 -69
- package/packages/components/global-components/sh-pull-refresh/index.vue +156 -157
- package/packages/components/global-components/sh-result/index.vue +37 -28
- package/packages/components/global-components/sh-row/index.vue +21 -18
- package/packages/components/global-components/sh-split/index.vue +115 -109
- package/packages/components/global-components/sh-table/components/importModal.vue +95 -86
- package/packages/components/global-components/sh-table/components/sh-column.vue +54 -0
- package/packages/components/global-components/sh-table/{index.vue → grid.vue} +34 -145
- package/packages/components/global-components/sh-table/js/tableMethods.js +175 -0
- package/packages/components/global-components/sh-table/js/useTable.js +592 -0
- package/packages/components/global-components/sh-table/table.vue +269 -0
- package/packages/components/global-components/sh-tabs/index.vue +118 -93
- package/packages/components/global-components/sh-tag/index.vue +52 -51
- package/packages/components/global-components/sh-toolbar/index.vue +53 -47
- package/packages/components/global-components/sh-tree/components/table-tree.vue +152 -139
- package/packages/components/global-components/sh-tree/index.vue +218 -195
- package/packages/components/global-components/sh-tree/mixin/treeProps.js +118 -120
- package/packages/components/global-components/sh-upload/index.vue +308 -51
- package/packages/components/global-components/sh-water-fall/index.vue +4 -11
- package/packages/components/index.js +5 -3
- package/packages/components/other-components/sh-cron-modal/components/cron-content.vue +140 -129
- package/packages/components/other-components/sh-cron-modal/css/index.scss +0 -5
- package/packages/components/other-components/sh-cron-modal/index.vue +81 -67
- package/packages/components/other-components/sh-cron-modal/mixin/cron-emits.js +1 -0
- package/packages/components/other-components/sh-cron-modal/mixin/cron-hooks.js +179 -0
- package/packages/components/other-components/sh-cron-modal/mixin/cron-props.js +9 -0
- package/packages/components/other-components/sh-cron-modal/tabs/cron-day-box.vue +101 -92
- package/packages/components/other-components/sh-cron-modal/tabs/cron-hour-box.vue +68 -56
- package/packages/components/other-components/sh-cron-modal/tabs/cron-minute-box.vue +68 -56
- package/packages/components/other-components/sh-cron-modal/tabs/cron-month-box.vue +68 -56
- package/packages/components/other-components/sh-cron-modal/tabs/cron-second-box.vue +68 -56
- package/packages/components/other-components/sh-cron-modal/tabs/cron-week-box.vue +126 -115
- package/packages/components/other-components/sh-cron-modal/tabs/cron-year-box.vue +59 -46
- package/packages/components/other-components/sh-menu/index.vue +73 -60
- package/packages/components/other-components/sh-menu/menu-group-content.vue +71 -59
- package/packages/components/other-components/sh-menu/menu-item-content.vue +40 -30
- package/packages/components/other-components/sh-menu-card/index.vue +70 -64
- package/packages/components/other-components/sh-menu-card/menu-box.vue +50 -44
- package/packages/components/other-components/sh-preview/components/sh-excel.vue +182 -0
- package/packages/components/other-components/sh-preview/components/sh-word.vue +73 -0
- package/packages/components/other-components/sh-preview/index.vue +86 -85
- package/packages/components/other-components/sh-preview/js/data-hook.js +37 -0
- package/packages/components/other-components/sh-preview/js/data-props.js +11 -0
- package/packages/components/other-components/sh-system-tip/index.vue +28 -24
- package/packages/css/index.js +4 -4
- package/packages/directive/module/prevent-click.js +1 -1
- package/packages/directive/module/resize.js +11 -154
- package/packages/index.js +39 -39
- package/packages/mixin/index.js +86 -87
- package/packages/vxeTable/render/cell/vxe-render-checkbox.vue +14 -5
- package/packages/vxeTable/render/cell/vxe-render-checkgroup.vue +43 -36
- package/packages/vxeTable/render/cell/vxe-render-code.vue +14 -5
- package/packages/vxeTable/render/cell/vxe-render-goption.vue +34 -24
- package/packages/vxeTable/render/cell/vxe-render-href.vue +21 -11
- package/packages/vxeTable/render/cell/vxe-render-img.vue +16 -10
- package/packages/vxeTable/render/cell/vxe-render-input.vue +83 -79
- package/packages/vxeTable/render/cell/vxe-render-money.vue +14 -6
- package/packages/vxeTable/render/cell/vxe-render-progress.vue +28 -19
- package/packages/vxeTable/render/cell/vxe-render-radio.vue +14 -5
- package/packages/vxeTable/render/cell/vxe-render-radiogroup.vue +43 -36
- package/packages/vxeTable/render/cell/vxe-render-select.vue +44 -36
- package/packages/vxeTable/render/cell/vxe-render-switch.vue +14 -5
- package/packages/vxeTable/render/cell/vxe-render-table.vue +51 -78
- package/packages/vxeTable/render/cell/vxe-render-textarea.vue +14 -5
- package/packages/vxeTable/render/cell/vxe-render-time.vue +23 -13
- package/packages/vxeTable/render/cell/vxe-render-tree.vue +23 -27
- package/packages/vxeTable/render/cell/vxe-render-upload.vue +11 -7
- package/packages/vxeTable/render/filters/vxe-filter-input.vue +25 -43
- package/packages/vxeTable/render/footer/vxe-footer-input.vue +23 -13
- package/packages/vxeTable/render/footer/vxe-footer-money.vue +30 -20
- package/packages/vxeTable/render/globalRenders.jsx +1 -1
- package/packages/vxeTable/render/header/vxe-header-money.vue +31 -21
- package/packages/vxeTable/render/mixin/cell-hooks.js +162 -0
- package/packages/vxeTable/render/mixin/cell-props.js +23 -0
- package/packages/vxeTable/render/mixin/filter-hooks.js +28 -0
- package/packages/components/global-components/sh-form/components/form-item.vue +0 -25
- package/packages/components/global-components/sh-form/css/index.scss +0 -55
- package/packages/components/global-components/sh-form/index.vue +0 -114
- package/packages/components/global-components/sh-form/js/methods.js +0 -146
- package/packages/components/global-components/sh-form/mixin/defaultData.js +0 -32
- package/packages/components/global-components/sh-icon/css/default/index.scss +0 -27
- package/packages/components/global-components/sh-icon/css/font/index.scss +0 -16
- package/packages/components/global-components/sh-icon/icon-default.vue +0 -32
- package/packages/components/global-components/sh-icon/icon-font.vue +0 -32
- package/packages/components/global-components/sh-poptip/popper.js +0 -115
- package/packages/components/global-components/sh-query/index.vue +0 -317
- package/packages/components/global-components/sh-table/js/methods.js +0 -549
- package/packages/components/global-components/sh-table/mixin/defaultData.js +0 -94
- package/packages/components/global-components/sh-upload/js/mixin.js +0 -257
- package/packages/components/other-components/sh-cron-modal/mixin/cron-box.js +0 -169
- package/packages/vxeTable/render/mixin/cell-mixin.js +0 -195
- /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.svg → ionicons.svg} +0 -0
- /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.ttf → ionicons.ttf} +0 -0
- /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff → ionicons.woff} +0 -0
- /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff2 → ionicons.woff2} +0 -0
- /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.js → iconfont.js} +0 -0
- /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.json → iconfont.json} +0 -0
- /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.ttf → iconfont.ttf} +0 -0
- /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff → iconfont.woff} +0 -0
- /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff2 → iconfont.woff2} +0 -0
- /package/packages/{assets/css → css}/animated.scss +0 -0
- /package/packages/{assets/css → css}/loader.scss +0 -0
- /package/packages/{assets/css → css}/main.scss +0 -0
- /package/packages/{assets/css → css}/theme.scss +0 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="tableWrapRef" class="sh-vxe-table" :class="{ 'sh-table-ghost': tableGlobalConfig.ghost }" :style="{ height: wrapHeight }">
|
|
3
|
+
<div v-if="isTopSlot" ref="topSlotRef" v-resize="handleResize" class="sh-table-top"><slot name="top"></slot></div>
|
|
4
|
+
<div v-if="isFormSlot" ref="formSlotRef" v-resize="handleResize" class="sh-table-form">
|
|
5
|
+
<slot name="form">
|
|
6
|
+
<sh-query v-bind="tableQueryConfig" @submit="onFormSubmit" @reset="onFormReset" @collapsed="onFormCollapsed" @edit-closed="onFormEditClosed">
|
|
7
|
+
<template #footLeft><slot name="formLeft"></slot></template>
|
|
8
|
+
<template #footRight><slot name="formRight"></slot></template>
|
|
9
|
+
</sh-query>
|
|
10
|
+
</slot>
|
|
11
|
+
</div>
|
|
12
|
+
<div v-if="isToolbarSlot" ref="toolbarSlotRef" v-resize="handleResize" class="sh-table-toolbar">
|
|
13
|
+
<slot name="toolbar">
|
|
14
|
+
<div class="sh-table-toolbar-wrap">
|
|
15
|
+
<div class="sh-table-toolbar-left">
|
|
16
|
+
<div v-if="tableGlobalConfig.title" class="sh-table-toolbar-item">
|
|
17
|
+
<h3 class="tableName">{{ tableGlobalConfig.tableName }}</h3>
|
|
18
|
+
</div>
|
|
19
|
+
<!--ps:全表搜索不支持反转-->
|
|
20
|
+
<div v-if="tableGlobalConfig.globalFilter" class="sh-table-toolbar-item">
|
|
21
|
+
<vxe-input v-model="tableFilterText" v-bind="tableFilterConfig" @blur="handleTableFilter" @clear="handleTableFilter" @search-click="handleTableFilter" />
|
|
22
|
+
<span v-if="tableFilterData">
|
|
23
|
+
共搜索到 <strong>{{ tableFilterData.length }}</strong> 条数据
|
|
24
|
+
</span>
|
|
25
|
+
</div>
|
|
26
|
+
<div v-if="slots.toolbarLeft" class="sh-table-toolbar-item">
|
|
27
|
+
<slot name="toolbarLeft"></slot>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="sh-table-toolbar-right">
|
|
31
|
+
<div v-if="slots.toolbarRight" class="sh-table-toolbar-item">
|
|
32
|
+
<slot name="toolbarRight"></slot>
|
|
33
|
+
</div>
|
|
34
|
+
<template v-for="(tool, toolIndex) in tableTools" :key="toolIndex">
|
|
35
|
+
<div class="sh-table-toolbar-item">
|
|
36
|
+
<vxe-button v-ripple :size="size" v-bind="tool" @click="handleTableTool(tool)"></vxe-button>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</slot>
|
|
42
|
+
</div>
|
|
43
|
+
<div v-if="isHeadSlot" ref="headSlotRef" v-resize="handleResize" class="sh-table-head"><slot name="head"></slot></div>
|
|
44
|
+
<vxe-table
|
|
45
|
+
:id="id"
|
|
46
|
+
ref="tableRef"
|
|
47
|
+
:key="renderKey"
|
|
48
|
+
:class="{ 'is--hasfooter': showFooter }"
|
|
49
|
+
:data="tableViewData"
|
|
50
|
+
:width="width"
|
|
51
|
+
:height="tableHeight"
|
|
52
|
+
:min-height="minHeight"
|
|
53
|
+
:max-height="maxHeight"
|
|
54
|
+
:auto-resize="autoResize"
|
|
55
|
+
:sync-resize="syncResize"
|
|
56
|
+
:stripe="stripe && !tableTreeConfig"
|
|
57
|
+
:border="border"
|
|
58
|
+
:round="round"
|
|
59
|
+
:size="size"
|
|
60
|
+
:loading="loading"
|
|
61
|
+
:align="align"
|
|
62
|
+
:header-align="headerAlign"
|
|
63
|
+
:show-header="showHeader"
|
|
64
|
+
:row-class-name="rowClassName"
|
|
65
|
+
:cell-class-name="cellClassName"
|
|
66
|
+
:header-row-class-name="headerRowClassName"
|
|
67
|
+
:header-cell-class-name="headerCellClassName"
|
|
68
|
+
:footer-row-class-name="footerRowClassName"
|
|
69
|
+
:footer-cell-class-name="footerCellClassName"
|
|
70
|
+
:show-footer="showFooter"
|
|
71
|
+
:footer-method="footerMethod || tableFooterMethod"
|
|
72
|
+
:footer-span-method="footerSpanMethod || tableFooterSpanMethod"
|
|
73
|
+
:merge-cells="mergeCells"
|
|
74
|
+
:merge-footer-items="mergeFooterItems"
|
|
75
|
+
:show-overflow="showOverflow"
|
|
76
|
+
:show-header-overflow="showHeaderOverflow"
|
|
77
|
+
:show-footer-overflow="showFooterOverflow"
|
|
78
|
+
:keep-source="keepSource"
|
|
79
|
+
:empty-text="emptyText"
|
|
80
|
+
:row-config="rowConfig"
|
|
81
|
+
:column-config="tableColumnConfig"
|
|
82
|
+
:checkbox-config="tableCheckboxConfig"
|
|
83
|
+
:radio-config="radioConfig"
|
|
84
|
+
:tree-config="tableTreeConfig"
|
|
85
|
+
:seq-config="tableSeqConfig"
|
|
86
|
+
:expand-config="expandConfig"
|
|
87
|
+
:tooltip-config="tooltipConfig"
|
|
88
|
+
:edit-config="tableEditConfig"
|
|
89
|
+
:valid-config="validConfig"
|
|
90
|
+
:edit-rules="tableEditRules"
|
|
91
|
+
:toolbar-config="toolbarConfig"
|
|
92
|
+
:keyboard-config="keyboardConfig"
|
|
93
|
+
:sort-config="sortConfig"
|
|
94
|
+
:mouse-config="mouseConfig"
|
|
95
|
+
:custom-config="customConfig"
|
|
96
|
+
:export-config="tableExportConfig"
|
|
97
|
+
:print-config="tablePrintConfig"
|
|
98
|
+
:scroll-x="scrollX"
|
|
99
|
+
:scroll-y="scrollY"
|
|
100
|
+
@current-change="onCurrentChange"
|
|
101
|
+
@radio-change="onRadioChange"
|
|
102
|
+
@checkbox-change="onSelectionChange"
|
|
103
|
+
@checkbox-all="onSelectionChange"
|
|
104
|
+
@checkbox-range-end="onSelectionChange"
|
|
105
|
+
@cell-click="onCellClick"
|
|
106
|
+
@cell-dblclick="onCellDblClick"
|
|
107
|
+
@header-cell-click="onHeaderCellClick"
|
|
108
|
+
@sort-change="onSortChange"
|
|
109
|
+
@filter-change="onFilterChange"
|
|
110
|
+
@toggle-row-expand="onToggleRowExpand"
|
|
111
|
+
@toggle-tree-expand="onToggleTreeExpand"
|
|
112
|
+
@edit-closed="onEditClosed"
|
|
113
|
+
@edit-actived="onEditActived"
|
|
114
|
+
@scroll="onScroll"
|
|
115
|
+
@custom="onCustom"
|
|
116
|
+
@toolbar-button-click="onToolbarButtonClick"
|
|
117
|
+
@toolbar-tool-click="onToolbarToolClick"
|
|
118
|
+
@option-click="handleGoptionClick">
|
|
119
|
+
<template v-for="(column, columnIndex) in columnsConfigDefault" :key="columnIndex">
|
|
120
|
+
<vxe-column v-if="!!tableGlobalConfig[column.type]" v-bind="column"></vxe-column>
|
|
121
|
+
</template>
|
|
122
|
+
<template v-for="(column, columnIndex) in columns" :key="columnIndex">
|
|
123
|
+
<sh-column :column="column"></sh-column>
|
|
124
|
+
</template>
|
|
125
|
+
<template #empty>
|
|
126
|
+
<sh-empty :icon="emptyIcon" :content="emptyText"></sh-empty>
|
|
127
|
+
</template>
|
|
128
|
+
<template v-for="slot in tableSlots" #[slot]="scope">
|
|
129
|
+
<!-- 以之前的名字命名插槽,同时把数据原样绑定 -->
|
|
130
|
+
<slot :name="slot" v-bind="scope"></slot>
|
|
131
|
+
</template>
|
|
132
|
+
</vxe-table>
|
|
133
|
+
<div v-if="isFootSlot" ref="footSlotRef" v-resize="handleResize" class="sh-table-foot"><slot name="foot"></slot></div>
|
|
134
|
+
<div v-if="isPagerSlot" ref="pagerSlotRef" v-resize="handleResize" class="sh-table-pager">
|
|
135
|
+
<vxe-pager ref="pagerSlotRef" v-bind="tablePagerConfig" @page-change="onPageChange">
|
|
136
|
+
<template #pagerLeft>
|
|
137
|
+
<div v-if="selectionRows.length" class="sh-table-footer-info">
|
|
138
|
+
已选择 <strong>{{ selectionRows.length }}</strong> 项
|
|
139
|
+
</div>
|
|
140
|
+
<slot name="pagerLeft"></slot>
|
|
141
|
+
</template>
|
|
142
|
+
<template #pagerRight>
|
|
143
|
+
<slot name="pagerRight"></slot>
|
|
144
|
+
</template>
|
|
145
|
+
</vxe-pager>
|
|
146
|
+
</div>
|
|
147
|
+
<div v-if="isBottomSlot" ref="bottomSlotRef" v-resize="handleResize" class="sh-table-bottom"><slot name="bottom"></slot></div>
|
|
148
|
+
<!--导入弹窗-->
|
|
149
|
+
<importModal
|
|
150
|
+
v-if="importVisible"
|
|
151
|
+
v-model:visible="importVisible"
|
|
152
|
+
need-validate
|
|
153
|
+
:columns="columns"
|
|
154
|
+
:import-config="importConfig"
|
|
155
|
+
:import-rules="tableEditRules"
|
|
156
|
+
@confirm="setImportData"></importModal>
|
|
157
|
+
</div>
|
|
158
|
+
</template>
|
|
159
|
+
|
|
160
|
+
<script>
|
|
161
|
+
import { computed, defineComponent, getCurrentInstance, provide, ref } from 'vue'
|
|
162
|
+
import './css/index.scss'
|
|
163
|
+
|
|
164
|
+
import props from './js/props'
|
|
165
|
+
import shColumn from './components/sh-column.vue'
|
|
166
|
+
import importModal from './components/importModal.vue'
|
|
167
|
+
import useTable from './js/useTable'
|
|
168
|
+
import { turnColumnItemFilters } from './js/tableMethods'
|
|
169
|
+
export default defineComponent({
|
|
170
|
+
name: 'ShTable',
|
|
171
|
+
components: {
|
|
172
|
+
shColumn,
|
|
173
|
+
importModal
|
|
174
|
+
},
|
|
175
|
+
props: {
|
|
176
|
+
...props
|
|
177
|
+
},
|
|
178
|
+
emits: [
|
|
179
|
+
'current-change',
|
|
180
|
+
'radio-change',
|
|
181
|
+
'selection-change',
|
|
182
|
+
'cell-click',
|
|
183
|
+
'cell-dblclick',
|
|
184
|
+
'header-cell-click',
|
|
185
|
+
'sort-change',
|
|
186
|
+
'filter-change',
|
|
187
|
+
'toggle-row-expand',
|
|
188
|
+
'toggle-tree-expand',
|
|
189
|
+
'edit-closed',
|
|
190
|
+
'edit-actived',
|
|
191
|
+
'scroll',
|
|
192
|
+
'custom',
|
|
193
|
+
'page-change',
|
|
194
|
+
'toolbar-button-click',
|
|
195
|
+
'toolbar-tool-click',
|
|
196
|
+
|
|
197
|
+
'form-submit',
|
|
198
|
+
'form-reset',
|
|
199
|
+
'form-edit-closed',
|
|
200
|
+
'form-submit-invalid',
|
|
201
|
+
'import-confirm',
|
|
202
|
+
'globaloption',
|
|
203
|
+
'toolbaroption'
|
|
204
|
+
],
|
|
205
|
+
setup(props, context) {
|
|
206
|
+
const { proxy } = getCurrentInstance()
|
|
207
|
+
const { emit, slots } = context
|
|
208
|
+
const tableWrapRef = ref()
|
|
209
|
+
const topSlotRef = ref()
|
|
210
|
+
const formSlotRef = ref()
|
|
211
|
+
const toolbarSlotRef = ref()
|
|
212
|
+
const headSlotRef = ref()
|
|
213
|
+
const footSlotRef = ref()
|
|
214
|
+
const pagerSlotRef = ref()
|
|
215
|
+
const bottomSlotRef = ref()
|
|
216
|
+
const tableHeight = ref(props.height)
|
|
217
|
+
|
|
218
|
+
const useTableHooks = useTable(props, context, proxy)
|
|
219
|
+
|
|
220
|
+
const isTopSlot = computed(() => Boolean(slots.top))
|
|
221
|
+
const isFormSlot = computed(() => useTableHooks.tableGlobalConfig.value.search || Boolean(slots.form))
|
|
222
|
+
const isToolbarSlot = computed(() => {
|
|
223
|
+
const { title, globalFilter } = useTableHooks.tableGlobalConfig.value
|
|
224
|
+
return title || globalFilter || slots.toolbar || slots.toolbarLeft || slots.toolbarRight || useTableHooks.tableTools.value.length
|
|
225
|
+
})
|
|
226
|
+
const isHeadSlot = computed(() => Boolean(slots.head))
|
|
227
|
+
const isFootSlot = computed(() => Boolean(slots.foot))
|
|
228
|
+
const isPagerSlot = computed(() => useTableHooks.tablePagerConfig.value.enabled)
|
|
229
|
+
const isBottomSlot = computed(() => Boolean(slots.bottom))
|
|
230
|
+
|
|
231
|
+
provide('ShTableInstance', {
|
|
232
|
+
columnObjConfig: useTableHooks.tableColumnObjConfig,
|
|
233
|
+
turnColumnItemFilters: useTableHooks.turnColumnItemFilters
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
const handleResize = e => {
|
|
237
|
+
if (useTableHooks.wrapHeight.value === 'auto') return
|
|
238
|
+
let slotRefs = [topSlotRef, formSlotRef, toolbarSlotRef, headSlotRef, footSlotRef, pagerSlotRef, bottomSlotRef]
|
|
239
|
+
let otherHeight = 0
|
|
240
|
+
let parentHeight = tableWrapRef.value?.offsetHeight
|
|
241
|
+
slotRefs.forEach(slotRef => {
|
|
242
|
+
otherHeight += slotRef.value?.offsetHeight || 0
|
|
243
|
+
})
|
|
244
|
+
tableHeight.value = parentHeight - otherHeight
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
...useTableHooks,
|
|
249
|
+
tableWrapRef,
|
|
250
|
+
topSlotRef,
|
|
251
|
+
formSlotRef,
|
|
252
|
+
toolbarSlotRef,
|
|
253
|
+
headSlotRef,
|
|
254
|
+
footSlotRef,
|
|
255
|
+
pagerSlotRef,
|
|
256
|
+
bottomSlotRef,
|
|
257
|
+
tableHeight,
|
|
258
|
+
isTopSlot,
|
|
259
|
+
isFormSlot,
|
|
260
|
+
isToolbarSlot,
|
|
261
|
+
isHeadSlot,
|
|
262
|
+
isFootSlot,
|
|
263
|
+
isPagerSlot,
|
|
264
|
+
isBottomSlot,
|
|
265
|
+
handleResize
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
</script>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="sh-tabs" :class="{ 'sh-tabs-card': type === 'card' }">
|
|
3
3
|
<div class="sh-tabs-nav">
|
|
4
|
-
<div v-if="
|
|
5
|
-
<div ref="
|
|
4
|
+
<div v-if="slots.left" class="sh-tabs-nav-slot sh-tabs-nav-left"><slot name="left"></slot></div>
|
|
5
|
+
<div ref="navWrapRef" v-resize="handleResize" class="sh-tabs-nav-wrap" :class="{ 'sh-tabs-nav-scrollable': scrollable }">
|
|
6
6
|
<span v-if="scrollable" class="sh-tabs-nav-prev" :class="{ 'sh-tabs-nav-btn-disabled': scrollable }" @click="scrollPrev"><sh-icon type="ios-arrow-back"></sh-icon></span>
|
|
7
|
-
<div ref="
|
|
8
|
-
<div ref="
|
|
7
|
+
<div ref="navScrollRef" class="sh-tabs-nav-scroll" @DOMMouseScroll="handleScroll" @mousewheel="handleScroll">
|
|
8
|
+
<div ref="navRef" v-resize="handleResize" class="sh-tabs-nav-inner" :style="navStyle">
|
|
9
9
|
<template v-for="(tab, tabIndex) in tabList" :key="tabIndex">
|
|
10
10
|
<div class="sh-tab-item" :class="{ 'sh-tab-item-disabled': tab.disabled, 'sh-tab-item-active': tab.value === activeKey }" @click="handleChange(tab)">
|
|
11
11
|
<slot name="tabItem" v-bind="{ ...tab, isActive: tab.value === activeKey }">
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
<span v-if="scrollable" class="sh-tabs-nav-next" :class="{ 'sh-tabs-nav-btn-disabled': scrollable }" @click="scrollNext"><sh-icon type="ios-arrow-forward"></sh-icon></span>
|
|
21
21
|
</div>
|
|
22
|
-
<div v-if="
|
|
22
|
+
<div v-if="slots.right" class="sh-tabs-nav-slot sh-tabs-nav-right"><slot name="right"></slot></div>
|
|
23
23
|
</div>
|
|
24
24
|
<div v-if="hasContent" class="sh-tabs-content">
|
|
25
25
|
<div ref="contentWrap" class="sh-tabs-content-wrap" :class="{ 'sh-tabs-content-animated': animated }" :style="contentStyle">
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
36
|
<script>
|
|
37
|
-
|
|
37
|
+
import { defineComponent, computed, getCurrentInstance, ref, watch, onBeforeMount } from 'vue'
|
|
38
|
+
export default defineComponent({
|
|
38
39
|
name: 'ShTabs',
|
|
39
40
|
props: {
|
|
40
41
|
modelValue: {
|
|
@@ -72,89 +73,73 @@ export default {
|
|
|
72
73
|
}
|
|
73
74
|
},
|
|
74
75
|
emits: ['update:modelValue', 'close', 'change'],
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
76
|
+
setup(props, context) {
|
|
77
|
+
const { proxy } = getCurrentInstance()
|
|
78
|
+
const { $vUtils } = proxy
|
|
79
|
+
const { emit, slots } = context
|
|
80
|
+
|
|
81
|
+
const navRef = ref()
|
|
82
|
+
const navWrapRef = ref()
|
|
83
|
+
const navScrollRef = ref()
|
|
84
|
+
const contentWrapRef = ref()
|
|
85
|
+
const activeKey = ref(props.modelValue)
|
|
86
|
+
const scrollable = ref(false)
|
|
87
|
+
const closedList = ref([])
|
|
88
|
+
const navStyle = ref({ transform: '' })
|
|
89
|
+
|
|
90
|
+
const hasContent = computed(() => props.isContent && activeKey.value && props.options.map(item => item.value).includes(activeKey.value))
|
|
91
|
+
const tabList = computed(() => props.options.filter(tab => !closedList.value.includes(tab.value)) || [])
|
|
92
|
+
const contentStyle = computed(() => {
|
|
93
|
+
const x = tabList.value.findIndex(tab => tab.value === activeKey.value)
|
|
92
94
|
const p = x === 0 ? '0%' : `-${x}00%`
|
|
93
95
|
let style = {}
|
|
94
96
|
if (x > -1) {
|
|
95
|
-
style = {
|
|
96
|
-
transform: `translateX(${p}) translateZ(0px)`
|
|
97
|
-
}
|
|
97
|
+
style = { transform: `translateX(${p}) translateZ(0px)` }
|
|
98
98
|
}
|
|
99
99
|
return style
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
106
|
-
activeKey(val) {
|
|
107
|
-
this.$emit('update:modelValue', val)
|
|
108
|
-
},
|
|
109
|
-
options() {
|
|
110
|
-
this.closedList = []
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
mounted() {},
|
|
114
|
-
beforeUnmount() {},
|
|
115
|
-
methods: {
|
|
116
|
-
scrollPrev() {
|
|
117
|
-
const containerWidth = this.$refs.navScroll.offsetWidth
|
|
118
|
-
const currentOffset = this.getCurrentScrollOffset()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
const scrollPrev = () => {
|
|
103
|
+
const containerWidth = navScrollRef.value.offsetWidth
|
|
104
|
+
const currentOffset = getCurrentScrollOffset()
|
|
119
105
|
if (!currentOffset) return
|
|
120
106
|
let newOffset = currentOffset > containerWidth ? currentOffset - containerWidth : 0
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
scrollNext() {
|
|
124
|
-
const navWidth =
|
|
125
|
-
const containerWidth =
|
|
126
|
-
const currentOffset =
|
|
107
|
+
setOffset(newOffset)
|
|
108
|
+
}
|
|
109
|
+
const scrollNext = () => {
|
|
110
|
+
const navWidth = navRef.value.offsetWidth
|
|
111
|
+
const containerWidth = navScrollRef.value.offsetWidth
|
|
112
|
+
const currentOffset = getCurrentScrollOffset()
|
|
127
113
|
if (navWidth - currentOffset <= containerWidth) return
|
|
128
114
|
let newOffset = navWidth - currentOffset > containerWidth * 2 ? currentOffset + containerWidth : navWidth - containerWidth
|
|
129
|
-
|
|
130
|
-
}
|
|
131
|
-
setOffset
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
getCurrentScrollOffset() {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
const
|
|
144
|
-
const currentOffset = this.getCurrentScrollOffset()
|
|
115
|
+
setOffset(newOffset)
|
|
116
|
+
}
|
|
117
|
+
const setOffset = value => {
|
|
118
|
+
navStyle.value.transform = `translateX(-${value}px)`
|
|
119
|
+
}
|
|
120
|
+
const getCurrentScrollOffset = () => {
|
|
121
|
+
return navStyle.value.transform ? Number(navStyle.value.transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1]) : 0
|
|
122
|
+
}
|
|
123
|
+
const getTabIsClosable = tab => {
|
|
124
|
+
return props.closable && !tab.disabled && !tab.unClosed
|
|
125
|
+
}
|
|
126
|
+
const handleResize = e => {
|
|
127
|
+
const navWidth = navRef.value.offsetWidth
|
|
128
|
+
const containerWidth = navScrollRef.value.offsetWidth
|
|
129
|
+
const currentOffset = getCurrentScrollOffset()
|
|
145
130
|
if (containerWidth < navWidth) {
|
|
146
|
-
|
|
131
|
+
scrollable.value = true
|
|
147
132
|
if (navWidth - currentOffset < containerWidth) {
|
|
148
|
-
|
|
133
|
+
setOffset(navWidth - containerWidth)
|
|
149
134
|
}
|
|
150
135
|
} else {
|
|
151
|
-
|
|
136
|
+
scrollable.value = false
|
|
152
137
|
if (currentOffset > 0) {
|
|
153
|
-
|
|
138
|
+
setOffset(0)
|
|
154
139
|
}
|
|
155
140
|
}
|
|
156
|
-
}
|
|
157
|
-
handleScroll
|
|
141
|
+
}
|
|
142
|
+
const handleScroll = e => {
|
|
158
143
|
e.preventDefault()
|
|
159
144
|
e.stopPropagation()
|
|
160
145
|
let delta = 0
|
|
@@ -162,20 +147,20 @@ export default {
|
|
|
162
147
|
delta = e.wheelDelta ? e.wheelDelta : -(e.detail || 0) * 40
|
|
163
148
|
}
|
|
164
149
|
if (delta > 0) {
|
|
165
|
-
|
|
150
|
+
scrollPrev()
|
|
166
151
|
} else {
|
|
167
|
-
|
|
152
|
+
scrollNext()
|
|
168
153
|
}
|
|
169
|
-
}
|
|
170
|
-
handleChange
|
|
154
|
+
}
|
|
155
|
+
const handleChange = tab => {
|
|
171
156
|
if (!tab || tab.disabled) return
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (!
|
|
175
|
-
const navWidth =
|
|
176
|
-
const containerWidth =
|
|
177
|
-
const prevTabs =
|
|
178
|
-
const tabIndex =
|
|
157
|
+
activeKey.value = tab.value
|
|
158
|
+
emit('change', tab)
|
|
159
|
+
if (!scrollable.value) return
|
|
160
|
+
const navWidth = navRef.value.offsetWidth
|
|
161
|
+
const containerWidth = navScrollRef.value.offsetWidth
|
|
162
|
+
const prevTabs = navRef.value.querySelectorAll('.sh-tab-item')
|
|
163
|
+
const tabIndex = tabList.value.findIndex(tb => tb.value === tab.value)
|
|
179
164
|
let barOffset = 0
|
|
180
165
|
if (tabIndex > 0) {
|
|
181
166
|
const gutter = 5
|
|
@@ -186,18 +171,58 @@ export default {
|
|
|
186
171
|
barOffset = offset
|
|
187
172
|
}
|
|
188
173
|
let navOffset = navWidth - barOffset < containerWidth ? navWidth - containerWidth : barOffset
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
handleClose
|
|
192
|
-
|
|
193
|
-
if (tab.value ===
|
|
194
|
-
let isNotDisabledList =
|
|
195
|
-
|
|
174
|
+
setOffset(navOffset)
|
|
175
|
+
}
|
|
176
|
+
const handleClose = tab => {
|
|
177
|
+
closedList.value.push(tab.value)
|
|
178
|
+
if (tab.value === activeKey.value) {
|
|
179
|
+
let isNotDisabledList = tabList.value.filter(tab => !tab.disabled)
|
|
180
|
+
activeKey.value = isNotDisabledList.length ? isNotDisabledList[0].value : ''
|
|
196
181
|
}
|
|
197
|
-
|
|
182
|
+
emit('close', tab)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
watch(
|
|
186
|
+
() => props.modelValue,
|
|
187
|
+
value => {
|
|
188
|
+
activeKey.value = value
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
watch(
|
|
192
|
+
() => activeKey.value,
|
|
193
|
+
value => {
|
|
194
|
+
emit('update:modelValue', value)
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
watch(
|
|
198
|
+
() => props.options,
|
|
199
|
+
value => {
|
|
200
|
+
closedList.value = []
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
navRef,
|
|
206
|
+
navWrapRef,
|
|
207
|
+
navScrollRef,
|
|
208
|
+
contentWrapRef,
|
|
209
|
+
slots,
|
|
210
|
+
scrollable,
|
|
211
|
+
navStyle,
|
|
212
|
+
tabList,
|
|
213
|
+
activeKey,
|
|
214
|
+
hasContent,
|
|
215
|
+
contentStyle,
|
|
216
|
+
scrollPrev,
|
|
217
|
+
scrollNext,
|
|
218
|
+
handleScroll,
|
|
219
|
+
handleResize,
|
|
220
|
+
handleChange,
|
|
221
|
+
handleClose,
|
|
222
|
+
getTabIsClosable
|
|
198
223
|
}
|
|
199
224
|
}
|
|
200
|
-
}
|
|
225
|
+
})
|
|
201
226
|
</script>
|
|
202
227
|
|
|
203
228
|
<style scoped lang="scss">
|