sh-view 2.0.8 → 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 (129) 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 +216 -183
  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 +294 -287
  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 +75 -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 +71 -61
  61. package/packages/components/other-components/sh-menu-card/index.vue +81 -59
  62. package/packages/components/other-components/sh-menu-card/menu-box.vue +87 -68
  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 +115 -113
  69. package/packages/css/index.js +4 -4
  70. package/packages/{assets/css → css}/main.scss +2 -50
  71. package/packages/{assets/css → css}/theme.scss +35 -16
  72. package/packages/directive/module/prevent-click.js +1 -1
  73. package/packages/directive/module/resize.js +11 -154
  74. package/packages/index.js +39 -39
  75. package/packages/mixin/index.js +86 -87
  76. package/packages/vxeTable/css/index.scss +3 -0
  77. package/packages/vxeTable/render/cell/vxe-render-checkbox.vue +14 -5
  78. package/packages/vxeTable/render/cell/vxe-render-checkgroup.vue +43 -36
  79. package/packages/vxeTable/render/cell/vxe-render-code.vue +14 -5
  80. package/packages/vxeTable/render/cell/vxe-render-goption.vue +34 -24
  81. package/packages/vxeTable/render/cell/vxe-render-href.vue +21 -11
  82. package/packages/vxeTable/render/cell/vxe-render-img.vue +16 -10
  83. package/packages/vxeTable/render/cell/vxe-render-input.vue +83 -67
  84. package/packages/vxeTable/render/cell/vxe-render-money.vue +14 -6
  85. package/packages/vxeTable/render/cell/vxe-render-progress.vue +28 -19
  86. package/packages/vxeTable/render/cell/vxe-render-radio.vue +14 -5
  87. package/packages/vxeTable/render/cell/vxe-render-radiogroup.vue +43 -36
  88. package/packages/vxeTable/render/cell/vxe-render-select.vue +44 -36
  89. package/packages/vxeTable/render/cell/vxe-render-switch.vue +14 -5
  90. package/packages/vxeTable/render/cell/vxe-render-table.vue +51 -78
  91. package/packages/vxeTable/render/cell/vxe-render-textarea.vue +14 -5
  92. package/packages/vxeTable/render/cell/vxe-render-time.vue +23 -13
  93. package/packages/vxeTable/render/cell/vxe-render-tree.vue +23 -27
  94. package/packages/vxeTable/render/cell/vxe-render-upload.vue +11 -7
  95. package/packages/vxeTable/render/filters/vxe-filter-input.vue +25 -43
  96. package/packages/vxeTable/render/footer/vxe-footer-input.vue +23 -13
  97. package/packages/vxeTable/render/footer/vxe-footer-money.vue +30 -20
  98. package/packages/vxeTable/render/globalRenders.jsx +1 -1
  99. package/packages/vxeTable/render/header/vxe-header-money.vue +31 -21
  100. package/packages/vxeTable/render/mixin/cell-hooks.js +162 -0
  101. package/packages/vxeTable/render/mixin/cell-props.js +23 -0
  102. package/packages/vxeTable/render/mixin/filter-hooks.js +28 -0
  103. package/packages/components/global-components/sh-form/components/form-item.vue +0 -25
  104. package/packages/components/global-components/sh-form/css/index.scss +0 -55
  105. package/packages/components/global-components/sh-form/index.vue +0 -114
  106. package/packages/components/global-components/sh-form/js/methods.js +0 -146
  107. package/packages/components/global-components/sh-form/mixin/defaultData.js +0 -32
  108. package/packages/components/global-components/sh-icon/css/default/index.scss +0 -27
  109. package/packages/components/global-components/sh-icon/css/font/index.scss +0 -16
  110. package/packages/components/global-components/sh-icon/icon-default.vue +0 -32
  111. package/packages/components/global-components/sh-icon/icon-font.vue +0 -32
  112. package/packages/components/global-components/sh-poptip/popper.js +0 -115
  113. package/packages/components/global-components/sh-query/index.vue +0 -317
  114. package/packages/components/global-components/sh-table/js/methods.js +0 -549
  115. package/packages/components/global-components/sh-table/mixin/defaultData.js +0 -94
  116. package/packages/components/global-components/sh-upload/js/mixin.js +0 -257
  117. package/packages/components/other-components/sh-cron-modal/mixin/cron-box.js +0 -169
  118. package/packages/vxeTable/render/mixin/cell-mixin.js +0 -206
  119. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.svg → ionicons.svg} +0 -0
  120. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.ttf → ionicons.ttf} +0 -0
  121. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff → ionicons.woff} +0 -0
  122. /package/packages/components/global-components/sh-icon/css/default/{fonts/ionicons.woff2 → ionicons.woff2} +0 -0
  123. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.js → iconfont.js} +0 -0
  124. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.json → iconfont.json} +0 -0
  125. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.ttf → iconfont.ttf} +0 -0
  126. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff → iconfont.woff} +0 -0
  127. /package/packages/components/global-components/sh-icon/css/font/{fonts/iconfont.woff2 → iconfont.woff2} +0 -0
  128. /package/packages/{assets/css → css}/animated.scss +0 -0
  129. /package/packages/{assets/css → css}/loader.scss +0 -0
