@jzt-packages/components 1.0.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 (145) hide show
  1. package/package.json +68 -0
  2. package/src/JztBackTop/index.vue +255 -0
  3. package/src/JztButtonList/index.vue +88 -0
  4. package/src/JztChart/index.vue +95 -0
  5. package/src/JztCharts/index.vue +317 -0
  6. package/src/JztClassTabs/index.vue +156 -0
  7. package/src/JztDateSelect/dateSelect.vue +186 -0
  8. package/src/JztDateSelect/dateType.vue +54 -0
  9. package/src/JztDateSelect/index.ts +135 -0
  10. package/src/JztDateSelect/interface/index.ts +13 -0
  11. package/src/JztDialog/index.vue +249 -0
  12. package/src/JztEllipsisTooltip/index.vue +61 -0
  13. package/src/JztEmpty/index.vue +45 -0
  14. package/src/JztErrorPage/403.vue +30 -0
  15. package/src/JztErrorPage/404.vue +19 -0
  16. package/src/JztErrorPage/500.vue +18 -0
  17. package/src/JztErrorPage/assets/401.png +0 -0
  18. package/src/JztErrorPage/assets/403.png +0 -0
  19. package/src/JztErrorPage/assets/404.png +0 -0
  20. package/src/JztErrorPage/assets/500.png +0 -0
  21. package/src/JztErrorPage/index.scss +35 -0
  22. package/src/JztErrorPage/index.vue +35 -0
  23. package/src/JztFilePreview/components/pdfViewer.vue +221 -0
  24. package/src/JztFilePreview/hooks/useImageMethod.ts +256 -0
  25. package/src/JztFilePreview/index.scss +171 -0
  26. package/src/JztFilePreview/index.vue +68 -0
  27. package/src/JztFilePreview/interface/index.ts +18 -0
  28. package/src/JztFilePreview/previewFile.vue +371 -0
  29. package/src/JztFormGrid/README.md +520 -0
  30. package/src/JztFormGrid/components/formItem.vue +209 -0
  31. package/src/JztFormGrid/components/formItemValue.vue +384 -0
  32. package/src/JztFormGrid/components/showDetailForm.vue +172 -0
  33. package/src/JztFormGrid/index.scss +60 -0
  34. package/src/JztFormGrid/index.vue +513 -0
  35. package/src/JztFormGrid/interface/index.ts +106 -0
  36. package/src/JztGrid/components/GridItem.vue +68 -0
  37. package/src/JztGrid/index.vue +179 -0
  38. package/src/JztGrid/interface/index.ts +6 -0
  39. package/src/JztImportExcel/assets/delete.png +0 -0
  40. package/src/JztImportExcel/index.scss +46 -0
  41. package/src/JztImportExcel/index.vue +430 -0
  42. package/src/JztImportExcel/interface/index.ts +25 -0
  43. package/src/JztLabelTitle/index.vue +65 -0
  44. package/src/JztLeftRightMode/components/CollapseButton.vue +80 -0
  45. package/src/JztLeftRightMode/components/LeftCard.vue +203 -0
  46. package/src/JztLeftRightMode/components/LeftLayout.vue +173 -0
  47. package/src/JztLeftRightMode/components/RightHeader.vue +186 -0
  48. package/src/JztLeftRightMode/components/RightLayout.vue +235 -0
  49. package/src/JztLeftRightMode/components/RightTableHeader.vue +43 -0
  50. package/src/JztLeftRightMode/hooks/useCollapse.ts +17 -0
  51. package/src/JztLeftRightMode/hooks/useDefaultProps.ts +19 -0
  52. package/src/JztLeftRightMode/hooks/useLeftLayout.ts +201 -0
  53. package/src/JztLeftRightMode/hooks/useMode.ts +20 -0
  54. package/src/JztLeftRightMode/hooks/usePrevNext.ts +60 -0
  55. package/src/JztLeftRightMode/hooks/useRightLayout.ts +215 -0
  56. package/src/JztLeftRightMode/hooks/useSlots.ts +15 -0
  57. package/src/JztLeftRightMode/index.ts +3 -0
  58. package/src/JztLeftRightMode/index.vue +494 -0
  59. package/src/JztLeftRightMode/types/index.ts +457 -0
  60. package/src/JztLoading/fullScreen.ts +45 -0
  61. package/src/JztLoading/index.scss +67 -0
  62. package/src/JztLoading/index.vue +18 -0
  63. package/src/JztLogin/components/LoginFooter.vue +17 -0
  64. package/src/JztLogin/components/LoginForm.vue +99 -0
  65. package/src/JztLogin/hooks/useLogin.ts +186 -0
  66. package/src/JztLogin/index.scss +142 -0
  67. package/src/JztLogin/index.vue +31 -0
  68. package/src/JztLogin/interface/index.ts +47 -0
  69. package/src/JztNumericalRange/index.vue +81 -0
  70. package/src/JztPageCard/comm/datePicker.vue +151 -0
  71. package/src/JztPageCard/comm/details.vue +60 -0
  72. package/src/JztPageCard/comm/export.vue +24 -0
  73. package/src/JztPageCard/comm/tabs.vue +94 -0
  74. package/src/JztPageCard/comm/tooltip.vue +31 -0
  75. package/src/JztPageCard/index.vue +287 -0
  76. package/src/JztPagination/index.vue +70 -0
  77. package/src/JztProductInfo/components/imagePreview.vue +275 -0
  78. package/src/JztProductInfo/components/qxUnique.vue +101 -0
  79. package/src/JztProductInfo/components/records.vue +265 -0
  80. package/src/JztProductInfo/hooks/useParams.ts +143 -0
  81. package/src/JztProductInfo/hooks/useQxUnique.tsx +466 -0
  82. package/src/JztProductInfo/images/defaultProduct.png +0 -0
  83. package/src/JztProductInfo/index.ts +116 -0
  84. package/src/JztProductInfo/index.vue +108 -0
  85. package/src/JztProductInfo/interface/index.ts +15 -0
  86. package/src/JztQueryDetailTable/index.scss +100 -0
  87. package/src/JztQueryDetailTable/index.vue +400 -0
  88. package/src/JztQueryDetailTable/interface/index.ts +10 -0
  89. package/src/JztQueryTable/QueryTable /345/212/237/350/203/275.md" +1580 -0
  90. package/src/JztQueryTable/README.md +567 -0
  91. package/src/JztQueryTable/components/ColSetting.vue +67 -0
  92. package/src/JztQueryTable/components/ColumnsSetting.vue +404 -0
  93. package/src/JztQueryTable/components/ColumnsSetting1.vue +220 -0
  94. package/src/JztQueryTable/components/DeployToAccountLevelSetting.vue +351 -0
  95. package/src/JztQueryTable/components/Pagination.vue +54 -0
  96. package/src/JztQueryTable/components/TableColumn.vue +109 -0
  97. package/src/JztQueryTable/const.ts +1 -0
  98. package/src/JztQueryTable/hooks/useQueryTable.ts +194 -0
  99. package/src/JztQueryTable/hooks/useSelection.ts +47 -0
  100. package/src/JztQueryTable/hooks/useTableSetting.ts +197 -0
  101. package/src/JztQueryTable/hooks/useTemplate.ts +127 -0
  102. package/src/JztQueryTable/index.scss +91 -0
  103. package/src/JztQueryTable/index.vue +1445 -0
  104. package/src/JztQueryTable/interface/index.ts +185 -0
  105. package/src/JztRegionSelect/index.vue +134 -0
  106. package/src/JztSearchForm/components/SearchFormItem.vue +473 -0
  107. package/src/JztSearchForm/index.vue +530 -0
  108. package/src/JztSearchForm/interface/index.ts +100 -0
  109. package/src/JztSelectFilter/index.scss +63 -0
  110. package/src/JztSelectFilter/index.vue +110 -0
  111. package/src/JztSelectTable/index.vue +257 -0
  112. package/src/JztTable/index.scss +72 -0
  113. package/src/JztTable/index.vue +353 -0
  114. package/src/JztTable/interface/index.ts +1 -0
  115. package/src/JztTime/comm/agencySelect.vue +112 -0
  116. package/src/JztTime/comm/collapseRow.vue +132 -0
  117. package/src/JztTime/comm/dateSelect.vue +292 -0
  118. package/src/JztTime/comm/deptSelect.vue +193 -0
  119. package/src/JztTime/comm/typeSelect.vue +97 -0
  120. package/src/JztTime/index.ts +216 -0
  121. package/src/JztTime/index.vue +303 -0
  122. package/src/JztTime/interface/index.ts +23 -0
  123. package/src/JztTreeFilter/index.scss +44 -0
  124. package/src/JztTreeFilter/index.vue +177 -0
  125. package/src/JztUploadFile/interface/index.ts +21 -0
  126. package/src/JztUploadFile/multiple.scss +215 -0
  127. package/src/JztUploadFile/multiple.vue +318 -0
  128. package/src/JztUploadFile/single.scss +226 -0
  129. package/src/JztUploadFile/single.vue +274 -0
  130. package/src/JztUploadImg/Img.vue +294 -0
  131. package/src/JztUploadImg/Imgs.vue +411 -0
  132. package/src/JztUploadImg/index.scss +138 -0
  133. package/src/JztUploadImg/interface/index.ts +22 -0
  134. package/src/SelectIcon/index.scss +39 -0
  135. package/src/SelectIcon/index.vue +106 -0
  136. package/src/SvgIcon/index.vue +22 -0
  137. package/src/hooks/useAuthButtons.ts +58 -0
  138. package/src/hooks/useFormByUserType.ts +90 -0
  139. package/src/hooks/useTableEvents.ts +30 -0
  140. package/src/hooks/useUploadFileHook.ts +262 -0
  141. package/src/index.ts +91 -0
  142. package/src/typings/global.d.ts +101 -0
  143. package/src/utils/index.ts +107 -0
  144. package/src/utils/tree.ts +57 -0
  145. package/tsconfig.json +45 -0
