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.
Files changed (128) hide show
  1. package/package.json +9 -13
  2. package/packages/components/global-components/sh-alert/index.vue +175 -173
  3. package/packages/components/global-components/sh-badge/index.vue +57 -43
  4. package/packages/components/global-components/sh-card/index.vue +24 -16
  5. package/packages/components/global-components/sh-code-editor/index.vue +250 -260
  6. package/packages/components/global-components/sh-col/index.vue +44 -36
  7. package/packages/components/global-components/sh-corner/index.vue +230 -228
  8. package/packages/components/global-components/sh-count-to/index.vue +60 -51
  9. package/packages/components/global-components/sh-drawer/index.vue +209 -182
  10. package/packages/components/global-components/sh-drawer/scrollbar.js +44 -42
  11. package/packages/components/global-components/sh-empty/index.vue +0 -1
  12. package/packages/components/global-components/sh-form/form.vue +110 -0
  13. package/packages/components/global-components/sh-form/js/props.js +76 -63
  14. package/packages/components/global-components/sh-form/js/useForm.js +236 -0
  15. package/packages/components/global-components/sh-form/query.vue +70 -0
  16. package/packages/components/global-components/sh-header/index.vue +35 -50
  17. package/packages/components/global-components/sh-icon/css/index.scss +44 -0
  18. package/packages/components/global-components/sh-icon/index.vue +24 -11
  19. package/packages/components/global-components/sh-image/index.vue +47 -38
  20. package/packages/components/global-components/sh-list/index.vue +42 -37
  21. package/packages/components/global-components/sh-loading/index.vue +12 -8
  22. package/packages/components/global-components/sh-modal/index.vue +49 -40
  23. package/packages/components/global-components/sh-noticebar/index.vue +68 -54
  24. package/packages/components/global-components/sh-poptip/index.vue +247 -130
  25. package/packages/components/global-components/sh-progress/index.vue +71 -69
  26. package/packages/components/global-components/sh-pull-refresh/index.vue +156 -157
  27. package/packages/components/global-components/sh-result/index.vue +37 -28
  28. package/packages/components/global-components/sh-row/index.vue +21 -18
  29. package/packages/components/global-components/sh-split/index.vue +115 -109
  30. package/packages/components/global-components/sh-table/components/importModal.vue +95 -86
  31. package/packages/components/global-components/sh-table/components/sh-column.vue +54 -0
  32. package/packages/components/global-components/sh-table/{index.vue → grid.vue} +34 -145
  33. package/packages/components/global-components/sh-table/js/tableMethods.js +175 -0
  34. package/packages/components/global-components/sh-table/js/useTable.js +592 -0
  35. package/packages/components/global-components/sh-table/table.vue +269 -0
  36. package/packages/components/global-components/sh-tabs/index.vue +118 -93
  37. package/packages/components/global-components/sh-tag/index.vue +52 -51
  38. package/packages/components/global-components/sh-toolbar/index.vue +53 -47
  39. package/packages/components/global-components/sh-tree/components/table-tree.vue +152 -139
  40. package/packages/components/global-components/sh-tree/index.vue +218 -195
  41. package/packages/components/global-components/sh-tree/mixin/treeProps.js +118 -120
  42. package/packages/components/global-components/sh-upload/index.vue +308 -51
  43. package/packages/components/global-components/sh-water-fall/index.vue +4 -11
  44. package/packages/components/index.js +5 -3
  45. package/packages/components/other-components/sh-cron-modal/components/cron-content.vue +140 -129
  46. package/packages/components/other-components/sh-cron-modal/css/index.scss +0 -5
  47. package/packages/components/other-components/sh-cron-modal/index.vue +81 -67
  48. package/packages/components/other-components/sh-cron-modal/mixin/cron-emits.js +1 -0
  49. package/packages/components/other-components/sh-cron-modal/mixin/cron-hooks.js +179 -0
  50. package/packages/components/other-components/sh-cron-modal/mixin/cron-props.js +9 -0
  51. package/packages/components/other-components/sh-cron-modal/tabs/cron-day-box.vue +101 -92
  52. package/packages/components/other-components/sh-cron-modal/tabs/cron-hour-box.vue +68 -56
  53. package/packages/components/other-components/sh-cron-modal/tabs/cron-minute-box.vue +68 -56
  54. package/packages/components/other-components/sh-cron-modal/tabs/cron-month-box.vue +68 -56
  55. package/packages/components/other-components/sh-cron-modal/tabs/cron-second-box.vue +68 -56
  56. package/packages/components/other-components/sh-cron-modal/tabs/cron-week-box.vue +126 -115
  57. package/packages/components/other-components/sh-cron-modal/tabs/cron-year-box.vue +59 -46
  58. package/packages/components/other-components/sh-menu/index.vue +73 -60
  59. package/packages/components/other-components/sh-menu/menu-group-content.vue +71 -59
  60. package/packages/components/other-components/sh-menu/menu-item-content.vue +40 -30
  61. package/packages/components/other-components/sh-menu-card/index.vue +70 -64
  62. package/packages/components/other-components/sh-menu-card/menu-box.vue +50 -44
  63. package/packages/components/other-components/sh-preview/components/sh-excel.vue +182 -0
  64. package/packages/components/other-components/sh-preview/components/sh-word.vue +73 -0
  65. package/packages/components/other-components/sh-preview/index.vue +86 -85
  66. package/packages/components/other-components/sh-preview/js/data-hook.js +37 -0
  67. package/packages/components/other-components/sh-preview/js/data-props.js +11 -0
  68. package/packages/components/other-components/sh-system-tip/index.vue +28 -24
  69. package/packages/css/index.js +4 -4
  70. package/packages/directive/module/prevent-click.js +1 -1
  71. package/packages/directive/module/resize.js +11 -154
  72. package/packages/index.js +39 -39
  73. package/packages/mixin/index.js +86 -87
  74. package/packages/vxeTable/render/cell/vxe-render-checkbox.vue +14 -5
  75. package/packages/vxeTable/render/cell/vxe-render-checkgroup.vue +43 -36
  76. package/packages/vxeTable/render/cell/vxe-render-code.vue +14 -5
  77. package/packages/vxeTable/render/cell/vxe-render-goption.vue +34 -24
  78. package/packages/vxeTable/render/cell/vxe-render-href.vue +21 -11
  79. package/packages/vxeTable/render/cell/vxe-render-img.vue +16 -10
  80. package/packages/vxeTable/render/cell/vxe-render-input.vue +83 -79
  81. package/packages/vxeTable/render/cell/vxe-render-money.vue +14 -6
  82. package/packages/vxeTable/render/cell/vxe-render-progress.vue +28 -19
  83. package/packages/vxeTable/render/cell/vxe-render-radio.vue +14 -5
  84. package/packages/vxeTable/render/cell/vxe-render-radiogroup.vue +43 -36
  85. package/packages/vxeTable/render/cell/vxe-render-select.vue +44 -36
  86. package/packages/vxeTable/render/cell/vxe-render-switch.vue +14 -5
  87. package/packages/vxeTable/render/cell/vxe-render-table.vue +51 -78
  88. package/packages/vxeTable/render/cell/vxe-render-textarea.vue +14 -5
  89. package/packages/vxeTable/render/cell/vxe-render-time.vue +23 -13
  90. package/packages/vxeTable/render/cell/vxe-render-tree.vue +23 -27
  91. package/packages/vxeTable/render/cell/vxe-render-upload.vue +11 -7
  92. package/packages/vxeTable/render/filters/vxe-filter-input.vue +25 -43
  93. package/packages/vxeTable/render/footer/vxe-footer-input.vue +23 -13
  94. package/packages/vxeTable/render/footer/vxe-footer-money.vue +30 -20
  95. package/packages/vxeTable/render/globalRenders.jsx +1 -1
  96. package/packages/vxeTable/render/header/vxe-header-money.vue +31 -21
  97. package/packages/vxeTable/render/mixin/cell-hooks.js +162 -0
  98. package/packages/vxeTable/render/mixin/cell-props.js +23 -0
  99. package/packages/vxeTable/render/mixin/filter-hooks.js +28 -0
  100. package/packages/components/global-components/sh-form/components/form-item.vue +0 -25
  101. package/packages/components/global-components/sh-form/css/index.scss +0 -55
  102. package/packages/components/global-components/sh-form/index.vue +0 -114
  103. package/packages/components/global-components/sh-form/js/methods.js +0 -146
  104. package/packages/components/global-components/sh-form/mixin/defaultData.js +0 -32
  105. package/packages/components/global-components/sh-icon/css/default/index.scss +0 -27
  106. package/packages/components/global-components/sh-icon/css/font/index.scss +0 -16
  107. package/packages/components/global-components/sh-icon/icon-default.vue +0 -32
  108. package/packages/components/global-components/sh-icon/icon-font.vue +0 -32
  109. package/packages/components/global-components/sh-poptip/popper.js +0 -115
  110. package/packages/components/global-components/sh-query/index.vue +0 -317
  111. package/packages/components/global-components/sh-table/js/methods.js +0 -549
  112. package/packages/components/global-components/sh-table/mixin/defaultData.js +0 -94
  113. package/packages/components/global-components/sh-upload/js/mixin.js +0 -257
  114. package/packages/components/other-components/sh-cron-modal/mixin/cron-box.js +0 -169
  115. package/packages/vxeTable/render/mixin/cell-mixin.js +0 -195
  116. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.svg → ionicons.svg} +0 -0
  117. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.ttf → ionicons.ttf} +0 -0
  118. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff → ionicons.woff} +0 -0
  119. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff2 → ionicons.woff2} +0 -0
  120. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.js → iconfont.js} +0 -0
  121. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.json → iconfont.json} +0 -0
  122. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.ttf → iconfont.ttf} +0 -0
  123. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff → iconfont.woff} +0 -0
  124. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff2 → iconfont.woff2} +0 -0
  125. /package/packages/{assets/css → css}/animated.scss +0 -0
  126. /package/packages/{assets/css → css}/loader.scss +0 -0
  127. /package/packages/{assets/css → css}/main.scss +0 -0
  128. /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="$slots.left" class="sh-tabs-nav-slot sh-tabs-nav-left"><slot name="left"></slot></div>