@@ -2,7 +2,7 @@
2
2
  <sh-row :gutter="10">
3
3
  <template v-for="(menuitem, menuindex) in resetRenderList(list)" :key="menuindex">
4
4
  <sh-col v-bind="colsConfig">
5
- <sh-card :icon="menuitem.icon" size="small" :title="menuitem.meta.title" :icon-size="18" :color="getMenuColor(menuindex)" :padding="8" class="menuCard">
5
+ <sh-card :icon="menuitem.icon" size="small" :title="menuitem?.meta?.title" :icon-size="18" :color="getMenuColor(menuindex)" :padding="8" class="menuCard">
6
6
  <div :ref="`cardBtnsWrap${menuindex}`" class="cardBtnsWrap">
7
7
  <template v-for="cardBtn in menuitem.buttons" :key="cardBtn.value">
8
8
  <template v-if="menuitem.children && menuitem.children.length > 0">
@@ -11,19 +11,18 @@
11
11
  transfer
12
12
  :title="cardBtn.name"
13
13
  :width="poptipWidth"
14
+ :height="poptipHeight"
14
15
  :placement="cardBtn.placement"
15
- @on-popper-show="handleFocusBtn(cardBtn, menuindex)"
16
- @on-popper-hide="handleBlurBtn(cardBtn, menuindex)">
16
+ @popper-show="handleFocusBtn(cardBtn, menuindex)"
17
+ @popper-hide="handleBlurBtn(cardBtn, menuindex)">
17
18
  <div class="cardBtn" :style="getCardStyle(menuindex, cardActive === cardBtn.value + menuindex)" @click="handleCardBtn($event, cardBtn, menuitem, menuindex)">
18
19
  <sh-icon :type="cardBtn.icon" :size="16" class="mr-2" :color="getMenuColor(menuindex, cardActive === cardBtn.value + menuindex)" />
19
20
  <span>{{ cardBtn.name }}</span>
20
21
  <sh-corner v-if="getBudgeNum(menuitem, cardBtn)" v-bind="btnCornerConfig(cardBtn, menuitem, menuindex)"></sh-corner>
21
22
  </div>
22
23
  <template #content>
23
- <div class="cardPoptipContent">
24
- <menuBox v-if="cardActive.startsWith('menus')" :menu="menuitem" first></menuBox>
25
- <sh-empty v-else></sh-empty>
26
- </div>
24
+ <menuBox v-if="cardActive.startsWith('menus')" :menu="menuitem" first></menuBox>
25
+ <sh-empty v-else></sh-empty>
27
26
  </template>
28
27
  </sh-poptip>
29
28
  </template>
@@ -43,8 +42,9 @@
43
42
  </template>
44
43
 
45
44
  <script>
45
+ import { defineComponent, computed, provide, getCurrentInstance, ref, onMounted } from 'vue'
46
46
  import menuBox from './menu-box.vue'
