@xilonglab/vue-main 1.1.20 → 1.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xilonglab/vue-main",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "description": "xilong vue main",
5
5
  "main": "packages/index.js",
6
6
  "scripts": {
@@ -1,355 +0,0 @@
1
- <script setup>
2
- defineOptions({ name: "XlSignatureInput" })
3
-
4
- import { ref, computed } from 'vue'
5
- import {
6
- Edit,
7
- Check,
8
- RefreshLeft,
9
- Close,
10
- Document,
11
- InfoFilled
12
- } from '@element-plus/icons-vue'
13
-
14
- const emits = defineEmits(['change', 'update:modelValue'])
15
-
16
- const props = defineProps({
17
- modelValue: {
18
- default: "",
19
- },
20
- api: {
21
- type: Function,
22
- default: () => { },
23
- },
24
- params: {
25
- type: Object,
26
- default: () => ({})
27
- },
28
- disabled: {
29
- default: false,
30
- },
31
- width: {
32
- default: 400
33
- },
34
- height: {
35
- default: 200
36
- }
37
- })
38
-
39
- const refs = {
40
- pad: ref(null)
41
- }
42
- const editing = ref(false)
43
- const loading = ref(false)
44
- const saving = ref(false)
45
-
46
- const url = computed({
47
- get() {
48
- return `/storage/${props.modelValue.uri}`;
49
- },
50
- set(data) {
51
- emits('change', data)
52
- emits('update:modelValue', data)
53
- },
54
- });
55
-
56
- const handlers = {
57
- async save() {
58
- const { api, params } = props
59
- const base64 = refs.pad.value.save('image/png')
60
- saving.value = true
61
- try {
62
- const data = await api({ ...params, base64 })
63
- emits('update:modelValue', data)
64
- editing.value = false
65
- } catch (error) {
66
- console.error('保存签名失败:', error)
67
- } finally {
68
- saving.value = false
69
- }
70
- },
71
- clear() {
72
- refs.pad.value.clear()
73
- },
74
- edit() {
75
- editing.value = true
76
- }
77
- }
78
-
79
- const handleImageError = () => {
80
- console.warn('签名图片加载失败')
81
- }
82
-
83
- </script>
84
-
85
- <template>
86
- <div class="xl-signature-input" :class="{ 'disabled': disabled }">
87
- <div class="signature-wrapper" :style="{ width: width + 'px', height: height + 'px' }">
88
- <!-- 编辑模式 -->
89
- <div v-if="editing" class="signature-pad">
90
- <Vue3Signature
91
- class="pad"
92
- :ref="refs.pad"
93
- :width="width"
94
- :height="height"
95
- />
96
- <div class="pad-overlay">
97
- <div class="hint-text">请在下方区域进行签名</div>
98
- </div>
99
- </div>
100
-
101
- <!-- 预览模式 -->
102
- <div v-else class="signature-preview">
103
- <div v-if="modelValue && modelValue.uri" class="image-container">
104
- <img
105
- v-loading="loading"
106
- :src="url"
107
- :alt="'签名图片'"
108
- @error="handleImageError"
109
- />
110
- <div class="image-overlay">
111
- <div class="preview-actions">
112
- <el-button
113
- type="primary"
114
- size="small"
115
- :icon="Edit"
116
- @click="handlers.edit"
117
- >
118
- 重新签名
119
- </el-button>
120
- </div>
121
- </div>
122
- </div>
123
- <div v-else class="empty-state">
124
- <div class="empty-icon">
125
- <el-icon size="48"><Document /></el-icon>
126
- </div>
127
- <div class="empty-text">暂无签名</div>
128
- <el-button
129
- type="primary"
130
- :icon="Edit"
131
- @click="handlers.edit"
132
- :disabled="disabled"
133
- >
134
- 开始签名
135
- </el-button>
136
- </div>
137
- </div>
138
- </div>
139
-
140
- <!-- 操作按钮 -->
141
- <div v-if="editing" class="signature-controls">
142
- <div class="control-buttons">
143
- <el-button
144
- type="success"
145
- :loading="saving"
146
- :icon="Check"
147
- @click="handlers.save"
148
- >
149
- 保存签名
150
- </el-button>
151
- <el-button
152
- type="warning"
153
- :icon="RefreshLeft"
154
- @click="handlers.clear"
155
- >
156
- 清空重写
157
- </el-button>
158
- <el-button
159
- :icon="Close"
160
- @click="editing = false"
161
- >
162
- 取消
163
- </el-button>
164
- </div>
165
- <div class="signature-tips">
166
- <el-icon><InfoFilled /></el-icon>
167
- <span>请使用鼠标或触控笔进行签名</span>
168
- </div>
169
- </div>
170
- </div>
171
- </template>
172
-
173
- <style lang="less">
174
- .xl-signature-input {
175
- display: flex;
176
- flex-direction: column;
177
- align-items: center;
178
- gap: 12px;
179
-
180
- &.disabled {
181
- opacity: 0.6;
182
- pointer-events: none;
183
- }
184
-
185
- .signature-wrapper {
186
- position: relative;
187
- border: 2px dashed #d9d9d9;
188
- border-radius: 8px;
189
- background: #fafafa;
190
- transition: all 0.3s ease;
191
- overflow: hidden;
192
- margin: 0 auto;
193
-
194
- &:hover {
195
- border-color: #409eff;
196
- background: #f0f9ff;
197
- }
198
-
199
- .signature-pad {
200
- position: relative;
201
- width: 100%;
202
- height: 100%;
203
-
204
- .pad {
205
- width: 100%;
206
- height: 100%;
207
- background: white;
208
- border-radius: 6px;
209
- }
210
-
211
- .pad-overlay {
212
- position: absolute;
213
- top: 0;
214
- left: 0;
215
- right: 0;
216
- bottom: 0;
217
- pointer-events: none;
218
- display: flex;
219
- align-items: center;
220
- justify-content: center;
221
- z-index: 1;
222
-
223
- .hint-text {
224
- background: rgba(0, 0, 0, 0.7);
225
- color: white;
226
- padding: 8px 16px;
227
- border-radius: 4px;
228
- font-size: 14px;
229
- opacity: 0;
230
- animation: fadeInOut 2s infinite;
231
- }
232
- }
233
- }
234
-
235
- .signature-preview {
236
- width: 100%;
237
- height: 100%;
238
- position: relative;
239
-
240
- .image-container {
241
- position: relative;
242
- width: 100%;
243
- height: 100%;
244
- display: flex;
245
- align-items: center;
246
- justify-content: center;
247
-
248
- img {
249
- max-width: 100%;
250
- max-height: 100%;
251
- object-fit: contain;
252
- border-radius: 6px;
253
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
254
- }
255
-
256
- .image-overlay {
257
- position: absolute;
258
- top: 0;
259
- left: 0;
260
- right: 0;
261
- bottom: 0;
262
- background: rgba(0, 0, 0, 0.5);
263
- display: flex;
264
- align-items: center;
265
- justify-content: center;
266
- opacity: 0;
267
- transition: opacity 0.3s ease;
268
-
269
- &:hover {
270
- opacity: 1;
271
- }
272
-
273
- .preview-actions {
274
- .el-button {
275
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
276
- }
277
- }
278
- }
279
-
280
- &:hover .image-overlay {
281
- opacity: 1;
282
- }
283
- }
284
-
285
- .empty-state {
286
- display: flex;
287
- flex-direction: column;
288
- align-items: center;
289
- justify-content: center;
290
- height: 100%;
291
- padding: 20px;
292
- text-align: center;
293
-
294
- .empty-icon {
295
- color: #c0c4cc;
296
- margin-bottom: 12px;
297
- }
298
-
299
- .empty-text {
300
- color: #909399;
301
- font-size: 14px;
302
- margin-bottom: 16px;
303
- }
304
- }
305
- }
306
- }
307
-
308
- .signature-controls {
309
- display: flex;
310
- flex-direction: column;
311
- align-items: center;
312
- gap: 8px;
313
- width: 100%;
314
-
315
- .control-buttons {
316
- display: flex;
317
- gap: 8px;
318
- justify-content: center;
319
- flex-wrap: wrap;
320
- }
321
-
322
- .signature-tips {
323
- display: flex;
324
- align-items: center;
325
- justify-content: center;
326
- gap: 4px;
327
- color: #909399;
328
- font-size: 12px;
329
- padding: 4px 8px;
330
- background: #f5f7fa;
331
- border-radius: 4px;
332
- }
333
- }
334
- }
335
-
336
- @keyframes fadeInOut {
337
- 0%, 100% { opacity: 0; }
338
- 50% { opacity: 1; }
339
- }
340
-
341
- // 响应式设计
342
- @media (max-width: 768px) {
343
- .xl-signature-input {
344
- .signature-controls {
345
- .control-buttons {
346
- flex-direction: column;
347
-
348
- .el-button {
349
- width: 100%;
350
- }
351
- }
352
- }
353
- }
354
- }
355
- </style>