@@ -0,0 +1,221 @@
1
+ <template>
2
+ <div v-loading="loading" class="pdf-preview column-center">
3
+ <div
4
+ v-if="state.numPages > 1"
5
+ class="pageSize-tool flx-evenly-center cursor-pointer"
6
+ >
7
+ <span @click="lastPage">上一页</span>
8
+ <span class="ml10 mr10">{{ state.pageNum }}/{{ state.numPages }}</span>
9
+ <span @click="nextPage">下一页</span>
10
+ </div>
11
+ <el-scrollbar style="width: 100%; height: 100%">
12
+ <div
13
+ ref="wrapRef"
14
+ class="pdf-wrap"
15
+ @mousedown="onDragStart"
16
+ @mousemove="onDragMove"
17
+ @mouseup="onDragEnd"
18
+ @mouseleave="onDragEnd"
19
+ @wheel.prevent="onWheel"
20
+ >
21
+ <vue-pdf-embed
22
+ v-if="blobUrl"
23
+ id="printContent"
24
+ :source="blobUrl"
25
+ :scale="zoomState.scaleValue"
26
+ :style="scaleFun"
27
+ class="vue-pdf-embed"
28
+ :page="state.pageNum"
29
+ @loaded="handleLoaded"
30
+ @loading-failed="handleLoadingFailed"
31
+ />
32
+ </div>
33
+ </el-scrollbar>
34
+ <div class="page-tool flx-evenly-center cursor-pointer">
35
+ <span @click="useDownloadFile(blobUrl, pdfName)">
36
+ <el-tooltip effect="dark" content="下载" placement="top">
37
+ <i class="iconfont icon-xiazai"></i>
38
+ </el-tooltip>
39
+ </span>
40
+ <span @click="printFile({ printable: blobUrl, type: 'pdf' })">
41
+ <el-tooltip effect="dark" content="打印" placement="top">
42
+ <i class="iconfont icon-dayin"></i>
43
+ </el-tooltip>
44
+ </span>
45
+
46
+ <span @click="resetZoom">
47
+ <el-tooltip effect="dark" content="适应" placement="top">
48
+ <i class="iconfont icon-shiyingchuangkou"></i>
49
+ </el-tooltip>
50
+ </span>
51
+ <div class="flx-center">
52
+ <span @click="pageZoomOut">
53
+ <el-tooltip effect="dark" content="放大" placement="top">
54
+ <i class="iconfont icon-fangda"></i>
55
+ </el-tooltip>
56
+ </span>
57
+ <span class="ml10 mr10">{{ Math.round(zoomState.scaleValue * 100) }}%</span>
58
+ <span @click="pageZoomIn">
59
+ <el-tooltip effect="dark" content="缩小" placement="top">
60
+ <i class="iconfont icon-suoxiao"></i>
61
+ </el-tooltip>
62
+ </span>
63
+ </div>
64
+ </div>
65
+ </div>
66
+ </template>
67
+
68
+ <script lang="ts" setup>
69
+ import { printFile, useDownloadFile } from "@jzt-spd/utils";
70
+ import { computed, reactive, ref, watch, onBeforeUnmount } from "vue";
71
+ import VuePdfEmbed from "vue-pdf-embed";
72
+ import { usePdfDragZoom } from '../hooks/useImageMethod'
73
+
74
+ const props = defineProps<{
75
+ pdfUrl: string;
76
+ pdfName: string;
77
+ }>();
78
+
79
+ const {
80
+ state: zoomState,
81
+ wrapRef,
82
+ scaleFun,
83
+ pageZoomOut,
84
+ pageZoomIn,
85
+ resetZoom,
86
+ onDragStart,
87
+ onDragMove,
88
+ onDragEnd,
89
+ onWheel
90
+ } = usePdfDragZoom()
91
+
92
+ const state = reactive({
93
+ pageNum: 1, //当前页面
94
+ numPages: 0, // 总页数
95
+ });
96
+
97
+ // 通过 web 服务器同源请求获取 PDF,cookie 自动携带
98
+ const blobUrl = ref('')
99
+ const loading = ref(true)
100
+ let fetching = false
101
+
102
+ const fetchPdfBlob = async (url: string) => {
103
+ if (fetching) return
104
+ fetching = true
105
+ try {
106
+ const response = await fetch(url, {
107
+ credentials: 'include'
108
+ })
109
+ if (!response.ok) throw new Error(`HTTP ${response.status}`)
110
+ // 校验返回内容是否为 PDF,避免 vite SPA fallback 返回 HTML
111
+ const contentType = response.headers.get('content-type') || ''
112
+ if (!contentType.includes('pdf') && !contentType.includes('octet-stream')) {
113
+ throw new Error(`Invalid content type: ${contentType}`)
114
+ }
115
+ const blob = await response.blob()
116
+ if (blobUrl.value) URL.revokeObjectURL(blobUrl.value)
117
+ blobUrl.value = URL.createObjectURL(new Blob([blob], { type: 'application/pdf' }))
118
+ } catch {
119
+ loading.value = false
120
+ } finally {
121
+ fetching = false
122
+ }
123
+ }
124
+
125
+ watch(
126
+ () => props.pdfUrl,
127
+ url => {
128
+ if (url) fetchPdfBlob(url)
129
+ },
130
+ { immediate: true }
131
+ )
132
+
133
+ onBeforeUnmount(() => {
134
+ if (blobUrl.value) URL.revokeObjectURL(blobUrl.value)
135
+ })
136
+
137
+ // 上一页
138
+ function lastPage() {
139
+ if (state.pageNum > 1) {
140
+ state.pageNum -= 1;
141
+ }
142
+ }
143
+ // 下一页
144
+ function nextPage() {
145
+ if (state.pageNum < state.numPages) {
146
+ state.pageNum += 1;
147
+ }
148
+ }
149
+ // pdf加载完成
150
+ const handleLoaded = doc => {
151
+ state.numPages = doc.numPages || 0;
152
+ loading.value = false;
153
+ };
154
+
155
+ // pdf加载失败
156
+ const handleLoadingFailed = () => {
157
+ loading.value = false;
158
+ };
159
+
160
+ defineExpose({
161
+ pageZoomOut,
162
+ pageZoomIn,
163
+ })
164
+ </script>
165
+
166
+ <style lang="scss" scoped>
167
+ .pdf-preview {
168
+ width: 100%;
169
+ height: 100%;
170
+ position: relative;
171
+ .el-scrollbar__view {
172
+ height: 100%;
173
+ }
174
+ .iconfont {
175
+ font-size: 22px;
176
+ }
177
+ .pdf-wrap {
178
+ height: 100%;
179
+ display: flex;
180
+ justify-content: center;
181
+ cursor: grab;
182
+ // .vue-pdf-embed {
183
+ // box-sizing: border-box;
184
+ // }
185
+ }
186
+ .pageSize-tool {
187
+ position: absolute;
188
+ top: 0px;
189
+ left: 50%;
190
+ right: 50%;
191
+ transform: translateX(-50%);
192
+ width: 220px;
193
+ height: 30px;
194
+ opacity: 0.8;
195
+ border-radius: 8px;
196
+ background: #333333;
197
+ z-index: 10;
198
+ span {
199
+ color: white;
200
+ font-size: 14px;
201
+ }
202
+ }
203
+ .page-tool {
204
+ position: absolute;
205
+ bottom: 6px;
206
+ left: 50%;
207
+ right: 50%;
208
+ transform: translateX(-50%);
209
+ width: 310px;
210
+ height: 42px;
211
+ border-radius: 8px;
212
+ opacity: 0.8;
213
+ background: #333333;
214
+ z-index: 10;
215
+ span {
216
+ color: white;
217
+ padding: 0 5px;
218
+ }
219
+ }
220
+ }
221
+ </style>
@@ -0,0 +1,256 @@
1
+ import { ref, reactive, computed } from 'vue'
2
+
3
+ // 缩放范围常量(图片和 PDF 共用)
4
+ export const minScale = 0.5
5
+ export const maxScale = 4
6
+ export const zoomFactor = 0.5
7
+
8
+ /**
9
+ * 图片拖拽 + 滚轮缩放 + 旋转 composable
10
+ * 独立状态,每个图片预览实例互不干扰
11
+ */
12
+ export const useImageDragZoom = () => {
13
+ const scaleValue = ref(1)
14
+ const offsetX = ref(0)
15
+ const offsetY = ref(0)
16
+ const rotateDeg = ref(0)
17
+ const targetEleRef = ref<HTMLElement | null>(null)
18
+ let dragMoveHandler = (e: MouseEvent) => {}
19
+ let dragUpHandler = () => {}
20
+
21
+ /**
22
+ * 从 ref 解析真实 DOM 元素
23
+ * targetEleRef 可能挂在原生元素上,也可能挂在 Vue 组件(如 el-image)上,
24
+ * 后者的 ref 值是组件实例,需要取其根 DOM 元素($el)。
25
+ */
26
+ const getEl = (): HTMLElement | null => {
27
+ const raw = targetEleRef.value as any
28
+ if (!raw) return null
29
+ if (raw.nodeType === 1) return raw as HTMLElement // 原生 DOM 元素
30
+ if (raw.$el && raw.$el.nodeType === 1) return raw.$el as HTMLElement // Vue 组件根元素
31
+ return null
32
+ }
33
+
34
+ /**
35
+ * 应用变换样式(缩放 + 偏移 + 旋转)
36
+ */
37
+ const applyTransform = () => {
38
+ const el = getEl()
39
+ if (!el) return
40
+ el.style.transform = `rotate(${rotateDeg.value}deg)
41
+ scale(${scaleValue.value})
42
+ translate(${offsetX.value}px, ${offsetY.value}px)
43
+ `
44
+ }
45
+
46
+ /**
47
+ * 设置拖动事件监听器
48
+ */
49
+ const setupDragEvents = () => {
50
+ const el = getEl()
51
+ if (!el) return
52
+
53
+ let isDragging = false
54
+ let startX = 0
55
+ let startY = 0
56
+
57
+ // 清理旧监听器(防止重复绑定)
58
+ document.removeEventListener('mousemove', dragMoveHandler)
59
+ document.removeEventListener('mouseup', dragUpHandler)
60
+
61
+ // 新监听器
62
+ const moveHandler = (e: MouseEvent) => {
63
+ if (!isDragging) return
64
+ offsetX.value = e.clientX - startX
65
+ offsetY.value = e.clientY - startY
66
+ applyTransform()
67
+ }
68
+
69
+ const upHandler = () => {
70
+ isDragging = false
71
+ el.style.cursor = 'grab'
72
+ }
73
+
74
+ // 保存引用用于下次清理
75
+ dragMoveHandler = moveHandler
76
+ dragUpHandler = upHandler
77
+
78
+ el.addEventListener('mousedown', (e: MouseEvent) => {
79
+ e.preventDefault()
80
+ isDragging = true
81
+ startX = e.clientX - offsetX.value
82
+ startY = e.clientY - offsetY.value
83
+ el.style.cursor = 'grabbing'
84
+ })
85
+
86
+ document.addEventListener('mousemove', moveHandler)
87
+ document.addEventListener('mouseup', upHandler)
88
+ }
89
+
90
+ /**
91
+ * 设置滚轮缩放事件监听器
92
+ */
93
+ const setupWheelEvent = () => {
94
+ const el = getEl()
95
+ if (!el) return
96
+
97
+ el.addEventListener(
98
+ 'wheel',
99
+ (e: WheelEvent) => {
100
+ e.preventDefault()
101
+
102
+ if (e.deltaY < 0) {
103
+ if (scaleValue.value < maxScale) scaleValue.value += zoomFactor
104
+ } else {
105
+ if (scaleValue.value > minScale) scaleValue.value -= zoomFactor
106
+ }
107
+
108
+ applyTransform()
109
+ },
110
+ { passive: false }
111
+ )
112
+ }
113
+
114
+ /**
115
+ * 初始化缩放、旋转、偏移等状态
116
+ */
117
+ const resetImageInfo = () => {
118
+ scaleValue.value = 1
119
+ offsetX.value = 0
120
+ offsetY.value = 0
121
+ rotateDeg.value = 0
122
+ applyTransform()
123
+ }
124
+
125
+ /**
126
+ * 旋转图片
127
+ */
128
+ const useRotateImg = () => {
129
+ const el = getEl()
130
+ if (el) {
131
+ rotateDeg.value += 90
132
+ el.style.transform = `rotate(${rotateDeg.value}deg)`
133
+ el.style.transition = 'transform 0.3s ease'
134
+ }
135
+ }
136
+
137
+ /**
138
+ * 放大
139
+ */
140
+ const pageZoomOut = () => {
141
+ if (scaleValue.value < maxScale) {
142
+ scaleValue.value += zoomFactor
143
+ applyTransform()
144
+ }
145
+ }
146
+
147
+ /**
148
+ * 缩小
149
+ */
150
+ const pageZoomIn = () => {
151
+ if (scaleValue.value > minScale) {
152
+ scaleValue.value -= zoomFactor
153
+ applyTransform()
154
+ }
155
+ }
156
+
157
+ return {
158
+ targetEleRef,
159
+ scaleValue,
160
+ setupDragEvents,
161
+ setupWheelEvent,
162
+ resetImageInfo,
163
+ useRotateImg,
164
+ pageZoomOut,
165
+ pageZoomIn
166
+ }
167
+ }
168
+
169
+ /**
170
+ * PDF 拖拽 + 滚轮缩放 composable
171
+ * 独立状态,每个 PDF 实例互不干扰
172
+ */
173
+ export const usePdfDragZoom = () => {
174
+ const state = reactive({
175
+ scaleValue: 1,
176
+ isDragging: false,
177
+ startX: 0,
178
+ startY: 0,
179
+ offsetX: 0,
180
+ offsetY: 0
181
+ })
182
+ const wrapRef = ref<HTMLElement | null>(null)
183
+
184
+ // 缩放 + 拖拽偏移的 transform 样式
185
+ const scaleFun = computed(() => ({
186
+ width: '58%',
187
+ height: '100%',
188
+ transformOrigin: 'top center',
189
+ transform: `translate(${state.offsetX}px, ${state.offsetY}px) scale(${state.scaleValue})`
190
+ }))
191
+
192
+ // 放大
193
+ const pageZoomOut = () => {
194
+ if (state.scaleValue < maxScale) {
195
+ state.scaleValue += zoomFactor
196
+ }
197
+ }
198
+
199
+ // 缩小
200
+ const pageZoomIn = () => {
201
+ if (state.scaleValue > minScale) {
202
+ state.scaleValue -= zoomFactor
203
+ }
204
+ }
205
+
206
+ // 重置缩放和偏移
207
+ const resetZoom = () => {
208
+ state.scaleValue = 1
209
+ state.offsetX = 0
210
+ state.offsetY = 0
211
+ }
212
+
213
+ // 鼠标拖拽开始
214
+ const onDragStart = (e: MouseEvent) => {
215
+ if (state.scaleValue <= 1) return
216
+ state.isDragging = true
217
+ state.startX = e.clientX - state.offsetX
218
+ state.startY = e.clientY - state.offsetY
219
+ if (wrapRef.value) wrapRef.value.style.cursor = 'grabbing'
220
+ }
221
+
222
+ // 鼠标拖拽移动
223
+ const onDragMove = (e: MouseEvent) => {
224
+ if (!state.isDragging) return
225
+ state.offsetX = e.clientX - state.startX
226
+ state.offsetY = e.clientY - state.startY
227
+ }
228
+
229
+ // 鼠标拖拽结束
230
+ const onDragEnd = () => {
231
+ state.isDragging = false
232
+ if (wrapRef.value) wrapRef.value.style.cursor = 'grab'
233
+ }
234
+
235
+ // 鼠标滚轮缩放
236
+ const onWheel = (e: WheelEvent) => {
237
+ if (e.deltaY < 0) {
238
+ pageZoomOut()
239
+ } else {
240
+ pageZoomIn()
241
+ }
242
+ }
243
+
244
+ return {
245
+ state,
246
+ wrapRef,
247
+ scaleFun,
248
+ pageZoomOut,
249
+ pageZoomIn,
250
+ resetZoom,
251
+ onDragStart,
252
+ onDragMove,
253
+ onDragEnd,
254
+ onWheel
255
+ }
256
+ }
@@ -0,0 +1,171 @@
1
+ .is-fullscreen .dialog-content {
2
+ // height: calc(100vh - 90px);
3
+ height: 100%;
4
+ }
5
+
6
+ .el-dialog__body {
7
+ height: calc(100vh - 100px);
8
+ }
9
+
10
+ .dialog-content {
11
+ overflow: hidden;
12
+ height: calc(75vh - 20px);
13
+ // height: 100%;
14
+ margin: -5px;
15
+
16
+ .left-list {
17
+ height: 100%;
18
+
19
+ .el-scrollbar {
20
+ height: calc(100% - 40px);
21
+ }
22
+
23
+ .footer {
24
+ height: 40px;
25
+ text-align: center;
26
+ font-size: 14px;
27
+ line-height: 40px;
28
+ font-weight: 600;
29
+ color: #333333;
30
+ }
31
+ }
32
+
33
+ .thumbnail {
34
+ flex-wrap: wrap;
35
+ width: 350px;
36
+ height: 100%;
37
+ overflow: hidden;
38
+
39
+ &.single {
40
+ width: 180px;
41
+ }
42
+ .thumbnail-item {
43
+ margin: 10px;
44
+ width: 150px;
45
+
46
+ .thumbnail-box {
47
+ width: 150px;
48
+ height: 92px;
49
+ border-radius: 4px;
50
+ border: 2px solid transparent;
51
+ background: #f6f7f9;
52
+ box-sizing: border-box;
53
+ &.active-item {
54
+ border: 2px solid var(--el-color-primary);
55
+ }
56
+ &.pdf-box {
57
+ padding: 18px;
58
+ }
59
+ }
60
+ .thumbnail-image {
61
+ width: 100%;
62
+ height: 100%;
63
+ object-fit: contain;
64
+ }
65
+ .fileName {
66
+ width: 150px;
67
+ height: 22px;
68
+ text-align: left;
69
+ font-size: 14px;
70
+ line-height: 22px;
71
+ }
72
+ }
73
+ }
74
+ .preview {
75
+ position: relative;
76
+ flex: 1;
77
+ height: 100%;
78
+ display: flex;
79
+ flex-direction: column;
80
+ .fileName {
81
+ font-size: 16px;
82
+ line-height: 26px;
83
+ font-weight: 600;
84
+ }
85
+
86
+ .preview-item {
87
+ flex: 1;
88
+ height: 100%;
89
+ background-color: #f6f7f9;
90
+ overflow: hidden;
91
+ padding: 10px;
92
+ .preview-image {
93
+ width: 100%;
94
+ height: 100%;
95
+ object-fit: contain;
96
+ pointer-events: auto;
97
+ touch-action: none;
98
+ user-select: none;
99
+ cursor: grab;
100
+ will-change: transform;
101
+ transform-origin: center;
102
+ }
103
+ .circle {
104
+ width: 48px;
105
+ height: 48px;
106
+ border-radius: 50%;
107
+ opacity: 0.8;
108
+ border: 1px solid #bbbfc2;
109
+ background: #ffffffcc;
110
+ }
111
+
112
+ .previous {
113
+ position: absolute;
114
+ left: 24px;
115
+ top: 50%;
116
+ transform: translateY(-50%);
117
+ z-index: 10;
118
+ cursor: pointer;
119
+ }
120
+ .next {
121
+ position: absolute;
122
+ right: 24px;
123
+ top: 50%;
124
+ transform: translateY(-50%);
125
+ z-index: 10;
126
+ cursor: pointer;
127
+ }
128
+ }
129
+
130
+ .page-tool {
131
+ position: absolute;
132
+ bottom: 16px;
133
+ left: 50%;
134
+ right: 50%;
135
+ transform: translateX(-50%);
136
+ width: 378px;
137
+ height: 42px;
138
+ border-radius: 8px;
139
+ opacity: 0.8;
140
+ background: #333333;
141
+ z-index: 10;
142
+ span {
143
+ color: #fff;
144
+ padding: 0 5px;
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ // @media print {
151
+ // @page {
152
+ // size: A4; /* 或其他你需要的页面大小 */
153
+ // margin: 10mm; /* 设置合适的边距 */
154
+ // }
155
+ // }
156
+
157
+ // @media print {
158
+ // @page {
159
+ // size: auto;
160
+ // margin: 0;
161
+ // }
162
+ // body {
163
+ // margin: 0;
164
+ // padding: 0;
165
+ // img {
166
+ // width: 100%;
167
+ // height: 100%;
168
+ // object-fit: contain;
169
+ // }
170
+ // }
171
+ // }
@@ -0,0 +1,68 @@
1
+ <template>
2
+ <!-- <span class="ml10">请上传 .xls , .xlsx 标准格式文件,文件最大为 {{ parameter.fileSize }}M</span> -->
3
+ <jzt-dialog
4
+ v-model="dialogVisible"
5
+ :title="title"
6
+ width="75%"
7
+ :cancel-text="false"
8
+ :confirm-text="false"
9
+ :show-footer="false"
10
+ @close="closeDialog"
11
+ >
12
+ <previewFile ref="previewFileRef" :showList="showList" :showHeader="showHeader">
13
+ <template v-if="slots.leftContent" #leftContent>
14
+ <slot name="leftContent"></slot>
15
+ </template>
16
+ </previewFile>
17
+ </jzt-dialog>
18
+ </template>
19
+
20
+ <script setup lang="ts" name="JztFilePreview">
21
+ import { ref, nextTick, useSlots } from 'vue'
22
+ import { FileItemProps } from './interface/index'
23
+ import JztDialog from '../JztDialog/index.vue'
24
+ import previewFile from './previewFile.vue'
25
+
26
+ export interface FilePreview {
27
+ title?: string
28
+ showList?: boolean
29
+ showHeader?: boolean
30
+ }
31
+ const props = withDefaults(defineProps<FilePreview>(), {
32
+ title: '证照预览',
33
+ showList: true, // 是否展示左边的缩略图列表
34
+ showHeader: true // 是否展示头部
35
+ })
36
+ const slots = useSlots()
37
+ const dialogVisible = ref(false)
38
+ const previewFileRef = ref()
39
+
40
+ /**
41
+ * @description 打开预览弹框
42
+ * @param file 文件
43
+ * @param number 点击打开的是第几个文件
44
+ * */
45
+ const openDialog = (list: string, curIndex: number = 0) => {
46
+ dialogVisible.value = true
47
+ nextTick(() => {
48
+ previewFileRef.value.setFileInfo(list, curIndex)
49
+ })
50
+ }
51
+
52
+ // 关闭弹框
53
+ const closeDialog = () => {
54
+ dialogVisible.value = false
55
+ previewFileRef.value.closePreview()
56
+ }
57
+
58
+ defineExpose({
59
+ openDialog
60
+ })
61
+ </script>
62
+ <style lang="scss" scoped>
63
+ @use './index';
64
+
65
+ .iconfont {
66
+ font-size: 22px;
67
+ }
68
+ </style>