47
- export default {
47
+ export default defineComponent({
48
48
  name: 'MenuCard',
49
49
  components: {
50
50
  menuBox
@@ -83,32 +83,34 @@ export default {
83
83
  { name: '已办事项', value: 'untodo', icon: 'ios-calendar', placement: 'bottom-end' }
84
84
  ]
85
85
  }
86
+ },
87
+ labelField: {
88
+ type: String,
89
+ default: 'label'
90
+ },
91
+ labelFormat: {
92
+ type: Function
86
93
  }
87
94
  },
88
- data() {
89
- return {
90
- poptipWidth: 320,
91
- cardActive: ''
92
- }
93
- },
94
- computed: {
95
- colsConfig() {
96
- return {
97
- xs: { span: 24 },
98
- sm: { span: 24 },
99
- md: { span: 12 },
100
- lg: { span: 8 },
101
- xl: { span: 8 },
102
- xxl: { span: 6 }
103
- }
104
- }
105
- },
106
- methods: {
95
+ emits: ['select'],
96
+ setup(props, context) {
97
+ const { proxy } = getCurrentInstance()
98
+ const { $vUtils } = proxy
99
+ const { emit, slots } = context
100
+
101
+ const poptipWidth = 320
102
+ const poptipHeight = 300
103
+ const cardActive = ref('')
104
+
105
+ const colsConfig = computed(() => {
106
+ return { xs: { span: 24 }, sm: { span: 24 }, md: { span: 12 }, lg: { span: 8 }, xl: { span: 8 }, xxl: { span: 6 } }
107
+ })
108
+
107
109
  // 重新生成卡片列表
108
- resetRenderList(list) {
109
- return this.$vUtils.mapTree(list, item => {
110
+ const resetRenderList = list => {
111
+ return $vUtils.mapTree(list, item => {
110
112
  return {
111
- buttons: this.cardBtns.map(btn => {
113
+ buttons: props.cardBtns.map(btn => {
112
114
  return {
113
115
  visible: false,
114
116
  placement: 'bottom-start',
@@ -118,62 +120,82 @@ export default {
118
120
  ...item
119
121
  }
120
122
  })
121
- },
123
+ }
122
124
  // 动态角标配置
123
- btnCornerConfig(cardBtn, menuitem, menuindex) {
125
+ const btnCornerConfig = (cardBtn, menuitem, menuindex) => {
124
126
  return {
125
- title: this.getBudgeNum(menuitem, cardBtn),
127
+ title: getBudgeNum(menuitem, cardBtn),
126
128
  dark: true,
127
129
  width: '30',
128
130
  height: '30',
129
- color: this.getMenuColor(menuindex)
131
+ color: getMenuColor(menuindex)
130
132
  }
131
- },
132
- getMenuColor(menuindex, active) {
133
- return this.getCardStyle(menuindex, true)[active ? 'color' : 'backgroundColor']
134
- },
135
- getCardStyle(index, active) {
136
- let themeLength = this.menuColors.length
137
- let backgroundColor = this.menuColors[index % themeLength][active ? 'active' : 'default']
133
+ }
134
+ const getMenuColor = (menuindex, active) => {
135
+ return getCardStyle(menuindex, true)[active ? 'color' : 'backgroundColor']
136
+ }
137
+ const getCardStyle = (index, active) => {
138
+ let themeLength = props.menuColors.length
139
+ let backgroundColor = props.menuColors[index % themeLength][active ? 'active' : 'default']
138
140
  let color = active ? '#fff' : ''
139
141
  return { backgroundColor, color }
140
- },
141
- getBudgeNum(menu, card) {
142
+ }
143
+ const getBudgeNum = (menu, card) => {
142
144
  switch (card.value) {
143
145
  case 'menus':
144
- return this.$vUtils.toTreeArray(menu.children || []).length
146
+ return $vUtils.toTreeArray(menu.children || []).length
145
147
  default:
146
148
  return ''
147
149
  }
148
- },
149
- handleCardBtn($event, cardBtn, menu, menuIndex) {
150
+ }
151
+ const handleCardBtn = ($event, cardBtn, menu, menuIndex) => {
150
152
  if (!menu.children || menu.children.length < 1) {
151
153
  cardBtn.visible = false
152
- return this.routerTo(menu)
154
+ onMenuSelect(menu)
155
+ return
153
156
  }
154
157
  let windowWidth = window.document.body.clientWidth
155
158
  let selfOffsetRight = windowWidth - $event.pageX
156
- cardBtn.placement = selfOffsetRight < this.poptipWidth ? 'bottom-end' : 'bottom-start'
159
+ cardBtn.placement = selfOffsetRight < poptipWidth ? 'bottom-end' : 'bottom-start'
157
160
  cardBtn.visible = true
158
- },
159
- handleFocusBtn(card, index) {
160
- this.cardActive = card.value + index
161
- },
162
- handleBlurBtn(card, index) {
163
- if (this.cardActive === card.value + index) this.cardActive = ''
161
+ }
162
+ const handleFocusBtn = (card, index) => {
163
+ cardActive.value = card.value + index
164
+ }
165
+ const handleBlurBtn = (card, index) => {
166
+ if (cardActive.value === card.value + index) cardActive.value = ''
167
+ }
168
+ const onMenuSelect = menu => {
169
+ emit('select', menu)
170
+ }
171
+
172
+ provide('MenuCardInstance', {
173
+ ...props,
174
+ onMenuSelect
175
+ })
176
+
177
+ return {
178
+ cardActive,
179
+ poptipWidth,
180
+ poptipHeight,
181
+ colsConfig,
182
+ resetRenderList,
183
+ btnCornerConfig,
184
+ getMenuColor,
185
+ getCardStyle,
186
+ getBudgeNum,
187
+ handleFocusBtn,
188
+ handleBlurBtn,
189
+ handleCardBtn
164
190
  }
165
191
  }
166
- }
192
+ })
167
193
  </script>
168
194
 
169
195
  <style lang="scss">
170
196
  .menuCard {
171
197
  margin-bottom: 10px;
172
198
  }
173
- .cardPoptipContent {
174
- max-height: 400px;
175
- overflow: auto;
176
- }
177
199
  .cardBtnsWrap {
178
200
  position: relative;
179
201
  display: flex;
@@ -1,68 +1,87 @@
1
- <template>
2
- <div class="menuBoxWrap" :class="{ first }">
3
- <template v-if="menus.length > 0">
4
- <div v-if="first" class="menuBoxFilter">
5
- <vxe-input v-model="filterText" size="mini" class="w-100" clearable placeholder="请输入关键词" prefix-icon="vxe-icon-search"></vxe-input>
6
- </div>
7
- <template v-for="(item, itemindex) in menuBoxList" :key="itemindex">
8
- <a class="menuBoxTitle" @click="routerTo(item)">{{ formatTitle(item) }}</a>
9
- <menuBox v-if="hasChildren(item)" :menu="item"></menuBox>
10
- </template>
11
- </template>
12
- <sh-empty v-else></sh-empty>
13
- </div>
14
- </template>
15
-
16
- <script>
17
- export default {
18
- name: 'MenuBox',
19
- props: {
20
- menu: {
21
- type: [Object, Array],
22
- default() {
23
- return {}
24
- }
25
- },
26
- first: {
27
- type: Boolean
28
- }
29
- },
30
- data() {
31
- return {
32
- filterText: '',
33
- filterData: null,
34
- filterChangeDebounce: this.$vUtils.debounce(this.handleMenuFilter, 500)
35
- }
36
- },
37
- computed: {
38
- menus() {
39
- return Array.isArray(this.menu) ? this.menu : this.menu?.children || []
40
- },
41
- menuBoxList() {
42
- return this.filterData || this.menus
43
- }
44
- },
45
- watch: {
46
- filterText: {
47
- handler(newvalue, oldValue) {
48
- this.filterChangeDebounce(newvalue)
49
- }
50
- }
51
- },
52
- methods: {
53
- // 全局搜索过滤事件
54
- handleMenuFilter(text) {
55
- const that = this
56
- let filterText = that.$vUtils.toValueString(text).trim().toLowerCase()
57
- let filterData = null
58
- if (filterText) {
59
- filterData = that.$vUtils.searchTree(that.menus, menu => this.formatTitle(menu).indexOf(filterText) > -1)
60
- }
61
- if (that.filterData === null && !filterText) {
62
- return
63
- }
64
- that.filterData = filterData
65
- }
66
- }
67
- }
68
- </script>
1
+ <template>
2
+ <div class="menuBoxWrap" :class="{ first }">
3
+ <template v-if="menusList.length > 0">
4
+ <div v-if="first" class="menuBoxFilter">
5
+ <vxe-input v-model="filterText" size="mini" class="w-100" clearable placeholder="请输入关键词" prefix-icon="vxe-icon-search"></vxe-input>
6
+ </div>
7
+ <template v-for="(item, itemindex) in menuBoxList" :key="itemindex">
8
+ <a class="menuBoxTitle" @click="handleMenuClick(item)">{{ getItemTitle(item) }}</a>
9
+ <menuBox v-if="hasChildren(item)" :menu="item"></menuBox>
10
+ </template>
11
+ </template>
12
+ <sh-empty v-else></sh-empty>
13
+ </div>
14
+ </template>
15
+
16
+ <script>
17
+ import { defineComponent, computed, getCurrentInstance, watch, ref, inject } from 'vue'
18
+ export default defineComponent({
19
+ name: 'MenuBox',
20
+ props: {
21
+ menu: {
22
+ type: [Object, Array],
23
+ default() {
24
+ return {}
25
+ }
26
+ },
27
+ first: {
28
+ type: Boolean
29
+ }
30
+ },
31
+ setup(props, context) {
32
+ const { proxy } = getCurrentInstance()
33
+ const { $vUtils } = proxy
34
+ const { emit, slots } = context
35
+ const MenuCardInstance = inject('MenuCardInstance')
36
+
37
+ const filterText = ref('')
38
+ const filterData = ref(null)
39
+
40
+ const menusList = computed(() => {
41
+ return Array.isArray(props.menu) ? props.menu : props.menu?.children || []
42
+ })
43
+ const menuBoxList = computed(() => {
44
+ return filterData.value || menusList.value
45
+ })
46
+
47
+ const hasChildren = menu => {
48
+ return menu && menu.children && Array.isArray(menu.children) && menu.children.length > 0
49
+ }
50
+ const getItemTitle = menu => {
51
+ const { labelField, labelFormat } = MenuCardInstance
52
+ return labelFormat ? labelFormat(menu) : $vUtils.get(menu, labelField) || ''
53
+ }
54
+ const handleMenuClick = item => {
55
+ MenuCardInstance.onMenuSelect(item)
56
+ }
57
+ // 全局搜索过滤事件
58
+ const handleMenuFilter = text => {
59
+ let filterText = $vUtils.toValueString(text).trim().toLowerCase()
60
+ let searchData = null
61
+ if (filterText) {
62
+ searchData = $vUtils.searchTree(menusList.value, menu => getItemTitle(menu).indexOf(filterText) > -1)
63
+ }
64
+ if (filterData.value === null && !filterText) return
65
+ filterData.value = searchData
66
+ }
67
+
68
+ const filterChangeDebounce = $vUtils.debounce(handleMenuFilter, 500)
69
+
70
+ watch(
71
+ () => filterText.value,
72
+ nv => {
73
+ filterChangeDebounce(nv)
74
+ }
75
+ )
76
+
77
+ return {
78
+ menusList,
79
+ filterText,
80
+ menuBoxList,
81
+ getItemTitle,
82
+ hasChildren,
83
+ handleMenuClick
84
+ }
85
+ }
86
+ })
87
+ </script>
@@ -0,0 +1,182 @@
1
+ <script>
2
+ import { defineComponent, computed, getCurrentInstance } from 'vue'
3
+ import dataHook from '../js/data-hook'
4
+ import dataProps from '../js/data-hook'
5
+ import Spreadsheet from 'x-data-spreadsheet'
6
+ import ExcelJS from 'exceljs'
7
+ export default defineComponent({
8
+ name: 'ShOfficeDocx',
9
+ props: dataProps,
10
+ emits: ['rendered', 'error'],
11
+ setup(props, { emit }) {
12
+ const { proxy } = getCurrentInstance()
13
+ const { $vUtils } = proxy
14
+
15
+ let defaultOption = {
16
+ mode: 'read',
17
+ showToolbar: false
18
+ }
19
+
20
+ const excelOptions = computed(() => {
21
+ return Object.assign({}, defaultOption, props.options)
22
+ })
23
+
24
+ const domRender = async (data, container) => {
25
+ if (!data) {
26
+ container.innerHTML = ''
27
+ return Promise.resolve()
28
+ }
29
+ const wb = new ExcelJS.Workbook()
30
+ // 微软的 Excel ColorIndex 一个索引数字对应一个颜色
31
+ let workbook = await wb.xlsx.load(data)
32
+ let workbookData = []
33
+ workbook.eachSheet(sheet => {
34
+ // 构造x-data-spreadsheet 的 sheet 数据源结构
35
+ let sheetData = { name: sheet.name, styles: [], rows: {}, merges: [] }
36
+ // 收集合并单元格信息
37
+ let mergeAddressData = []
38
+ for (let mergeRange in sheet._merges) {
39
+ sheetData.merges.push(sheet._merges[mergeRange].shortRange)
40
+ let mergeAddress = {}
41
+ // 合并单元格起始地址
42
+ mergeAddress.startAddress = sheet._merges[mergeRange].tl
43
+ // 合并单元格终止地址
44
+ mergeAddress.endAddress = sheet._merges[mergeRange].br
45
+ // Y轴方向跨度
46
+ mergeAddress.YRange = sheet._merges[mergeRange].model.bottom - sheet._merges[mergeRange].model.top
47
+ // X轴方向跨度
48
+ mergeAddress.XRange = sheet._merges[mergeRange].model.right - sheet._merges[mergeRange].model.left
49
+ mergeAddressData.push(mergeAddress)
50
+ }
51
+ sheetData.cols = {}
52
+ for (let i = 0; i < sheet.columns.length; i++) {
53
+ sheetData.cols[i.toString()] = {}
54
+ if (sheet.columns[i].width) {
55
+ // 不知道为什么从 exceljs 读取的宽度显示到 x-data-spreadsheet 特别小, 这里乘以8
56
+ sheetData.cols[i.toString()].width = sheet.columns[i].width * 8
57
+ } else {
58
+ // 默认列宽
59
+ sheetData.cols[i.toString()].width = 100
60
+ }
61
+ }
62
+
63
+ // 遍历行
64
+ sheet.eachRow((row, rowIndex) => {
65
+ sheetData.rows[(rowIndex - 1).toString()] = { cells: {} }
66
+ //includeEmpty = false 不包含空白单元格
67
+ row.eachCell({ includeEmpty: true }, function (cell, colNumber) {
68
+ let cellText = ''
69
+ if (cell.value && cell.value.result) {
70
+ // Excel 单元格有公式
71
+ cellText = cell.value.result
72
+ } else if (cell.value && cell.value.richText) {
73
+ // Excel 单元格是多行文本
74
+ for (let text in cell.value.richText) {
75
+ // 多行文本做累加
76
+ cellText += cell.value.richText[text].text
77
+ }
78
+ } else {
79
+ // Excel 单元格无公式
80
+ cellText = cell.value
81
+ }
82
+ //解析单元格,包含样式
83
+ //*********************单元格存在背景色******************************
84
+ // 单元格存在背景色
85
+ let backGroundColor = null
86
+ if (cell.style.fill && cell.style.fill.fgColor && cell.style.fill.fgColor.argb) {
87
+ // 8位字符颜色先转rgb再转16进制颜色
88
+ backGroundColor = (val => {
89
+ val = val.trim().toLowerCase() //去掉前后空格
90
+ let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
91
+ let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
92
+ let percent = (parseInt(argb[1], 16) / 255) * 100
93
+ return $vUtils.fade(rgb, percent)
94
+ })(cell.style.fill.fgColor.argb)
95
+ }
96
+
97
+ if (backGroundColor) {
98
+ cell.style.bgcolor = backGroundColor
99
+ }
100
+ //*************************************************************************** */
101
+
102
+ //*********************字体存在背景色******************************
103
+ // 字体颜色
104
+ let fontColor = null
105
+ if (cell.style.font && cell.style.font.color && cell.style.font.color.argb) {
106
+ // 8位字符颜色先转rgb再转16进制颜色
107
+ fontColor = (val => {
108
+ val = val.trim().toLowerCase() //去掉前后空格
109
+ let argb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val)
110
+ let rgb = `rgba(${parseInt(argb[2], 16)}, ${parseInt(argb[3], 16)}, ${parseInt(argb[4], 16)})`
111
+ let percent = (parseInt(argb[1], 16) / 255) * 100
112
+ return $vUtils.fade(rgb, percent)
113
+ })(cell.style.font.color.argb)
114
+ }
115
+ if (fontColor) {
116
+ cell.style.color = fontColor
117
+ }
118
+
119
+ // exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
120
+ if (cell.style.alignment && cell.style.alignment.horizontal) {
121
+ cell.style.align = cell.style.alignment.horizontal
122
+ cell.style.valign = cell.style.alignment.vertical
123
+ }
124
+
125
+ //处理合并单元格
126
+ let mergeAddress = _.find(mergeAddressData, function (o) {
127
+ return o.startAddress === cell._address
128
+ })
129
+ if (mergeAddress) {
130
+ // 遍历的单元格属于合并单元格
131
+ if (cell.master.address !== mergeAddress.startAddress) {
132
+ // 不是合并单元格中的第一个单元格不需要计入数据源
133
+ return
134
+ }
135
+ // 说明是合并单元格区域的起始单元格
136
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0, merge: [mergeAddress.YRange, mergeAddress.XRange] }
137
+ sheetData.styles.push(cell.style)
138
+ //对应的style存放序号
139
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
140
+ } else {
141
+ // 非合并单元格
142
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()] = { text: cellText, style: 0 }
143
+ //解析单元格,包含样式
144
+ sheetData.styles.push(cell.style)
145
+ //对应的style存放序号
146
+ sheetData.rows[(rowIndex - 1).toString()].cells[(colNumber - 1).toString()].style = sheetData.styles.length - 1
147
+ }
148
+ })
149
+ })
150
+ workbookData.push(sheetData)
151
+ })
152
+ return new Spreadsheet(rootRef.value, excelOptions).loadData(workbookData)
153
+ }
154
+
155
+ const useData = dataHook(props, context, {
156
+ domRender
157
+ })
158
+
159
+ return {
160
+ ...useData
161
+ }
162
+ }
163
+ })
164
+ </script>
165
+
166
+ <template>
167
+ <div ref="rootRef" class="sh-office-docx"></div>
168
+ </template>
169
+
170
+ <style lang="less">
171
+ @media screen and (max-width: 800px) {
172
+ .sh-office-docx {
173
+ .docx-wrapper {
174
+ padding: 10px;
175
+ > section.docx {
176
+ padding: 10px !important;
177
+ width: 100% !important;
178
+ }
179
+ }
180
+ }
181
+ }
182
+ </style>
@@ -0,0 +1,73 @@
1
+ <script>
2
+ import { defineComponent, computed } from 'vue'
3
+ import dataHook from '../js/data-hook'
4
+ import dataProps from '../js/data-hook'
5
+ import { renderAsync } from 'docx-preview'
6
+ export default defineComponent({
7
+ name: 'ShOfficeDocx',
8
+ props: dataProps,
9
+ emits: ['rendered', 'error'],
10
+ setup(props, context) {
11
+ let defaultOption = {
12
+ inWrapper: true, //启用围绕文档内容呈现包装器
13
+ ignoreWidth: true, //禁用页面的渲染宽度
14
+ ignoreHeight: false, //禁用页面的渲染高度
15
+ ignoreFonts: false, //禁用字体渲染
16
+ breakPages: true, //在分页符上启用分页
17
+ ignoreLastRenderedPageBreak: true, //在lastRenderedPageBreak元素上禁用分页
18
+ experimental: false, //启用实验功能(制表符停止计算)
19
+ trimXmlDeclaration: true, //如果为true,则在解析之前将从xml文档中删除xml声明
20
+ useBase64URL: false, //如果为true,图像、字体等将转换为base 64 URL,否则使用URL.createObjectURL
21
+ useMathMLPolyfill: false, //包括用于铬、边等的MathML多填充。
22
+ showChanges: false, //启用文档更改的实验渲染(插入/删除)
23
+ debug: false //启用额外的日志记录
24
+ }
25
+
26
+ const docxOptions = computed(() => {
27
+ return Object.assign({}, defaultOption, props.options)
28
+ })
29
+
30
+ const domRender = (data, container) => {
31
+ if (!data) {
32
+ container.innerHTML = ''
33
+ return Promise.resolve()
34
+ }
35
+ let blob
36
+ if (data instanceof Blob) {
37
+ blob = data
38
+ } else if (data instanceof Response) {
39
+ blob = data.blob()
40
+ } else if (data instanceof ArrayBuffer) {
41
+ blob = new Blob([data])
42
+ }
43
+ return renderAsync(blob, container, null, docxOptions.value)
44
+ }
45
+
46
+ const useData = dataHook(props, context, {
47
+ domRender
48
+ })
49
+
50
+ return {
51
+ ...useData
52
+ }
53
+ }
54
+ })
55
+ </script>
56
+
57
+ <template>
58
+ <div ref="rootRef" class="sh-office-docx"></div>
59
+ </template>
60
+
61
+ <style lang="less">
62
+ @media screen and (max-width: 800px) {
63
+ .sh-office-docx {
64
+ .docx-wrapper {
65
+ padding: 10px;
66
+ > section.docx {
67
+ padding: 10px !important;
68
+ width: 100% !important;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ </style>