adtec-core-package 3.1.7 → 3.1.8
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/adtec-core-package-3.1.7.tgz +0 -0
- package/package/.editorconfig +6 -0
- package/package/adtec-core-package/adtec-core-package.css +1 -0
- package/package/adtec-core-package/adtec-core-package.js +41216 -0
- package/package/adtec-core-package/adtec-core-package.umd.cjs +87 -0
- package/package/adtec-core-package/favicon.ico +0 -0
- package/package/index.html +13 -0
- package/package/prebuilt/umo-editor/favicon.ico +0 -0
- package/package/prebuilt/umo-editor/umo-editor.css +1 -0
- package/package/public/favicon.ico +0 -0
- package/package/src/assets/base.css +86 -0
- package/package/src/assets/main.css +35 -0
- package/package/src/components/editor-main/src/extensions/bookmark.js +110 -0
- package/package.json +1 -1
- package/src/components/upload/ExcelJsViewer.vue +211 -37
- package/src/components/upload/OfficePreview.vue +3 -1
- package/src/utils/excelPreviewUtil.ts +212 -6
|
Binary file
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* color palette from <https://github.com/vuejs/theme> */
|
|
2
|
+
:root {
|
|
3
|
+
--vt-c-white: #ffffff;
|
|
4
|
+
--vt-c-white-soft: #f8f8f8;
|
|
5
|
+
--vt-c-white-mute: #f2f2f2;
|
|
6
|
+
|
|
7
|
+
--vt-c-black: #181818;
|
|
8
|
+
--vt-c-black-soft: #222222;
|
|
9
|
+
--vt-c-black-mute: #282828;
|
|
10
|
+
|
|
11
|
+
--vt-c-indigo: #2c3e50;
|
|
12
|
+
|
|
13
|
+
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
|
14
|
+
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
|
15
|
+
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
|
16
|
+
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
|
17
|
+
|
|
18
|
+
--vt-c-text-light-1: var(--vt-c-indigo);
|
|
19
|
+
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
|
20
|
+
--vt-c-text-dark-1: var(--vt-c-white);
|
|
21
|
+
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* semantic color variables for this project */
|
|
25
|
+
:root {
|
|
26
|
+
--color-background: var(--vt-c-white);
|
|
27
|
+
--color-background-soft: var(--vt-c-white-soft);
|
|
28
|
+
--color-background-mute: var(--vt-c-white-mute);
|
|
29
|
+
|
|
30
|
+
--color-border: var(--vt-c-divider-light-2);
|
|
31
|
+
--color-border-hover: var(--vt-c-divider-light-1);
|
|
32
|
+
|
|
33
|
+
--color-heading: var(--vt-c-text-light-1);
|
|
34
|
+
--color-text: var(--vt-c-text-light-1);
|
|
35
|
+
|
|
36
|
+
--section-gap: 160px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media (prefers-color-scheme: dark) {
|
|
40
|
+
:root {
|
|
41
|
+
--color-background: var(--vt-c-black);
|
|
42
|
+
--color-background-soft: var(--vt-c-black-soft);
|
|
43
|
+
--color-background-mute: var(--vt-c-black-mute);
|
|
44
|
+
|
|
45
|
+
--color-border: var(--vt-c-divider-dark-2);
|
|
46
|
+
--color-border-hover: var(--vt-c-divider-dark-1);
|
|
47
|
+
|
|
48
|
+
--color-heading: var(--vt-c-text-dark-1);
|
|
49
|
+
--color-text: var(--vt-c-text-dark-2);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
*,
|
|
54
|
+
*::before,
|
|
55
|
+
*::after {
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
margin: 0;
|
|
58
|
+
font-weight: normal;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
body {
|
|
62
|
+
min-height: 100vh;
|
|
63
|
+
color: var(--color-text);
|
|
64
|
+
background: var(--color-background);
|
|
65
|
+
transition:
|
|
66
|
+
color 0.5s,
|
|
67
|
+
background-color 0.5s;
|
|
68
|
+
line-height: 1.6;
|
|
69
|
+
font-family:
|
|
70
|
+
Inter,
|
|
71
|
+
-apple-system,
|
|
72
|
+
BlinkMacSystemFont,
|
|
73
|
+
'Segoe UI',
|
|
74
|
+
Roboto,
|
|
75
|
+
Oxygen,
|
|
76
|
+
Ubuntu,
|
|
77
|
+
Cantarell,
|
|
78
|
+
'Fira Sans',
|
|
79
|
+
'Droid Sans',
|
|
80
|
+
'Helvetica Neue',
|
|
81
|
+
sans-serif;
|
|
82
|
+
font-size: 15px;
|
|
83
|
+
text-rendering: optimizeLegibility;
|
|
84
|
+
-webkit-font-smoothing: antialiased;
|
|
85
|
+
-moz-osx-font-smoothing: grayscale;
|
|
86
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@import './base.css';
|
|
2
|
+
|
|
3
|
+
#app {
|
|
4
|
+
max-width: 1280px;
|
|
5
|
+
margin: 0 auto;
|
|
6
|
+
padding: 2rem;
|
|
7
|
+
font-weight: normal;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
a,
|
|
11
|
+
.green {
|
|
12
|
+
text-decoration: none;
|
|
13
|
+
color: hsla(160, 100%, 37%, 1);
|
|
14
|
+
transition: 0.4s;
|
|
15
|
+
padding: 3px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (hover: hover) {
|
|
19
|
+
a:hover {
|
|
20
|
+
background-color: hsla(160, 100%, 37%, 0.2);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@media (min-width: 1024px) {
|
|
25
|
+
body {
|
|
26
|
+
display: flex;
|
|
27
|
+
place-items: center;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#app {
|
|
31
|
+
display: grid;
|
|
32
|
+
grid-template-columns: 1fr 1fr;
|
|
33
|
+
padding: 0 2rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Mark, mergeAttributes } from '@tiptap/core'
|
|
2
|
+
import { TextSelection } from '@tiptap/pm/state'
|
|
3
|
+
|
|
4
|
+
import { shortId } from '../utils/short-id'
|
|
5
|
+
|
|
6
|
+
// 书签格式 创建一个书签
|
|
7
|
+
export default Mark.create({
|
|
8
|
+
name: 'bookmark',
|
|
9
|
+
priority: 1000,
|
|
10
|
+
keepOnSplit: false,
|
|
11
|
+
exitable: true,
|
|
12
|
+
addOptions() {
|
|
13
|
+
return {
|
|
14
|
+
bookmarkName: '',
|
|
15
|
+
class: 'umo-editor-bookmark',
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
addAttributes() {
|
|
19
|
+
return {
|
|
20
|
+
bookmarkName: {
|
|
21
|
+
default: 'bookmarkName',
|
|
22
|
+
},
|
|
23
|
+
class: {
|
|
24
|
+
default: this.options.class,
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
parseHTML() {
|
|
30
|
+
return [
|
|
31
|
+
{
|
|
32
|
+
tag: 'bookmark',
|
|
33
|
+
},
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
renderHTML({ HTMLAttributes }) {
|
|
38
|
+
return ['bookmark', mergeAttributes(this.options, HTMLAttributes), 0]
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
addCommands() {
|
|
42
|
+
return {
|
|
43
|
+
// 设置书签 若书签有选中区域数据 否则默认值为书签名称
|
|
44
|
+
setBookmark:
|
|
45
|
+
(attributes) =>
|
|
46
|
+
({ chain, editor }) => {
|
|
47
|
+
try {
|
|
48
|
+
chain().setMark(this.name, attributes).run()
|
|
49
|
+
const { empty } = editor.state.selection
|
|
50
|
+
if (empty && attributes.bookmarkName) {
|
|
51
|
+
chain().focus().insertContent(attributes.bookmarkName).run()
|
|
52
|
+
}
|
|
53
|
+
return true
|
|
54
|
+
} catch (e) {
|
|
55
|
+
return false
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
focusBookmark:
|
|
59
|
+
(bookmarkName) =>
|
|
60
|
+
({ editor, tr }) => {
|
|
61
|
+
if (bookmarkName) {
|
|
62
|
+
const element = editor.view.dom.querySelector(
|
|
63
|
+
`bookmark[bookmarkName="${bookmarkName}"]`,
|
|
64
|
+
)
|
|
65
|
+
if (element) {
|
|
66
|
+
element.scrollIntoView({
|
|
67
|
+
behavior: 'smooth',
|
|
68
|
+
block: 'center',
|
|
69
|
+
inline: 'nearest',
|
|
70
|
+
})
|
|
71
|
+
const pos = editor.view.posAtDOM(element, 0)
|
|
72
|
+
if (tr) {
|
|
73
|
+
tr.setSelection(new TextSelection(tr.doc.resolve(pos)))
|
|
74
|
+
editor.view.dispatch(tr)
|
|
75
|
+
editor.view.focus()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true
|
|
79
|
+
} else return false
|
|
80
|
+
},
|
|
81
|
+
getAllBookmarks:
|
|
82
|
+
(callback) =>
|
|
83
|
+
({ editor }) => {
|
|
84
|
+
const bookmarkData = []
|
|
85
|
+
try {
|
|
86
|
+
const alltext = editor.getHTML()
|
|
87
|
+
const parser = new DOMParser()
|
|
88
|
+
const doc = parser.parseFromString(alltext, 'text/html')
|
|
89
|
+
// 获取所有的 <bookmark> 元素
|
|
90
|
+
const bookmarks = doc.body.querySelectorAll(this.name)
|
|
91
|
+
const keyNode = []
|
|
92
|
+
Array.from(bookmarks).forEach((node) => {
|
|
93
|
+
if (node !== null) {
|
|
94
|
+
const bookName = node.getAttribute('bookmarkName')
|
|
95
|
+
if (bookName && !keyNode.includes(bookName)) {
|
|
96
|
+
keyNode.push(bookName)
|
|
97
|
+
bookmarkData.push({
|
|
98
|
+
bookmarkRowId: shortId(),
|
|
99
|
+
bookmarkRowName: bookName,
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
} catch (e) {}
|
|
105
|
+
callback(bookmarkData)
|
|
106
|
+
return true
|
|
107
|
+
},
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
})
|
package/package.json
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<div class="excel-
|
|
7
|
-
<div class="excel-scale-host" :style="scaleHostStyle">
|
|
2
|
+
<div class="excel-js-viewer">
|
|
3
|
+
<div ref="scrollRef" class="excel-grid-scroll">
|
|
4
|
+
<div v-if="loading" class="excel-loading">正在解析表格…</div>
|
|
5
|
+
<div v-else-if="sheets.length === 0" class="excel-empty">表格为空或无法解析</div>
|
|
6
|
+
<div v-else class="excel-scale-host" :style="scaleHostStyle">
|
|
8
7
|
<table class="excel-table" :style="tableStyle">
|
|
8
|
+
<thead>
|
|
9
|
+
<tr>
|
|
10
|
+
<th class="excel-corner" />
|
|
11
|
+
<th
|
|
12
|
+
v-for="col in columnHeaders"
|
|
13
|
+
:key="col"
|
|
14
|
+
class="excel-col-header"
|
|
15
|
+
:style="{ minWidth: `${getColWidth(col)}px`, width: `${getColWidth(col)}px` }"
|
|
16
|
+
>
|
|
17
|
+
{{ toExcelColumnLabel(col) }}
|
|
18
|
+
</th>
|
|
19
|
+
</tr>
|
|
20
|
+
</thead>
|
|
9
21
|
<tbody>
|
|
10
22
|
<tr v-for="(row, rowIndex) in activeSheet?.rows || []" :key="rowIndex">
|
|
23
|
+
<th class="excel-row-header">{{ (row[0]?.row ?? rowIndex) + 1 }}</th>
|
|
11
24
|
<td
|
|
12
25
|
v-for="cell in row"
|
|
13
26
|
:key="`${cell.row}-${cell.col}`"
|
|
@@ -16,6 +29,8 @@
|
|
|
16
29
|
:data-row="cell.row"
|
|
17
30
|
:data-col="cell.col"
|
|
18
31
|
:class="cellClass(cell)"
|
|
32
|
+
:style="cellInlineStyle(cell)"
|
|
33
|
+
@click="selectCell(cell)"
|
|
19
34
|
>
|
|
20
35
|
{{ cell.value }}
|
|
21
36
|
</td>
|
|
@@ -24,6 +39,24 @@
|
|
|
24
39
|
</table>
|
|
25
40
|
</div>
|
|
26
41
|
</div>
|
|
42
|
+
|
|
43
|
+
<div v-if="sheets.length > 1" class="excel-sheet-tabs">
|
|
44
|
+
<button
|
|
45
|
+
v-for="(sheet, index) in sheets"
|
|
46
|
+
:key="sheet.name + index"
|
|
47
|
+
type="button"
|
|
48
|
+
class="excel-sheet-tab"
|
|
49
|
+
:class="{ 'is-active': currentSheet === index + 1 }"
|
|
50
|
+
@click="switchSheet(index + 1)"
|
|
51
|
+
>
|
|
52
|
+
{{ sheet.name }}
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div v-if="sheets.length > 0 && !loading" class="excel-zoom-float">
|
|
57
|
+
<button type="button" class="excel-zoom-btn" title="放大" @click="emit('zoom-in')">+</button>
|
|
58
|
+
<button type="button" class="excel-zoom-btn" title="缩小" @click="emit('zoom-out')">−</button>
|
|
59
|
+
</div>
|
|
27
60
|
</div>
|
|
28
61
|
</template>
|
|
29
62
|
|
|
@@ -33,8 +66,10 @@ import {
|
|
|
33
66
|
type ExcelPreviewCell,
|
|
34
67
|
type ExcelPreviewSheet,
|
|
35
68
|
type ExcelSearchMatch,
|
|
69
|
+
cellStyleToCss,
|
|
36
70
|
parseExcelWorkbook,
|
|
37
71
|
searchExcelSheets,
|
|
72
|
+
toExcelColumnLabel,
|
|
38
73
|
} from '../../utils/excelPreviewUtil.ts'
|
|
39
74
|
|
|
40
75
|
const props = withDefaults(
|
|
@@ -49,6 +84,8 @@ const emit = defineEmits<{
|
|
|
49
84
|
loaded: []
|
|
50
85
|
error: [err?: unknown]
|
|
51
86
|
'page-change': [page: number]
|
|
87
|
+
'zoom-in': []
|
|
88
|
+
'zoom-out': []
|
|
52
89
|
}>()
|
|
53
90
|
|
|
54
91
|
const scrollRef = ref<HTMLElement | null>(null)
|
|
@@ -57,10 +94,19 @@ const loading = ref(false)
|
|
|
57
94
|
const currentSheet = ref(1)
|
|
58
95
|
const searchMatches = ref<ExcelSearchMatch[]>([])
|
|
59
96
|
const activeMatchIndex = ref(-1)
|
|
97
|
+
const selectedCell = ref<{ row: number; col: number } | null>(null)
|
|
60
98
|
|
|
61
99
|
const totalPages = ref(0)
|
|
62
100
|
const activeSheet = computed(() => sheets.value[currentSheet.value - 1])
|
|
63
101
|
|
|
102
|
+
const columnHeaders = computed(() => {
|
|
103
|
+
const sheet = activeSheet.value
|
|
104
|
+
if (!sheet) return []
|
|
105
|
+
const cols: number[] = []
|
|
106
|
+
for (let c = sheet.startCol; c <= sheet.endCol; c++) cols.push(c)
|
|
107
|
+
return cols
|
|
108
|
+
})
|
|
109
|
+
|
|
64
110
|
const userScale = computed(() => props.scale ?? 1)
|
|
65
111
|
const tableStyle = computed(() => ({
|
|
66
112
|
transform: `scale(${userScale.value})`,
|
|
@@ -70,11 +116,11 @@ const scaleHostStyle = computed(() => {
|
|
|
70
116
|
const sheet = activeSheet.value
|
|
71
117
|
if (!sheet) return {}
|
|
72
118
|
const rowCount = sheet.rows.length || 1
|
|
73
|
-
const colCount =
|
|
74
|
-
const baseWidth =
|
|
75
|
-
const baseHeight = rowCount *
|
|
119
|
+
const colCount = columnHeaders.value.length || 1
|
|
120
|
+
const baseWidth = columnHeaders.value.reduce((sum, col) => sum + getColWidth(col), 42)
|
|
121
|
+
const baseHeight = rowCount * 24 + 28
|
|
76
122
|
return {
|
|
77
|
-
width: `${baseWidth * userScale.value}px`,
|
|
123
|
+
width: `${Math.max(baseWidth, colCount * 72 + 42) * userScale.value}px`,
|
|
78
124
|
height: `${baseHeight * userScale.value}px`,
|
|
79
125
|
}
|
|
80
126
|
})
|
|
@@ -83,6 +129,8 @@ const activeMatch = computed(() =>
|
|
|
83
129
|
activeMatchIndex.value >= 0 ? searchMatches.value[activeMatchIndex.value] : null,
|
|
84
130
|
)
|
|
85
131
|
|
|
132
|
+
const getColWidth = (col: number) => activeSheet.value?.colWidths[col] ?? 72
|
|
133
|
+
|
|
86
134
|
const cellClass = (cell: ExcelPreviewCell) => {
|
|
87
135
|
const classes: string[] = []
|
|
88
136
|
const hasMatch = searchMatches.value.some(
|
|
@@ -97,8 +145,32 @@ const cellClass = (cell: ExcelPreviewCell) => {
|
|
|
97
145
|
) {
|
|
98
146
|
classes.push('excel-cell--active')
|
|
99
147
|
}
|
|
100
|
-
if (
|
|
101
|
-
|
|
148
|
+
if (
|
|
149
|
+
selectedCell.value &&
|
|
150
|
+
selectedCell.value.row === cell.row &&
|
|
151
|
+
selectedCell.value.col === cell.col
|
|
152
|
+
) {
|
|
153
|
+
classes.push('excel-cell--selected')
|
|
154
|
+
}
|
|
155
|
+
return classes.length > 0 ? classes : undefined
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const cellInlineStyle = (cell: ExcelPreviewCell) => {
|
|
159
|
+
const css = cellStyleToCss(cell.style)
|
|
160
|
+
if (cell.width) {
|
|
161
|
+
css.minWidth = `${cell.width}px`
|
|
162
|
+
css.width = `${cell.width}px`
|
|
163
|
+
css.maxWidth = `${Math.max(cell.width, 280)}px`
|
|
164
|
+
}
|
|
165
|
+
return css
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const selectCell = (cell: ExcelPreviewCell) => {
|
|
169
|
+
selectedCell.value = { row: cell.row, col: cell.col }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const switchSheet = async (sheetIndex: number) => {
|
|
173
|
+
await scrollToPage(sheetIndex)
|
|
102
174
|
}
|
|
103
175
|
|
|
104
176
|
const resetViewer = () => {
|
|
@@ -107,6 +179,7 @@ const resetViewer = () => {
|
|
|
107
179
|
currentSheet.value = 1
|
|
108
180
|
searchMatches.value = []
|
|
109
181
|
activeMatchIndex.value = -1
|
|
182
|
+
selectedCell.value = null
|
|
110
183
|
loading.value = false
|
|
111
184
|
}
|
|
112
185
|
|
|
@@ -116,6 +189,7 @@ const loadWorkbook = async (src: Blob | ArrayBuffer) => {
|
|
|
116
189
|
sheets.value = await parseExcelWorkbook(src)
|
|
117
190
|
totalPages.value = sheets.value.length
|
|
118
191
|
currentSheet.value = 1
|
|
192
|
+
selectedCell.value = null
|
|
119
193
|
emit('page-change', 1)
|
|
120
194
|
emit('loaded')
|
|
121
195
|
} catch (err) {
|
|
@@ -138,15 +212,17 @@ const scrollToCell = async (match: ExcelSearchMatch) => {
|
|
|
138
212
|
) as HTMLElement | null
|
|
139
213
|
if (!container || !cellEl) return
|
|
140
214
|
const top = cellEl.offsetTop - container.clientHeight * 0.3
|
|
141
|
-
|
|
215
|
+
const left = cellEl.offsetLeft - container.clientWidth * 0.2
|
|
216
|
+
container.scrollTo({ top: Math.max(0, top), left: Math.max(0, left), behavior: 'smooth' })
|
|
142
217
|
}
|
|
143
218
|
|
|
144
219
|
const scrollToPage = async (pageNum: number) => {
|
|
145
220
|
const target = Math.min(Math.max(1, pageNum), totalPages.value || 1)
|
|
146
221
|
currentSheet.value = target
|
|
222
|
+
selectedCell.value = null
|
|
147
223
|
emit('page-change', target)
|
|
148
224
|
await nextTick()
|
|
149
|
-
scrollRef.value?.scrollTo({ top: 0, behavior: 'smooth' })
|
|
225
|
+
scrollRef.value?.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
|
|
150
226
|
}
|
|
151
227
|
|
|
152
228
|
const runSearch = async (query: string) => {
|
|
@@ -178,7 +254,7 @@ const gotoSearchMatch = async (direction: 1 | -1) => {
|
|
|
178
254
|
}
|
|
179
255
|
|
|
180
256
|
const refitLayout = () => {
|
|
181
|
-
scrollRef.value?.scrollTo({ top: 0 })
|
|
257
|
+
scrollRef.value?.scrollTo({ top: 0, left: 0 })
|
|
182
258
|
}
|
|
183
259
|
|
|
184
260
|
watch(
|
|
@@ -202,51 +278,94 @@ defineExpose({
|
|
|
202
278
|
|
|
203
279
|
<style scoped lang="scss">
|
|
204
280
|
.excel-js-viewer {
|
|
281
|
+
position: relative;
|
|
282
|
+
display: flex;
|
|
205
283
|
flex: 1;
|
|
284
|
+
flex-direction: column;
|
|
206
285
|
width: 100%;
|
|
207
286
|
min-height: 0;
|
|
208
|
-
|
|
209
|
-
background: #f5f5f5;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
.excel-body {
|
|
213
|
-
min-height: 100%;
|
|
214
|
-
padding: 12px;
|
|
287
|
+
background: #e6e6e6;
|
|
215
288
|
}
|
|
216
289
|
|
|
217
|
-
.excel-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
290
|
+
.excel-grid-scroll {
|
|
291
|
+
flex: 1;
|
|
292
|
+
min-height: 0;
|
|
293
|
+
overflow: auto;
|
|
294
|
+
background: #e6e6e6;
|
|
222
295
|
}
|
|
223
296
|
|
|
224
297
|
.excel-scale-host {
|
|
225
298
|
display: inline-block;
|
|
226
299
|
min-width: 100%;
|
|
300
|
+
padding: 0;
|
|
227
301
|
}
|
|
228
302
|
|
|
229
303
|
.excel-table {
|
|
230
|
-
border-collapse:
|
|
304
|
+
border-collapse: separate;
|
|
305
|
+
border-spacing: 0;
|
|
231
306
|
background: #fff;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
307
|
+
font-size: 12px;
|
|
308
|
+
line-height: 1.35;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.excel-corner,
|
|
312
|
+
.excel-col-header,
|
|
313
|
+
.excel-row-header {
|
|
314
|
+
position: sticky;
|
|
315
|
+
z-index: 2;
|
|
316
|
+
background: #f0f0f0;
|
|
317
|
+
color: #444;
|
|
318
|
+
font-weight: 400;
|
|
319
|
+
text-align: center;
|
|
320
|
+
user-select: none;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.excel-corner {
|
|
324
|
+
top: 0;
|
|
325
|
+
left: 0;
|
|
326
|
+
z-index: 4;
|
|
327
|
+
width: 42px;
|
|
328
|
+
min-width: 42px;
|
|
329
|
+
border-right: 1px solid #c7c7c7;
|
|
330
|
+
border-bottom: 1px solid #c7c7c7;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.excel-col-header {
|
|
334
|
+
top: 0;
|
|
335
|
+
z-index: 3;
|
|
336
|
+
min-width: 72px;
|
|
337
|
+
height: 22px;
|
|
338
|
+
padding: 2px 6px;
|
|
339
|
+
border-right: 1px solid #d4d4d4;
|
|
340
|
+
border-bottom: 1px solid #c7c7c7;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.excel-row-header {
|
|
344
|
+
left: 0;
|
|
345
|
+
z-index: 2;
|
|
346
|
+
width: 42px;
|
|
347
|
+
min-width: 42px;
|
|
348
|
+
padding: 2px 4px;
|
|
349
|
+
border-right: 1px solid #c7c7c7;
|
|
350
|
+
border-bottom: 1px solid #d4d4d4;
|
|
235
351
|
}
|
|
236
352
|
|
|
237
353
|
.excel-table td {
|
|
238
354
|
min-width: 72px;
|
|
239
|
-
max-width:
|
|
240
|
-
padding: 6px
|
|
241
|
-
border: 1px solid #
|
|
355
|
+
max-width: 320px;
|
|
356
|
+
padding: 2px 6px;
|
|
357
|
+
border-right: 1px solid #d4d4d4;
|
|
358
|
+
border-bottom: 1px solid #d4d4d4;
|
|
242
359
|
color: #111827;
|
|
243
|
-
vertical-align:
|
|
360
|
+
vertical-align: middle;
|
|
244
361
|
word-break: break-word;
|
|
245
362
|
white-space: pre-wrap;
|
|
363
|
+
background: #fff;
|
|
364
|
+
cursor: cell;
|
|
246
365
|
}
|
|
247
366
|
|
|
248
|
-
.excel-
|
|
249
|
-
|
|
367
|
+
.excel-cell--selected {
|
|
368
|
+
box-shadow: inset 0 0 0 2px #217346 !important;
|
|
250
369
|
}
|
|
251
370
|
|
|
252
371
|
.excel-cell--match {
|
|
@@ -258,6 +377,61 @@ defineExpose({
|
|
|
258
377
|
box-shadow: inset 0 0 0 2px rgba(255, 87, 34, 0.75);
|
|
259
378
|
}
|
|
260
379
|
|
|
380
|
+
.excel-sheet-tabs {
|
|
381
|
+
display: flex;
|
|
382
|
+
gap: 2px;
|
|
383
|
+
align-items: stretch;
|
|
384
|
+
min-height: 30px;
|
|
385
|
+
padding: 0 6px;
|
|
386
|
+
overflow-x: auto;
|
|
387
|
+
background: #f0f0f0;
|
|
388
|
+
border-top: 1px solid #c7c7c7;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.excel-sheet-tab {
|
|
392
|
+
flex-shrink: 0;
|
|
393
|
+
padding: 4px 14px;
|
|
394
|
+
border: none;
|
|
395
|
+
border-top: 2px solid transparent;
|
|
396
|
+
background: #e2e2e2;
|
|
397
|
+
color: #333;
|
|
398
|
+
font-size: 12px;
|
|
399
|
+
cursor: pointer;
|
|
400
|
+
|
|
401
|
+
&.is-active {
|
|
402
|
+
background: #fff;
|
|
403
|
+
border-top-color: #217346;
|
|
404
|
+
font-weight: 600;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.excel-zoom-float {
|
|
409
|
+
position: absolute;
|
|
410
|
+
right: 16px;
|
|
411
|
+
bottom: 42px;
|
|
412
|
+
z-index: 5;
|
|
413
|
+
display: flex;
|
|
414
|
+
flex-direction: column;
|
|
415
|
+
gap: 8px;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.excel-zoom-btn {
|
|
419
|
+
width: 34px;
|
|
420
|
+
height: 34px;
|
|
421
|
+
border: none;
|
|
422
|
+
border-radius: 50%;
|
|
423
|
+
background: rgba(255, 255, 255, 0.92);
|
|
424
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
425
|
+
color: #333;
|
|
426
|
+
font-size: 20px;
|
|
427
|
+
line-height: 1;
|
|
428
|
+
cursor: pointer;
|
|
429
|
+
|
|
430
|
+
&:hover {
|
|
431
|
+
background: #fff;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
261
435
|
.excel-loading,
|
|
262
436
|
.excel-empty {
|
|
263
437
|
display: flex;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
:search-index="searchMatchIndex"
|
|
12
12
|
:search-total="searchMatchTotal"
|
|
13
13
|
:show-search="showSearch"
|
|
14
|
-
:show-page-nav="showPageNav"
|
|
14
|
+
:show-page-nav="showPageNav && officeType !== 'excel'"
|
|
15
15
|
:show-zoom="showZoom"
|
|
16
16
|
:show-download="showDownload"
|
|
17
17
|
:show-refresh="showRefresh"
|
|
@@ -55,6 +55,8 @@
|
|
|
55
55
|
@loaded="handleRendered"
|
|
56
56
|
@error="handleError"
|
|
57
57
|
@page-change="previewCurrentPage = $event"
|
|
58
|
+
@zoom-in="zoomIn"
|
|
59
|
+
@zoom-out="zoomOut"
|
|
58
60
|
/>
|
|
59
61
|
<docx-js-viewer
|
|
60
62
|
v-else-if="officeType === 'docx' && !previewAsPdf"
|