5
- <div ref="navWrap" v-resize="handleResize" class="sh-tabs-nav-wrap" :class="{ 'sh-tabs-nav-scrollable': scrollable }">
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="navScroll" class="sh-tabs-nav-scroll" @DOMMouseScroll="handleScroll" @mousewheel="handleScroll">
8
- <div ref="nav" v-resize="handleResize" class="sh-tabs-nav-inner" :style="navStyle">
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="$slots.right" class="sh-tabs-nav-slot sh-tabs-nav-right"><slot name="right"></slot></div>
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
- export default {
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
- data() {
76
- return {
77
- activeKey: this.modelValue,
78
- scrollable: false,
79
- closedList: [],
80
- navStyle: { transform: '' }
81
- }
82
- },
83
- computed: {
84
- hasContent() {
85
- return this.isContent && this.activeKey && this.options.map(item => item.value).includes(this.activeKey)
86
- },
87
- tabList() {
88
- return this.options.filter(tab => !this.closedList.includes(tab.value)) || []
89
- },
90
- contentStyle() {
91
- const x = this.tabList.findIndex(tab => tab.value === this.activeKey)
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
- watch: {
103
- modelValue(val) {
104
- this.activeKey = val
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
- this.setOffset(newOffset)
122
- },
123
- scrollNext() {
124
- const navWidth = this.$refs.nav.offsetWidth
125
- const containerWidth = this.$refs.navScroll.offsetWidth
126
- const currentOffset = this.getCurrentScrollOffset()
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
- this.setOffset(newOffset)
130
- },
131
- setOffset(value) {
132
- this.navStyle.transform = `translateX(-${value}px)`
133
- },
134
- getCurrentScrollOffset() {
135
- const { navStyle } = this
136
- return navStyle.transform ? Number(navStyle.transform.match(/translateX\(-(\d+(\.\d+)*)px\)/)[1]) : 0
137
- },
138
- getTabIsClosable(tab) {
139
- return this.closable && !tab.disabled && !tab.unClosed
140
- },
141
- handleResize(e) {
142
- const navWidth = this.$refs.nav.offsetWidth
143
- const containerWidth = this.$refs.navScroll.offsetWidth
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
- this.scrollable = true
131
+ scrollable.value = true
147
132
  if (navWidth - currentOffset < containerWidth) {
148
- this.setOffset(navWidth - containerWidth)
133
+ setOffset(navWidth - containerWidth)
149
134
  }
150
135
  } else {
151
- this.scrollable = false
136
+ scrollable.value = false
152
137
  if (currentOffset > 0) {
153
- this.setOffset(0)
138
+ setOffset(0)
154
139
  }
155
140
  }
156
- },
157
- handleScroll(e) {
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
- this.scrollPrev()
150
+ scrollPrev()
166
151
  } else {
167
- this.scrollNext()
152
+ scrollNext()
168
153
  }
169
- },
170
- handleChange(tab) {
154
+ }
155
+ const handleChange = tab => {
171
156
  if (!tab || tab.disabled) return
172
- this.activeKey = tab.value
173
- this.$emit('change', tab)
174
- if (!this.scrollable) return
175
- const navWidth = this.$refs.nav.offsetWidth
176
- const containerWidth = this.$refs.navScroll.offsetWidth
177
- const prevTabs = this.$refs.nav.querySelectorAll('.sh-tab-item')
178
- const tabIndex = this.tabList.findIndex(tb => tb.value === tab.value)
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
- this.setOffset(navOffset)
190
- },
191
- handleClose(tab) {
192
- this.closedList.push(tab.value)
193
- if (tab.value === this.activeKey) {
194
- let isNotDisabledList = this.tabList.filter(tab => !tab.disabled)
195
- this.activeKey = isNotDisabledList.length ? isNotDisabledList[0].value : ''
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
- this.$emit('close', tab)
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">