@file-ud.js/plugins 0.1.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.
- package/README.md +583 -0
- package/dist/downloader/index.d.mts +2 -0
- package/dist/downloader/index.d.ts +2 -0
- package/dist/downloader/index.js +126 -0
- package/dist/downloader/index.js.map +1 -0
- package/dist/downloader/index.mjs +124 -0
- package/dist/downloader/index.mjs.map +1 -0
- package/dist/index-CVuMEvjg.d.ts +201 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +781 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +773 -0
- package/dist/index.mjs.map +1 -0
- package/dist/retry/index.d.mts +84 -0
- package/dist/retry/index.d.ts +84 -0
- package/dist/retry/index.js +126 -0
- package/dist/retry/index.js.map +1 -0
- package/dist/retry/index.mjs +124 -0
- package/dist/retry/index.mjs.map +1 -0
- package/dist/uploader/index.d.mts +2 -0
- package/dist/uploader/index.d.ts +2 -0
- package/dist/uploader/index.js +658 -0
- package/dist/uploader/index.js.map +1 -0
- package/dist/uploader/index.mjs +652 -0
- package/dist/uploader/index.mjs.map +1 -0
- package/package.json +78 -0
- package/src/uploader/compress/README.md +388 -0
- package/src/uploader/validator/README.md +563 -0
- package/src/uploader/watermark/README.md +498 -0
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
# 水印插件 (WatermarkPlugin)
|
|
2
|
+
|
|
3
|
+
## 📖 功能介绍
|
|
4
|
+
|
|
5
|
+
水印插件可以在上传前自动为图片添加文字或图片水印,保护版权和标识来源。
|
|
6
|
+
|
|
7
|
+
### ✨ 核心特性
|
|
8
|
+
|
|
9
|
+
- ✅ **双模式支持**:文字水印和图片水印
|
|
10
|
+
- ✅ **多位置选择**:5个预设位置(四角+中心)
|
|
11
|
+
- ✅ **透明度控制**:可调节水印透明度
|
|
12
|
+
- ✅ **样式自定义**:字体、颜色、大小均可配置
|
|
13
|
+
- ✅ **完全非侵入式**:通过插件系统实现,不改动核心代码
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 🚀 快速开始
|
|
18
|
+
|
|
19
|
+
### 1. 安装插件
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @file-ud.js/plugins
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 2. 基本使用 - 文字水印
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { FileUD } from '@file-ud.js/core';
|
|
29
|
+
import { WatermarkPlugin } from '@file-ud.js/plugins/uploader';
|
|
30
|
+
|
|
31
|
+
const uploader = FileUD.createUploader("myUploader", {
|
|
32
|
+
action: '/api/upload',
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 使用默认文字水印
|
|
36
|
+
uploader.use(new WatermarkPlugin({
|
|
37
|
+
text: "© MyCompany"
|
|
38
|
+
}));
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 3. 图片水印
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
uploader.use(new WatermarkPlugin({
|
|
45
|
+
imageUrl: "https://example.com/logo.png",
|
|
46
|
+
imageWidth: 100,
|
|
47
|
+
imageHeight: 100,
|
|
48
|
+
position: "bottom-right"
|
|
49
|
+
}));
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## ⚙️ 配置选项
|
|
55
|
+
|
|
56
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
57
|
+
|------|------|--------|------|
|
|
58
|
+
| `text` | `string` | `"© FileUD"` | 水印文字内容 |
|
|
59
|
+
| `imageUrl` | `string` | `""` | 水印图片 URL(与 text 二选一) |
|
|
60
|
+
| `position` | `"top-left" \| "top-right" \| "bottom-left" \| "bottom-right" \| "center"` | `"bottom-right"` | 水印位置 |
|
|
61
|
+
| `opacity` | `number` | `0.6` | 透明度(0-1),0 完全透明,1 完全不透明 |
|
|
62
|
+
| `fontSize` | `number` | `24` | 字体大小(像素) |
|
|
63
|
+
| `color` | `string` | `"#ffffff"` | 字体颜色(CSS 颜色值) |
|
|
64
|
+
| `padding` | `number` | `20` | 边距(像素),水印距离边缘的距离 |
|
|
65
|
+
| `imageWidth` | `number` | `100` | 水印图片宽度(像素) |
|
|
66
|
+
| `imageHeight` | `number` | `100` | 水印图片高度(像素) |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 📊 使用示例
|
|
71
|
+
|
|
72
|
+
### 示例 1:右下角文字水印
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
new WatermarkPlugin({
|
|
76
|
+
text: "© 2024 MyCompany",
|
|
77
|
+
position: "bottom-right",
|
|
78
|
+
fontSize: 28,
|
|
79
|
+
color: "#ffffff",
|
|
80
|
+
opacity: 0.7,
|
|
81
|
+
padding: 30
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 效果:在图片右下角显示半透明白色文字
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 示例 2:居中品牌水印
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
new WatermarkPlugin({
|
|
91
|
+
text: "CONFIDENTIAL",
|
|
92
|
+
position: "center",
|
|
93
|
+
fontSize: 48,
|
|
94
|
+
color: "#ff0000",
|
|
95
|
+
opacity: 0.3,
|
|
96
|
+
padding: 0
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 效果:在图片中央显示红色半透明大字
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 示例 3:左上角 Logo 水印
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
new WatermarkPlugin({
|
|
106
|
+
imageUrl: "https://cdn.example.com/logo.png",
|
|
107
|
+
position: "top-left",
|
|
108
|
+
imageWidth: 80,
|
|
109
|
+
imageHeight: 80,
|
|
110
|
+
opacity: 0.8,
|
|
111
|
+
padding: 20
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// 效果:在图片左上角显示公司 Logo
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 示例 4:平铺水印(高级技巧)
|
|
118
|
+
|
|
119
|
+
虽然插件不直接支持平铺,但可以通过多次调用实现:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// 方案:使用较大的透明 PNG 作为水印图片
|
|
123
|
+
new WatermarkPlugin({
|
|
124
|
+
imageUrl: "data:image/png;base64,iVBORw0KGgo...", // 平铺图案
|
|
125
|
+
position: "center",
|
|
126
|
+
opacity: 0.1,
|
|
127
|
+
imageWidth: 400,
|
|
128
|
+
imageHeight: 400
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 💡 高级用法
|
|
135
|
+
|
|
136
|
+
### 1. 根据图片尺寸动态调整
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
uploader.use(new WatermarkPlugin({
|
|
140
|
+
text: "© MyCompany",
|
|
141
|
+
fontSize: 24, // 固定大小
|
|
142
|
+
|
|
143
|
+
// 或者在运行时动态计算
|
|
144
|
+
onFileSelect: async (file, context) => {
|
|
145
|
+
const img = new Image();
|
|
146
|
+
const url = URL.createObjectURL(file.File);
|
|
147
|
+
|
|
148
|
+
return new Promise((resolve) => {
|
|
149
|
+
img.onload = () => {
|
|
150
|
+
URL.revokeObjectURL(url);
|
|
151
|
+
|
|
152
|
+
// 根据图片宽度动态调整字体大小
|
|
153
|
+
const dynamicFontSize = Math.max(24, Math.floor(img.width / 50));
|
|
154
|
+
|
|
155
|
+
// 更新插件配置(需要重新创建插件实例)
|
|
156
|
+
resolve(file);
|
|
157
|
+
};
|
|
158
|
+
img.src = url;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}));
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 2. 结合压缩插件使用
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import {
|
|
168
|
+
WatermarkPlugin,
|
|
169
|
+
CompressImagePlugin,
|
|
170
|
+
FileValidatorPlugin
|
|
171
|
+
} from '@file-ud.js/plugins/uploader';
|
|
172
|
+
|
|
173
|
+
uploader.use([
|
|
174
|
+
// 1. 文件校验
|
|
175
|
+
new FileValidatorPlugin({
|
|
176
|
+
maxSize: 10 * 1024 * 1024,
|
|
177
|
+
accept: ['image/*']
|
|
178
|
+
}),
|
|
179
|
+
|
|
180
|
+
// 2. 添加水印(先加水印)
|
|
181
|
+
new WatermarkPlugin({
|
|
182
|
+
text: "© MyCompany",
|
|
183
|
+
position: "bottom-right"
|
|
184
|
+
}),
|
|
185
|
+
|
|
186
|
+
// 3. 图片压缩(后压缩,减小文件大小)
|
|
187
|
+
new CompressImagePlugin({
|
|
188
|
+
quality: 0.8,
|
|
189
|
+
format: "webp"
|
|
190
|
+
})
|
|
191
|
+
]);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### 3. 条件性添加水印
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
// 只为特定类型的图片添加水印
|
|
198
|
+
const shouldAddWatermark = (file: File) => {
|
|
199
|
+
// 只对照片添加水印,不对截图添加
|
|
200
|
+
return file.size > 1024 * 1024; // 大于 1MB 的图片
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (shouldAddWatermark(selectedFile)) {
|
|
204
|
+
uploader.use(new WatermarkPlugin({
|
|
205
|
+
text: "© MyCompany"
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## 🔍 工作原理
|
|
213
|
+
|
|
214
|
+
### 文字水印流程
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
1. 用户选择图片
|
|
218
|
+
↓
|
|
219
|
+
2. 插件拦截文件(onFileSelect 钩子)
|
|
220
|
+
↓
|
|
221
|
+
3. 创建 Canvas 并绘制原图
|
|
222
|
+
↓
|
|
223
|
+
4. 设置文字样式(字体、颜色、透明度)
|
|
224
|
+
↓
|
|
225
|
+
5. 计算文字位置(根据 position 和 padding)
|
|
226
|
+
↓
|
|
227
|
+
6. 在 Canvas 上绘制文字
|
|
228
|
+
↓
|
|
229
|
+
7. 导出为新的 File 对象
|
|
230
|
+
↓
|
|
231
|
+
8. 替换原文件,继续上传流程
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 图片水印流程
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
1. 用户选择图片
|
|
238
|
+
↓
|
|
239
|
+
2. 加载水印图片(处理跨域)
|
|
240
|
+
↓
|
|
241
|
+
3. 创建 Canvas 并绘制原图
|
|
242
|
+
↓
|
|
243
|
+
4. 计算水印图片位置和尺寸
|
|
244
|
+
↓
|
|
245
|
+
5. 在 Canvas 上绘制水印图片
|
|
246
|
+
↓
|
|
247
|
+
6. 导出为新的 File 对象
|
|
248
|
+
↓
|
|
249
|
+
7. 替换原文件,继续上传流程
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 🎯 最佳实践
|
|
255
|
+
|
|
256
|
+
### 1. 选择合适的透明度
|
|
257
|
+
|
|
258
|
+
| 用途 | 推荐透明度 | 说明 |
|
|
259
|
+
|------|-----------|------|
|
|
260
|
+
| **版权保护** | 0.3 - 0.5 | 明显但不影响观看 |
|
|
261
|
+
| **品牌标识** | 0.6 - 0.8 | 清晰可见 |
|
|
262
|
+
| **防伪标记** | 0.1 - 0.2 | 隐约可见,不影响主体 |
|
|
263
|
+
| **重要声明** | 0.7 - 0.9 | 非常醒目 |
|
|
264
|
+
|
|
265
|
+
### 2. 位置选择建议
|
|
266
|
+
|
|
267
|
+
| 位置 | 适用场景 | 优点 | 缺点 |
|
|
268
|
+
|------|---------|------|------|
|
|
269
|
+
| **bottom-right** ⭐ | 通用推荐 | 不遮挡主体,符合习惯 | 容易被裁剪 |
|
|
270
|
+
| **center** | 防盗用 | 难以去除 | 影响观看体验 |
|
|
271
|
+
| **top-left** | 品牌展示 | 第一眼看到 | 可能遮挡重要内容 |
|
|
272
|
+
| **bottom-left** | 次要信息 | 低调不显眼 | 容易被忽略 |
|
|
273
|
+
| **top-right** | 时间戳等 | 符合阅读习惯 | 同上 |
|
|
274
|
+
|
|
275
|
+
### 3. 字体大小设置
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// ❌ 不推荐:固定小字体,大图看不清
|
|
279
|
+
new WatermarkPlugin({
|
|
280
|
+
fontSize: 12 // 太小!
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// ✅ 推荐:根据图片尺寸动态调整
|
|
284
|
+
const getFontSize = (imageWidth: number) => {
|
|
285
|
+
return Math.max(24, Math.floor(imageWidth / 50));
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
new WatermarkPlugin({
|
|
289
|
+
fontSize: 28, // 适合 1920px 宽度的图片
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### 4. 颜色选择
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
// 白色文字 + 黑色描边(提高对比度)
|
|
297
|
+
new WatermarkPlugin({
|
|
298
|
+
color: "#ffffff",
|
|
299
|
+
// 注意:当前版本不支持描边,可以自行扩展
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// 深色背景用浅色文字
|
|
303
|
+
new WatermarkPlugin({
|
|
304
|
+
color: "#ffffff" // 白色
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// 浅色背景用深色文字
|
|
308
|
+
new WatermarkPlugin({
|
|
309
|
+
color: "#000000" // 黑色
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 🐛 常见问题
|
|
316
|
+
|
|
317
|
+
### Q1: 水印图片跨域加载失败?
|
|
318
|
+
|
|
319
|
+
**错误信息**:`Tainted canvases may not be exported`
|
|
320
|
+
|
|
321
|
+
**原因**:水印图片来自不同域名,且未设置 CORS。
|
|
322
|
+
|
|
323
|
+
**解决方案**:
|
|
324
|
+
```typescript
|
|
325
|
+
// 方案1:确保水印图片服务器支持 CORS
|
|
326
|
+
// 在图片服务器响应头中添加:
|
|
327
|
+
// Access-Control-Allow-Origin: *
|
|
328
|
+
|
|
329
|
+
// 方案2:使用 Base64 编码的水印图片
|
|
330
|
+
const watermarkBase64 = "data:image/png;base64,iVBORw0KGgo...";
|
|
331
|
+
|
|
332
|
+
new WatermarkPlugin({
|
|
333
|
+
imageUrl: watermarkBase64
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// 方案3:将水印图片托管到同域名下
|
|
337
|
+
new WatermarkPlugin({
|
|
338
|
+
imageUrl: "/assets/watermark.png" // 同域名
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Q2: 文字水印显示乱码?
|
|
343
|
+
|
|
344
|
+
**原因**:Canvas 默认字体不支持中文。
|
|
345
|
+
|
|
346
|
+
**解决方案**:
|
|
347
|
+
```typescript
|
|
348
|
+
// 指定支持中文的字体
|
|
349
|
+
new WatermarkPlugin({
|
|
350
|
+
text: "版权所有",
|
|
351
|
+
// Canvas font 格式: "size family"
|
|
352
|
+
// 注意:当前插件使用 Arial,可能需要扩展支持自定义字体
|
|
353
|
+
});
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Q3: 水印位置不准确?
|
|
357
|
+
|
|
358
|
+
**原因**:padding 设置不当或图片尺寸特殊。
|
|
359
|
+
|
|
360
|
+
**解决方案**:
|
|
361
|
+
```typescript
|
|
362
|
+
// 调整 padding
|
|
363
|
+
new WatermarkPlugin({
|
|
364
|
+
position: "bottom-right",
|
|
365
|
+
padding: 30 // 增加边距
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Q4: 可以同时添加文字和图片水印吗?
|
|
370
|
+
|
|
371
|
+
**当前限制**:插件只支持一种水印类型(文字或图片)。
|
|
372
|
+
|
|
373
|
+
** workaround**:
|
|
374
|
+
```typescript
|
|
375
|
+
// 方案:创建一个包含文字的图片作为水印
|
|
376
|
+
const createTextWatermarkImage = (text: string): string => {
|
|
377
|
+
const canvas = document.createElement('canvas');
|
|
378
|
+
const ctx = canvas.getContext('2d');
|
|
379
|
+
canvas.width = 400;
|
|
380
|
+
canvas.height = 100;
|
|
381
|
+
|
|
382
|
+
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
|
|
383
|
+
ctx.font = '48px Arial';
|
|
384
|
+
ctx.fillText(text, 20, 70);
|
|
385
|
+
|
|
386
|
+
return canvas.toDataURL();
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
new WatermarkPlugin({
|
|
390
|
+
imageUrl: createTextWatermarkImage("© MyCompany"),
|
|
391
|
+
imageWidth: 400,
|
|
392
|
+
imageHeight: 100
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 📈 性能建议
|
|
399
|
+
|
|
400
|
+
### 1. 优化水印图片
|
|
401
|
+
|
|
402
|
+
- 使用 PNG 格式(支持透明)
|
|
403
|
+
- 尺寸不要过大(建议 100-200px)
|
|
404
|
+
- 提前压缩水印图片
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
// ✅ 推荐:小而清晰的水印
|
|
408
|
+
new WatermarkPlugin({
|
|
409
|
+
imageUrl: "/watermark-small.png",
|
|
410
|
+
imageWidth: 100,
|
|
411
|
+
imageHeight: 100
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// ❌ 不推荐:过大的水印
|
|
415
|
+
new WatermarkPlugin({
|
|
416
|
+
imageUrl: "/watermark-huge.png",
|
|
417
|
+
imageWidth: 1000, // 太大!
|
|
418
|
+
imageHeight: 1000
|
|
419
|
+
});
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### 2. 批量上传优化
|
|
423
|
+
|
|
424
|
+
水印添加在主线程执行,大批量上传时可能阻塞 UI:
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// 限制并发数量
|
|
428
|
+
uploader.updateConfig({
|
|
429
|
+
chunkOptions: {
|
|
430
|
+
maxConcurrent: 2
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## 🎨 设计建议
|
|
438
|
+
|
|
439
|
+
### 1. 版权保护水印
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
new WatermarkPlugin({
|
|
443
|
+
text: "© 2024 MyCompany. All rights reserved.",
|
|
444
|
+
position: "center",
|
|
445
|
+
fontSize: 36,
|
|
446
|
+
color: "#ffffff",
|
|
447
|
+
opacity: 0.3,
|
|
448
|
+
padding: 0
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### 2. 品牌标识水印
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
new WatermarkPlugin({
|
|
456
|
+
imageUrl: "https://cdn.mycompany.com/logo-transparent.png",
|
|
457
|
+
position: "top-left",
|
|
458
|
+
imageWidth: 120,
|
|
459
|
+
imageHeight: 40,
|
|
460
|
+
opacity: 0.9,
|
|
461
|
+
padding: 20
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### 3. 草稿/预览水印
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
new WatermarkPlugin({
|
|
469
|
+
text: "DRAFT",
|
|
470
|
+
position: "center",
|
|
471
|
+
fontSize: 72,
|
|
472
|
+
color: "#ff0000",
|
|
473
|
+
opacity: 0.2,
|
|
474
|
+
padding: 0
|
|
475
|
+
});
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
---
|
|
479
|
+
|
|
480
|
+
## 📝 更新日志
|
|
481
|
+
|
|
482
|
+
### v1.0.0 (2024-01-XX)
|
|
483
|
+
- ✨ 首次发布
|
|
484
|
+
- ✅ 支持文字水印
|
|
485
|
+
- ✅ 支持图片水印
|
|
486
|
+
- ✅ 5种位置选择
|
|
487
|
+
- ✅ 透明度控制
|
|
488
|
+
- ✅ 自定义样式
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## 🤝 贡献指南
|
|
493
|
+
|
|
494
|
+
欢迎提交 Issue 和 Pull Request!
|
|
495
|
+
|
|
496
|
+
**报告 Bug**:[GitHub Issues](https://github.com/your-repo/file-ud/issues)
|
|
497
|
+
|
|
498
|
+
**提出建议**:[Feature Requests](https://github.com/your-repo/file-ud/discussions)
|