xw-devtool-cli 1.0.25 → 1.0.27
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 +13 -1
- package/README_EN.md +2 -0
- package/package.json +1 -1
- package/src/commands/baseConvert.js +111 -0
- package/src/commands/crosshair.js +94 -0
- package/src/index.js +10 -0
- package/src/locales/en.js +15 -1
- package/src/locales/zh.js +19 -1
package/README.md
CHANGED
|
@@ -15,8 +15,13 @@
|
|
|
15
15
|
- **图片分割**:支持网格等分(自定义行/列数)或自定义分割线(像素/百分比),自动生成分割后的图片文件。
|
|
16
16
|
- **图片主色识别**:提取图片主色调(Hex/RGB/HSL/HSV),默认复制 Hex 到剪贴板,支持保存详细信息到文件。
|
|
17
17
|
- **颜色吸取**:从图片中吸取单像素颜色或区域平均颜色,支持 px/% 坐标输入,结果显示颜色条并自动复制 Hex/Hex8。
|
|
18
|
-
-
|
|
18
|
+
- **屏幕取色**:直接在屏幕上将鼠标移动到目标位置按 **空格键** 即可取色。
|
|
19
|
+
> **注意事项**:
|
|
20
|
+
> 1. 使用前请确保命令行窗口处于 **激活状态** (Focus)。
|
|
21
|
+
> 2. 由于涉及跨进程通信,按下空格后可能存在轻微延时,请耐心等待结果。
|
|
22
|
+
> 3. 取色模式下会显示全屏十字辅助线,按 **回车键** 退出模式。
|
|
19
23
|
- **占位图生成**:快速生成指定尺寸、颜色、文字的占位图片 (Placeholder Image)。
|
|
24
|
+
- **全屏十字辅助线**:显示跟随鼠标的全屏红色十字线,用于屏幕对齐和定位。
|
|
20
25
|
- **Mock 数据生成**:
|
|
21
26
|
- 支持生成:英文段落 (Lorem Ipsum)、中文字符、中国居民身份证号、电子邮箱、URL、订单号、手机号、座机号。
|
|
22
27
|
- 支持批量生成。
|
|
@@ -29,6 +34,7 @@
|
|
|
29
34
|
- **Unicode 编解码**:文本与 Unicode 转义序列 (\uXXXX) 互转。
|
|
30
35
|
- **UUID**:生成 UUID v4。
|
|
31
36
|
- **中文转拼音**:将汉字转换为不带声调的拼音。
|
|
37
|
+
- **进制转换**:支持二进制、八进制、十进制、十六进制之间的互相转换。
|
|
32
38
|
- **颜色转换**:Hex <-> RGB 互转,并在结果中显示颜色条预览(支持透明度棋盘背景),自动复制 Hex。
|
|
33
39
|
- **颜色预览**:输入颜色并在终端显示颜色条,便于快速视觉确认,同时自动复制 Hex 到剪贴板。
|
|
34
40
|
- **变量格式转换**:支持 CamelCase, PascalCase, SnakeCase, KebabCase, ConstantCase 互转。
|
|
@@ -297,6 +303,12 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
|
|
|
297
303
|
- **Format Conversion**: Convert between PNG, JPG, WebP, ICO, with adjustable compression quality. For ICO, you can specify sizes (comma-separated); leave empty to generate `256` size by default. Output filenames include timestamps to avoid overwriting.
|
|
298
304
|
- **Image ↔ Base64**: Convert images to Base64 strings and vice versa.
|
|
299
305
|
- **Image Dominant Color**: Extract dominant color (Hex/RGB/HSL/HSV), copy Hex to clipboard by default, or save details to file.
|
|
306
|
+
- **Image Color Picker**: Pick color from image (single pixel or average), supports px/% coordinates, shows color bar and auto-copies Hex/Hex8.
|
|
307
|
+
- **Screen Color Picker**: Pick color directly from screen by moving mouse and pressing **Space**.
|
|
308
|
+
> **Note**:
|
|
309
|
+
> 1. Ensure the terminal window is **Focused** before use.
|
|
310
|
+
> 2. There might be a slight delay after pressing Space due to system calls.
|
|
311
|
+
> 3. A full-screen crosshair is shown in picking mode; press **Enter** to exit.
|
|
300
312
|
- **Placeholder Image**: Quickly generate placeholder images with custom size, color, and text.
|
|
301
313
|
- **Mock Data**:
|
|
302
314
|
- Generate: Lorem Ipsum, Chinese characters, ID cards, Emails, URLs, Order IDs, Phone numbers.
|
package/README_EN.md
CHANGED
|
@@ -16,6 +16,7 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
|
|
|
16
16
|
- **Placeholder Image**: Quickly generate placeholder images with custom size, color, and text.
|
|
17
17
|
- **Color Picker**: Pick a single pixel color or area average from an image; supports px/% coordinates; shows preview bar and auto-copies Hex/Hex8.
|
|
18
18
|
- **Screen Picker**: Pick color directly from the screen at the mouse position; move the cursor and press Enter to sample; supports alpha preview.
|
|
19
|
+
- **Screen Crosshair**: Display a full-screen red crosshair following the mouse for alignment.
|
|
19
20
|
- **Mock Data**:
|
|
20
21
|
- Generate: Lorem Ipsum, Chinese characters, ID cards, Emails, URLs, Order IDs, Phone numbers.
|
|
21
22
|
- Supports batch generation.
|
|
@@ -28,6 +29,7 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
|
|
|
28
29
|
- **Unicode Encode/Decode**: Text <-> Unicode escape sequences (\uXXXX).
|
|
29
30
|
- **UUID**: Generate UUID v4.
|
|
30
31
|
- **Pinyin**: Convert Chinese characters to Pinyin (without tone).
|
|
32
|
+
- **Base Converter**: Convert between Binary, Octal, Decimal, and Hexadecimal.
|
|
31
33
|
- **Color Converter**: Hex <-> RGB, and shows a color bar preview in results (with checkerboard alpha simulation); Hex auto-copied.
|
|
32
34
|
- **Color Preview**: Enter a color and display a color bar in terminal for quick visual confirmation; Hex is auto-copied to clipboard.
|
|
33
35
|
- **Variable Format**: CamelCase, PascalCase, SnakeCase, KebabCase, ConstantCase.
|
package/package.json
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
import { copy } from '../utils/clipboard.js';
|
|
3
|
+
import { selectFromMenu } from '../utils/menu.js';
|
|
4
|
+
import i18next from '../i18n.js';
|
|
5
|
+
|
|
6
|
+
function cleanInput(input, base) {
|
|
7
|
+
input = input.trim();
|
|
8
|
+
if (base === 16 && (input.startsWith('0x') || input.startsWith('0X'))) {
|
|
9
|
+
return input.slice(2);
|
|
10
|
+
}
|
|
11
|
+
if (base === 2 && (input.startsWith('0b') || input.startsWith('0B'))) {
|
|
12
|
+
return input.slice(2);
|
|
13
|
+
}
|
|
14
|
+
if (base === 8 && (input.startsWith('0o') || input.startsWith('0O'))) {
|
|
15
|
+
return input.slice(2);
|
|
16
|
+
}
|
|
17
|
+
return input;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isValid(input, base) {
|
|
21
|
+
const regexMap = {
|
|
22
|
+
10: /^-?\d+$/,
|
|
23
|
+
16: /^-?[0-9a-fA-F]+$/,
|
|
24
|
+
2: /^-?[01]+$/,
|
|
25
|
+
8: /^-?[0-7]+$/
|
|
26
|
+
};
|
|
27
|
+
return regexMap[base] ? regexMap[base].test(input) : false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function baseConvertHandler() {
|
|
31
|
+
const { rawInput } = await inquirer.prompt([
|
|
32
|
+
{
|
|
33
|
+
type: 'input',
|
|
34
|
+
name: 'rawInput',
|
|
35
|
+
message: i18next.t('baseConvert.inputPrompt'),
|
|
36
|
+
validate: (input) => input.trim().length > 0 || i18next.t('baseConvert.invalidInput')
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const inputBase = await selectFromMenu(i18next.t('baseConvert.selectBase'), [
|
|
41
|
+
{ name: i18next.t('baseConvert.auto'), value: 'auto' },
|
|
42
|
+
{ name: 'Decimal (10)', value: 10 },
|
|
43
|
+
{ name: 'Hexadecimal (16)', value: 16 },
|
|
44
|
+
{ name: 'Binary (2)', value: 2 },
|
|
45
|
+
{ name: 'Octal (8)', value: 8 }
|
|
46
|
+
], true, i18next.t('common.back'));
|
|
47
|
+
|
|
48
|
+
if (inputBase === '__BACK__') {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let decimalValue;
|
|
53
|
+
let base = inputBase;
|
|
54
|
+
let inputToParse = rawInput.trim();
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
if (inputBase === 'auto') {
|
|
58
|
+
if (inputToParse.startsWith('0x') || inputToParse.startsWith('0X')) {
|
|
59
|
+
base = 16;
|
|
60
|
+
inputToParse = inputToParse.slice(2);
|
|
61
|
+
} else if (inputToParse.startsWith('0b') || inputToParse.startsWith('0B')) {
|
|
62
|
+
base = 2;
|
|
63
|
+
inputToParse = inputToParse.slice(2);
|
|
64
|
+
} else if (inputToParse.startsWith('0o') || inputToParse.startsWith('0O')) {
|
|
65
|
+
base = 8;
|
|
66
|
+
inputToParse = inputToParse.slice(2);
|
|
67
|
+
} else {
|
|
68
|
+
base = 10;
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
inputToParse = cleanInput(inputToParse, base);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!isValid(inputToParse, base)) {
|
|
75
|
+
console.error(`\n${i18next.t('baseConvert.error')} (Base: ${base})`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
decimalValue = parseInt(inputToParse, base);
|
|
80
|
+
|
|
81
|
+
if (isNaN(decimalValue)) {
|
|
82
|
+
throw new Error('Invalid number');
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.error(`\n${i18next.t('baseConvert.error')}`);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const results = [];
|
|
90
|
+
results.push(`Decimal (10): ${decimalValue.toString(10)}`);
|
|
91
|
+
results.push(`Hexadecimal (16): 0x${decimalValue.toString(16).toUpperCase()}`);
|
|
92
|
+
results.push(`Binary (2): 0b${decimalValue.toString(2)}`);
|
|
93
|
+
results.push(`Octal (8): 0o${decimalValue.toString(8)}`);
|
|
94
|
+
|
|
95
|
+
console.log(`\n=== ${i18next.t('baseConvert.result')} ===`);
|
|
96
|
+
results.forEach(res => console.log(res));
|
|
97
|
+
console.log('==========================\n');
|
|
98
|
+
|
|
99
|
+
const copyChoice = await selectFromMenu(i18next.t('baseConvert.copyPrompt'), [
|
|
100
|
+
{ name: 'Decimal', value: decimalValue.toString(10) },
|
|
101
|
+
{ name: 'Hexadecimal', value: decimalValue.toString(16).toUpperCase() },
|
|
102
|
+
{ name: 'Binary', value: decimalValue.toString(2) },
|
|
103
|
+
{ name: 'Octal', value: decimalValue.toString(8) }
|
|
104
|
+
], true, i18next.t('common.back'));
|
|
105
|
+
|
|
106
|
+
if (copyChoice === '__BACK__') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await copy(copyChoice);
|
|
111
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import i18next from '../i18n.js';
|
|
3
|
+
|
|
4
|
+
export async function crosshairHandler() {
|
|
5
|
+
if (process.platform !== 'win32') {
|
|
6
|
+
console.log(i18next.t('crosshair.notSupported'));
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
console.log(i18next.t('crosshair.startPrompt'));
|
|
11
|
+
|
|
12
|
+
const overlayScript = `
|
|
13
|
+
Add-Type -AssemblyName System.Windows.Forms; Add-Type -AssemblyName System.Drawing;
|
|
14
|
+
Add-Type -TypeDefinition @'
|
|
15
|
+
using System;
|
|
16
|
+
using System.Drawing;
|
|
17
|
+
using System.Windows.Forms;
|
|
18
|
+
using System.Runtime.InteropServices;
|
|
19
|
+
public class OverlayForm : Form {
|
|
20
|
+
const int WS_EX_TRANSPARENT=0x20;
|
|
21
|
+
const int WS_EX_LAYERED=0x80000;
|
|
22
|
+
const int GWL_EXSTYLE=-20;
|
|
23
|
+
[DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
|
24
|
+
[DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
|
|
25
|
+
Timer t;
|
|
26
|
+
public OverlayForm(){
|
|
27
|
+
this.FormBorderStyle=FormBorderStyle.None;
|
|
28
|
+
this.TopMost=true;
|
|
29
|
+
this.ShowInTaskbar=false;
|
|
30
|
+
this.WindowState=FormWindowState.Maximized;
|
|
31
|
+
this.BackColor=Color.Fuchsia;
|
|
32
|
+
this.TransparencyKey=this.BackColor;
|
|
33
|
+
this.DoubleBuffered=true;
|
|
34
|
+
this.Cursor = Cursors.Default;
|
|
35
|
+
}
|
|
36
|
+
protected override void OnShown(EventArgs e){
|
|
37
|
+
base.OnShown(e);
|
|
38
|
+
int ex=GetWindowLong(this.Handle,GWL_EXSTYLE);
|
|
39
|
+
SetWindowLong(this.Handle,GWL_EXSTYLE,ex|WS_EX_LAYERED|WS_EX_TRANSPARENT);
|
|
40
|
+
t=new Timer();
|
|
41
|
+
t.Interval=16;
|
|
42
|
+
t.Tick+=(s,ev)=>{ this.Invalidate(); };
|
|
43
|
+
t.Start();
|
|
44
|
+
}
|
|
45
|
+
protected override void OnPaint(PaintEventArgs e){
|
|
46
|
+
var p=Cursor.Position;
|
|
47
|
+
var g=e.Graphics;
|
|
48
|
+
using(var pen=new Pen(Color.Red,1)){
|
|
49
|
+
g.DrawLine(pen,0,p.Y,this.Width,p.Y);
|
|
50
|
+
g.DrawLine(pen,p.X,0,p.X,this.Height);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
public static class Entry {
|
|
55
|
+
public static void Main(){ Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new OverlayForm()); }
|
|
56
|
+
}
|
|
57
|
+
'@ -ReferencedAssemblies System.Windows.Forms,System.Drawing;
|
|
58
|
+
[Entry]::Main()
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
const overlay = spawn('powershell', ['-NoProfile', '-Command', overlayScript], { windowsHide: true });
|
|
62
|
+
|
|
63
|
+
// Handle exit
|
|
64
|
+
const cleanup = () => {
|
|
65
|
+
if (overlay && !overlay.killed) {
|
|
66
|
+
try {
|
|
67
|
+
overlay.kill();
|
|
68
|
+
} catch (e) {
|
|
69
|
+
// ignore
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Ensure cleanup on process exit
|
|
75
|
+
const exitHandler = () => cleanup();
|
|
76
|
+
process.once('exit', exitHandler);
|
|
77
|
+
process.once('SIGINT', exitHandler);
|
|
78
|
+
|
|
79
|
+
await new Promise((resolve) => {
|
|
80
|
+
const stdin = process.stdin;
|
|
81
|
+
try { stdin.setRawMode(true); } catch {}
|
|
82
|
+
stdin.resume();
|
|
83
|
+
const onData = (data) => {
|
|
84
|
+
stdin.removeListener('data', onData);
|
|
85
|
+
try { stdin.setRawMode(false); } catch {}
|
|
86
|
+
stdin.pause();
|
|
87
|
+
process.removeListener('exit', exitHandler);
|
|
88
|
+
process.removeListener('SIGINT', exitHandler);
|
|
89
|
+
cleanup();
|
|
90
|
+
resolve();
|
|
91
|
+
};
|
|
92
|
+
stdin.once('data', onData);
|
|
93
|
+
});
|
|
94
|
+
}
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import i18next from './i18n.js';
|
|
|
4
4
|
import { saveConfig } from './utils/config.js';
|
|
5
5
|
|
|
6
6
|
import { urlHandler } from './commands/url.js';
|
|
7
|
+
import { baseConvertHandler } from './commands/baseConvert.js';
|
|
7
8
|
import { base64Handler } from './commands/base64.js';
|
|
8
9
|
import { unicodeHandler } from './commands/unicode.js';
|
|
9
10
|
import { imgBase64Handler } from './commands/imgBase64.js';
|
|
@@ -28,6 +29,7 @@ import { markdownHandler } from './commands/markdown.js';
|
|
|
28
29
|
import { vscodeSnippetHandler } from './commands/vscodeSnippet.js';
|
|
29
30
|
import { dominantColorHandler } from './commands/dominantColor.js';
|
|
30
31
|
import { colorPickHandler } from './commands/colorPick.js';
|
|
32
|
+
import { crosshairHandler } from './commands/crosshair.js';
|
|
31
33
|
|
|
32
34
|
process.on('SIGINT', () => {
|
|
33
35
|
console.log(`\n${i18next.t('menu.bye')}`);
|
|
@@ -52,11 +54,13 @@ function getFeatures() {
|
|
|
52
54
|
{ name: i18next.t('menu.features.imgSplit'), value: 'imgSplit' },
|
|
53
55
|
{ name: i18next.t('menu.features.dominantColor'), value: 'dominantColor' },
|
|
54
56
|
{ name: i18next.t('menu.features.colorPick'), value: 'colorPick' },
|
|
57
|
+
{ name: i18next.t('menu.features.crosshair'), value: 'crosshair' },
|
|
55
58
|
{ name: i18next.t('menu.features.placeholderImg'), value: 'placeholderImg' },
|
|
56
59
|
{ name: i18next.t('menu.features.qrcode'), value: 'qrcode' },
|
|
57
60
|
|
|
58
61
|
// Encode/Decode & Formatting
|
|
59
62
|
{ name: i18next.t('menu.features.url'), value: 'url' },
|
|
63
|
+
{ name: i18next.t('menu.features.baseConvert'), value: 'baseConvert' },
|
|
60
64
|
{ name: i18next.t('menu.features.base64'), value: 'base64' },
|
|
61
65
|
{ name: i18next.t('menu.features.unicode'), value: 'unicode' },
|
|
62
66
|
{ name: i18next.t('menu.features.htmlEntities'), value: 'htmlEntities' },
|
|
@@ -168,6 +172,9 @@ async function handleAction(action) {
|
|
|
168
172
|
case 'url':
|
|
169
173
|
await urlHandler();
|
|
170
174
|
break;
|
|
175
|
+
case 'baseConvert':
|
|
176
|
+
await baseConvertHandler();
|
|
177
|
+
break;
|
|
171
178
|
case 'base64':
|
|
172
179
|
await base64Handler();
|
|
173
180
|
break;
|
|
@@ -189,6 +196,9 @@ async function handleAction(action) {
|
|
|
189
196
|
case 'colorPick':
|
|
190
197
|
await colorPickHandler();
|
|
191
198
|
break;
|
|
199
|
+
case 'crosshair':
|
|
200
|
+
await crosshairHandler();
|
|
201
|
+
break;
|
|
192
202
|
case 'timeFormat':
|
|
193
203
|
await timeFormatHandler();
|
|
194
204
|
break;
|
package/src/locales/en.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
common: {
|
|
3
|
+
back: 'Back to previous step'
|
|
4
|
+
},
|
|
2
5
|
menu: {
|
|
3
6
|
title: 'xw-devtool-cli Menu',
|
|
4
7
|
exit: 'Exit',
|
|
5
|
-
prompt: 'Please enter
|
|
8
|
+
prompt: 'Please enter feature key',
|
|
6
9
|
invalid: 'Invalid selection. Please enter a valid menu key.',
|
|
7
10
|
bye: 'Bye!',
|
|
8
11
|
features: {
|
|
@@ -11,9 +14,11 @@ export default {
|
|
|
11
14
|
imgSplit: 'Image Splitter',
|
|
12
15
|
dominantColor: 'Image Dominant Color',
|
|
13
16
|
colorPick: 'Color Picker',
|
|
17
|
+
crosshair: 'Screen Crosshair',
|
|
14
18
|
placeholderImg: 'Placeholder Image Generator',
|
|
15
19
|
qrcode: 'QR Code Generator',
|
|
16
20
|
url: 'URL Encode/Decode',
|
|
21
|
+
baseConvert: 'Number Base Converter',
|
|
17
22
|
base64: 'String Encode/Decode (Base64)',
|
|
18
23
|
unicode: 'Unicode Encode/Decode',
|
|
19
24
|
htmlEntities: 'HTML Entity Encode/Decode',
|
|
@@ -78,6 +83,15 @@ export default {
|
|
|
78
83
|
result: 'Result:',
|
|
79
84
|
error: 'Error processing URL:'
|
|
80
85
|
},
|
|
86
|
+
baseConvert: {
|
|
87
|
+
inputPrompt: 'Enter number:',
|
|
88
|
+
invalidInput: 'Please enter a valid number',
|
|
89
|
+
selectBase: 'Select input base:',
|
|
90
|
+
auto: 'Auto-detect',
|
|
91
|
+
result: 'Conversion Results',
|
|
92
|
+
error: 'Invalid number for the selected base.',
|
|
93
|
+
copyPrompt: 'Select format to copy'
|
|
94
|
+
},
|
|
81
95
|
imgSplit: {
|
|
82
96
|
mode: 'Select split mode',
|
|
83
97
|
modeGrid: 'Grid Split (Equal parts)',
|
package/src/locales/zh.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
common: {
|
|
3
|
+
back: '返回上一步'
|
|
4
|
+
},
|
|
5
|
+
crosshair: {
|
|
6
|
+
notSupported: '当前系统不支持屏幕辅助线。',
|
|
7
|
+
startPrompt: '屏幕十字辅助线已启动。按任意键退出...'
|
|
8
|
+
},
|
|
2
9
|
menu: {
|
|
3
10
|
title: 'xw-devtool-cli 菜单',
|
|
4
11
|
exit: '退出',
|
|
5
|
-
prompt: '请输入功能键
|
|
12
|
+
prompt: '请输入功能键',
|
|
6
13
|
invalid: '无效选择,请输入有效的菜单键。',
|
|
7
14
|
bye: '再见!',
|
|
8
15
|
features: {
|
|
@@ -11,9 +18,11 @@ export default {
|
|
|
11
18
|
imgSplit: '图片分割工具',
|
|
12
19
|
dominantColor: '图片主色识别',
|
|
13
20
|
colorPick: '颜色吸取',
|
|
21
|
+
crosshair: '全屏十字辅助线',
|
|
14
22
|
placeholderImg: '占位图生成器',
|
|
15
23
|
qrcode: '二维码生成器',
|
|
16
24
|
url: 'URL 编码/解码',
|
|
25
|
+
baseConvert: '进制转换工具',
|
|
17
26
|
base64: '字符串 编码/解码 (Base64)',
|
|
18
27
|
unicode: 'Unicode 编码/解码',
|
|
19
28
|
htmlEntities: 'HTML 实体 编码/解码',
|
|
@@ -78,6 +87,15 @@ export default {
|
|
|
78
87
|
result: '结果:',
|
|
79
88
|
error: '处理 URL 时出错:'
|
|
80
89
|
},
|
|
90
|
+
baseConvert: {
|
|
91
|
+
inputPrompt: '请输入数字:',
|
|
92
|
+
invalidInput: '请输入有效的数字',
|
|
93
|
+
selectBase: '选择输入进制:',
|
|
94
|
+
auto: '自动检测',
|
|
95
|
+
result: '转换结果',
|
|
96
|
+
error: '输入的数字对于所选进制无效。',
|
|
97
|
+
copyPrompt: '选择要复制的格式'
|
|
98
|
+
},
|
|
81
99
|
imgSplit: {
|
|
82
100
|
mode: '选择分割模式',
|
|
83
101
|
modeGrid: '网格分割 (等分)',
|