提交 dcdbf7ff 编写于 作者: B baiy 提交者: ninecents

ip网络计算器

上级 70bf953d
......@@ -40,35 +40,36 @@ npm run build -adapter=[chrome|edge|utools|firefox|web]
## 功能列表
|功能|说明|离线使用|
|---|---|---|
|哈希|`md5`, `sha1`, `sha256`, `sha512`,`sm3`|√|
|加密/解密|`AES`,`DES`,`RC4`,`Rabbit`,`TripleDes`,`sm2`|√|
|BASE64编码|`加密`,`解密`,`支持文件`|√|
|URL编码|`编码`,`解码`|√|
|时间戳|`双向转换`,`毫秒`|√|
|二维码|`生成`,`解析`|√|
|条形码|`生成`|√|
|汉字转拼音|`声调`,`首字母`,`分隔符`|√|
|IP地址查询|`运营商`,`城市`|×|
|代码格式化|`js`, `ts`, `html`, `css`, `less`, `scss`, `graphql`, `vue`, `angular`, `markdown`, `json5`, `xml`, `yaml`, `sql`, `压缩`|√|
|Unicode|`双向转换`,`emoji`,`html 实体`,`css 实体`|√|
|进制转换|`2-64进制`|√|
|正则表达式|`匹配`,`查找`,`替换`|√|
|随机字符生成器|`批量`,`特殊字符`|√|
|序列化转换|`json`, `xml`, `yaml`, `phpArray`, `phpSerialize`, `properties`|√|
|文本差异化对比|`行`,`单词`,`css`|√|
|crontab校验|`Crontab`,`规则`,`校验`,`例子`|√|
|websocket调试|`websocket`,`在线调试`|×|
|单位换算|`长度`,`面积`,`体积`,`质量`,`温度`,`压力`,`功率`,`功`,`密度`,`力`,`时间`,`速度`,`数据存储`,`角度`|√|
|时间计算器| - |√|
|JSON工具|`格式化`,`校验`,`压缩`,`转义`,`去除转义`,`Unicode转中文`,`中文转Unicode`,`转GET参数`,`Java`, `C#`, `Go`, `Dart`,`csv`,`table`,`Protobuf`|√|
|UUID|`在线生成uuid`|√|
|ascii编码转换|`十进制`, `十六进制`, `八进制`, `二进制`, `字符串`|√|
|变量名格式转换|`Var Name`, `var-name`, `VAR_NAME`, `VarName`, `varName`, `var_name`, `var name`|√|
|jwt解码|`header`, `payload`|√|
|Hex/String转换|`hex to string`, `string to hex`, `十六进制转字符串`, `字符串转十六进制`|√|
|文本处理|`大小写转换`, `中英文标点转换`, `简繁转换`, `替换`, `字符统计`, `行去重`, `添加行号`, `行排序`, `过滤行首尾不可见字符`,`过滤空行`|√|
|html编码|-|√|
|原码/反码/补码|`生成`|√|
|ARM/HEX|`互转`|×|
| 功能 |说明|离线使用|
|--------------|---|---|
| 哈希 |`md5`, `sha1`, `sha256`, `sha512`,`sm3`|√|
| 加密/解密 |`AES`,`DES`,`RC4`,`Rabbit`,`TripleDes`,`sm2`|√|
| BASE64编码 |`加密`,`解密`,`支持文件`|√|
| URL编码 |`编码`,`解码`|√|
| 时间戳 |`双向转换`,`毫秒`|√|
| 二维码 |`生成`,`解析`|√|
| 条形码 |`生成`|√|
| 汉字转拼音 |`声调`,`首字母`,`分隔符`|√|
| IP地址查询 |`运营商`,`城市`|×|
| 代码格式化 |`js`, `ts`, `html`, `css`, `less`, `scss`, `graphql`, `vue`, `angular`, `markdown`, `json5`, `xml`, `yaml`, `sql`, `压缩`|√|
| Unicode |`双向转换`,`emoji`,`html 实体`,`css 实体`|√|
| 进制转换 |`2-64进制`|√|
| 正则表达式 |`匹配`,`查找`,`替换`|√|
| 随机字符生成器 |`批量`,`特殊字符`|√|
| 序列化转换 |`json`, `xml`, `yaml`, `phpArray`, `phpSerialize`, `properties`|√|
| 文本差异化对比 |`行`,`单词`,`css`|√|
| crontab校验 |`Crontab`,`规则`,`校验`,`例子`|√|
| websocket调试 |`websocket`,`在线调试`|×|
| 单位换算 |`长度`,`面积`,`体积`,`质量`,`温度`,`压力`,`功率`,`功`,`密度`,`力`,`时间`,`速度`,`数据存储`,`角度`|√|
| 时间计算器 | - |√|
| JSON工具 |`格式化`,`校验`,`压缩`,`转义`,`去除转义`,`Unicode转中文`,`中文转Unicode`,`转GET参数`,`Java`, `C#`, `Go`, `Dart`,`csv`,`table`,`Protobuf`|√|
| UUID |`在线生成uuid`|√|
| ascii编码转换 |`十进制`, `十六进制`, `八进制`, `二进制`, `字符串`|√|
| 变量名格式转换 |`Var Name`, `var-name`, `VAR_NAME`, `VarName`, `varName`, `var_name`, `var name`|√|
| jwt解码 |`header`, `payload`|√|
| Hex/String转换 |`hex to string`, `string to hex`, `十六进制转字符串`, `字符串转十六进制`|√|
| 文本处理 |`大小写转换`, `中英文标点转换`, `简繁转换`, `替换`, `字符统计`, `行去重`, `添加行号`, `行排序`, `过滤行首尾不可见字符`,`过滤空行`|√|
| html编码 |-|√|
| 原码/反码/补码 |`生成`|√|
| ARM/HEX |`互转`|×|
| IP网络计算器 |`子网掩码各个进制表示换算,IP地址进制表示换算`|√|
......@@ -49,6 +49,7 @@
"lodash": "^4.17.21",
"mime-types": "^2.1.34",
"moment": "^2.29.1",
"netmask": "^2.0.2",
"pascal-case": "^3.1.2",
"php-array-reader": "^1.3.2",
"phparr": "^0.2.0",
......@@ -9474,6 +9475,14 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz",
......@@ -21654,6 +21663,11 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg=="
},
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz",
{
"name": "c-tool",
"version": "1.10.3",
"version": "1.11.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --port 8081",
......@@ -50,6 +50,7 @@
"lodash": "^4.17.21",
"mime-types": "^2.1.34",
"moment": "^2.29.1",
"netmask": "^2.0.2",
"pascal-case": "^3.1.2",
"php-array-reader": "^1.3.2",
"phparr": "^0.2.0",
......
......@@ -62,6 +62,7 @@ const tool = [
{'name': 'binary', 'cat': ['generate']},
{'name': 'armConverter', 'cat': ['conversion']},
{'name': 'bcrypt', 'cat': ['encryption','check']},
{'name': 'ipcalc', 'cat': ['generate']},
]
// 工具类功能配置
......
{
ip: "IP Address",
format: "Input Format",
mask: "Subnet Mask",
ip_info: "IP Detail",
ip_info_long: "Long IP",
ip_info_ip8: "Octal IP",
ip_info_ip10: "Decimal IP",
ip_info_ip16: "Hexadecimal IP",
ip_info_ip2: "Binary IP",
mask_info: "Mask Detail",
mask_info_mask: "Subnet Mask",
mask_info_long: "Long Mask",
mask_info_opposite: "Opposite Mask",
mask_info_mask8: "Octal Mask",
mask_info_mask16: "Hexadecimal Mask",
mask_info_mask2: "Binary Mask",
network_info: "Network Detail",
network_export: "Export Available IP",
network_info_available: "Available IP Size",
network_info_size: "All IP Size",
network_info_base: "Base",
network_info_first: "First IP",
network_info_last: "Last IP",
network_info_broadcast: "Broadcast Address",
mask_set_title: "Calculate mask by number of available IP"
}
......@@ -71,6 +71,7 @@
"tool_binary": "trueForm/inverse/complement",
"tool_armConverter": "ARM/HEX",
"tool_bcrypt": "Bcrypt",
"tool_ipcalc": "Ipcalc",
// other
"css_main_category_item_style": "padding: 0 10px",
"editor_line_wrapping": "Line Wrapping",
......
{
format: "输入格式",
ip: "IP地址",
mask: "掩码",
ip_info: "IP 信息",
ip_info_long: "整型IP",
ip_info_ip8: "点分八进制IP",
ip_info_ip10: "点分十进制IP",
ip_info_ip16: "点分十六进制IP",
ip_info_ip2: "点分二进制IP",
mask_info: "掩码信息",
mask_info_mask: "子网掩码",
mask_info_long: "整型掩码",
mask_info_opposite: "反掩码",
mask_info_mask8: "点分八进制掩码",
mask_info_mask16: "点分十六进制掩码",
mask_info_mask2: "点分二进制掩码",
network_info: "网络信息",
network_export: "导出可用IP",
network_info_available: "可用数量",
network_info_size: "全部数量",
network_info_base: "网络",
network_info_first: "第一个IP",
network_info_last: "最后一个IP",
network_info_broadcast: "广播地址",
mask_set_title: "通过可用IP数量设置掩码"
}
......@@ -71,6 +71,7 @@
"tool_binary": "原码/反码/补码",
"tool_armConverter": "ARM/HEX",
"tool_bcrypt": "Bcrypt",
"tool_ipcalc": "IP网络计算器",
// 其他
"css_main_category_item_style": "padding: 0 20px",
"editor_line_wrapping": "自动换行",
......
......@@ -153,6 +153,10 @@ const routes = [
{
path: '/tool/bcrypt',
component: r => require(['./views/tool/bcrypt.vue'], r)
},
{
path: '/tool/ipcalc',
component: r => require(['./views/tool/ipcalc.vue'], r)
}
]
......
<template>
<div>
<Row :gutter="8" style="margin-bottom: 10px">
<Col span="8" offset="3">
<Input v-model="current.ip">
<span slot="prepend">
{{ $t('ipcalc_ip') }}
</span>
</Input>
</Col>
<Col span="6">
<Input v-model="current.mask">
<span slot="prepend">{{ $t('ipcalc_mask') }}</span>
<Button slot="append" icon="md-settings" @click="maskSet"/>
</Input>
</Col>
<Col span="3">
<Tooltip transfer placement="top" :content="$t('ipcalc_format')" :delay="300">
<Icon type="ios-help-circle-outline" size="22" style="margin-top: 4px;cursor: pointer" @click="show_input_format = true" />
</Tooltip>
</Col>
</Row>
<div v-if="error" style="margin-top: 50px;text-align: center">
<Tag color="error"> {{ error }}</Tag>
</div>
<div class="tool-ipcalc" v-if="ipcalc && !error">
<Card :title="$t('ipcalc_ip_info')">
<span slot="extra">{{ current.ip }}</span>
<CellGroup @on-click="(name)=>$copy(ip[name])">
<Row>
<Col span="7">
<Cell name="ip" :title="ip.ip" :label="$t('ipcalc_ip_info_ip10')"/>
</Col>
<Col span="7">
<Cell name="long" :title="ip.long" :label="$t('ipcalc_ip_info_long')"/>
</Col>
<Col span="10">
<Cell name="ip8" :title="ip.ip8" :label="$t('ipcalc_ip_info_ip8')"/>
</Col>
</Row>
<Row>
<Col span="7">
<Cell name="ip16" :title="ip.ip16" :label="$t('ipcalc_ip_info_ip16')"/>
</Col>
<Col span="10">
<Cell name="ip2" :title="ip.ip2" :label="$t('ipcalc_ip_info_ip2')"/>
</Col>
</Row>
</CellGroup>
</Card>
<Card :title="$t('ipcalc_mask_info')" style="margin: 5px 0">
<span slot="extra">{{ current.mask }}</span>
<CellGroup @on-click="(name)=>$copy(mask[name])">
<Row>
<Col span="6">
<Cell name="bit" :title="mask.bit" :label="$t('ipcalc_mask')"/>
</Col>
<Col span="6">
<Cell name="mask" :title="mask.mask" :label="$t('ipcalc_mask_info_mask')"/>
</Col>
<Col span="6">
<Cell name="long" :title="mask.long" :label="$t('ipcalc_mask_info_long')"/>
</Col>
<Col span="6">
<Cell name="opposite" :title="mask.opposite" :label="$t('ipcalc_mask_info_opposite')"/>
</Col>
</Row>
<Row>
<Col span="6">
<Cell name="mask8" :title="mask.mask8" :label="$t('ipcalc_mask_info_mask8')"/>
</Col>
<Col span="6">
<Cell name="mask16" :title="mask.mask16" :label="$t('ipcalc_mask_info_mask16')"/>
</Col>
<Col span="12">
<Cell name="mask2" :title="mask.mask2" :label="$t('ipcalc_mask_info_mask2')"/>
</Col>
</Row>
</CellGroup>
</Card>
<Card :title="$t('ipcalc_network_info')">
<a href="#" slot="extra" @click.prevent="networkExport">{{ $t("ipcalc_network_export") }}</a>
<CellGroup @on-click="(name)=>$copy(network[name])">
<Row>
<Col span="7">
<Cell name="available" :title="`${network.available}`"
:label="$t('ipcalc_network_info_available')"/>
</Col>
<Col span="7">
<Cell name="size" :title="`${network.size}`" :label="$t('ipcalc_network_info_size')"/>
</Col>
<Col span="10">
<Cell name="base" :title="`${network.base}`" :label="$t('ipcalc_network_info_base')"/>
</Col>
</Row>
<Row>
<Col span="7">
<Cell name="first" :title="`${network.first}`" :label="$t('ipcalc_network_info_first')"/>
</Col>
<Col span="7">
<Cell name="last" :title="`${network.last}`" :label="$t('ipcalc_network_info_last')"/>
</Col>
<Col span="10">
<Cell name="broadcast" :title="`${network.broadcast}`"
:label="$t('ipcalc_network_info_broadcast')"/>
</Col>
</Row>
</CellGroup>
</Card>
</div>
<Modal
v-model="show_input_format"
:title="`${$t('ipcalc_format')}`"
:width="780"
footer-hide
>
<div class="tool-ipcalc">
<Card :title="$t('ipcalc_ip')" style="margin-bottom: 10px">
<CellGroup>
<Row>
<Col span="6">
<Cell title="192.168.0.1" :label="$t('ipcalc_ip_info_ip10')"/>
</Col>
<Col span="6">
<Cell title="3232235521" :label="$t('ipcalc_ip_info_long')"/>
</Col>
<Col span="6">
<Cell title="0300.0250.0000.0001" :label="$t('ipcalc_ip_info_ip8')"/>
</Col>
<Col span="6">
<Cell title="0xC0.0xA8.0x00.0x01" :label="$t('ipcalc_ip_info_ip16')"/>
</Col>
</Row>
<Row>
<Col span="15">
<Cell title="0b11000000.0b10101000.0b00000000.0b00000001" :label="$t('ipcalc_ip_info_ip2')"/>
</Col>
</Row>
</CellGroup>
</Card>
<Card :title="$t('ipcalc_mask')">
<CellGroup>
<Row>
<Col span="6">
<Cell title="24" :label="$t('ipcalc_mask')"/>
</Col>
<Col span="6">
<Cell title="255.255.255.0" :label="$t('ipcalc_mask_info_mask')"/>
</Col>
<Col span="6">
<Cell title="4294967040" :label="$t('ipcalc_mask_info_long')"/>
</Col>
<Col span="6">
<Cell title="0377.0377.0377.0000" :label="$t('ipcalc_mask_info_mask8')"/>
</Col>
</Row>
<Row>
<Col span="6">
<Cell title="0xFF.0xFF.0xFF.0x00" :label="$t('ipcalc_mask_info_mask16')"/>
</Col>
<Col span="15">
<Cell title="0b11111111.0b11111111.0b11111111.0b00000000"
:label="$t('ipcalc_mask_info_mask2')"/>
</Col>
</Row>
</CellGroup>
</Card>
</div>
</Modal>
<Modal
v-model="export_show"
:title="$t('ipcalc_network_export')"
:width="260"
footer-hide
>
<Input :rows="15" :value="export_data" type="textarea"></Input>
</Modal>
</div>
</template>
<script>
import ipcalc, {getMaskBitByAvailable} from "./library/ipcalc"
import heightResize from "./components/heightResize";
import autoHeightTextarea from "./components/autoHeightTextarea";
export default {
components: {
heightResize,
autoHeightTextarea
},
created() {
this.$initToolData()
},
computed: {
ip() {
const ipInfo = this.ipcalc.ipInfo()
return {
ip: ipInfo.ip,
long: ipInfo.long,
ip2: ipInfo.ip2,
ip8: ipInfo.ip8,
ip16: ipInfo.ip16,
}
},
mask() {
const maskInfo = this.ipcalc.maskInfo()
return {
bit: maskInfo.bit,
long: maskInfo.long,
mask: maskInfo.mask,
mask2: maskInfo.mask2,
mask8: maskInfo.mask8,
mask16: maskInfo.mask16,
opposite: maskInfo.opposite,
}
},
network() {
return {
available: this.ipcalc.available(),
size: this.ipcalc.size(),
base: this.ipcalc.base(),
first: this.ipcalc.first(),
last: this.ipcalc.last(),
broadcast: this.ipcalc.broadcast(),
}
}
},
watch: {
current: {
handler() {
this.init()
},
deep: true
}
},
methods: {
init() {
this.error = "";
try {
this.ipcalc = new ipcalc(this.current.ip, this.current.mask)
this.$saveToolData(this.current)
} catch (e) {
this.error = e.message
}
},
networkExport() {
this.export_data = ""
this.ipcalc.netmask.forEach((ip, long, index) => {
this.export_data = `${this.export_data ? this.export_data+"\n" : ""}${index+1}: ${ip}`
})
this.export_show = true
},
maskSet() {
let input = 254
this.$Modal.confirm({
title: this.$t('ipcalc_mask_set_title'),
onOk: () => {
try {
this.current.mask = getMaskBitByAvailable(input)
} catch (e) {
this.$Message.error(e.message)
}
},
render: (h) => {
return h('Input', {
props: {
value: input,
autofocus: true,
},
on: {
input: (val) => {
input = val
}
}
})
}
})
}
},
data() {
return {
current: {
ip: "192.168.0.1",
mask: "24",
},
ipcalc: new ipcalc(),
error: "",
show_input_format: false,
export_show:false,
export_data:""
}
}
}
</script>
<style>
.tool-ipcalc .ivu-card-head {
padding: 5px 10px;
}
.tool-ipcalc .ivu-card-body {
padding: 0 0;
}
.tool-ipcalc .ivu-card-extra {
top: 4px;
}
.tool-ipcalc .ivu-cell {
padding: 7px 16px;
}
.tool-ipcalc .ivu-cell-title {
line-height: 18px;
font-size: 16px;
}
</style>
import {ip2long, long2ip, Netmask} from "netmask"
import Radix from "./radix"
const radix = new Radix()
const tryBinaryToDecimal = (ip) => {
if (ip.includes('.') && ip.substr(0, 2).toUpperCase() === "0B") {
return ipConvert(ip, 10, 2, '0b')
}
return ip
}
export const ipConvert = (ip, toRadix = 10, fromRadix = 10, filterPrefix = "") => {
toRadix = parseInt(toRadix, 10);
fromRadix = parseInt(fromRadix, 10);
return ip.split('.').map((item) => {
// 移除前缀
if (
filterPrefix
&& item.length > filterPrefix.length
&& item.substr(0, filterPrefix.length).toUpperCase() === filterPrefix.toUpperCase()
) {
item = item.substr(filterPrefix.length)
}
// 移除补零
item = item.replace(/\b(0+)/gi, "") || "0"
if (toRadix === fromRadix) {
return `${item}`;
}
return `${radix.convent(item, fromRadix, toRadix).padStart(toRadix === 2 ? 8 : (toRadix === 8 ? 4 : 2), '0').toUpperCase()}`
}).join('.')
}
export const getMaskBitByAvailable = (available) => {
available = parseInt(`${available}`, 10);
if (isNaN(available) || available > 0xfffffffe || available < 1) {
throw new Error(`Available Size Invalid`)
}
let bitSize = parseInt(`${Math.log(available) / Math.log(2)}`) + 1;
if ((Math.pow(2, bitSize) - available) < 2) {
bitSize += 1;
}
return 32 - bitSize
}
export default class {
netmask = null
ip = ""
constructor(
ipAddr = "192.168.0.1" // lang/点分[10/8/16]进制
, maskAddr = "24" // 位数/lang/点分[10/8/16]进制
) {
// mask long
if (!`${maskAddr}`.includes('.') && parseInt(`${maskAddr}`, 10) > 32) {
maskAddr = long2ip(maskAddr)
}
// ip/mask 支持二进制
ipAddr = tryBinaryToDecimal(ipAddr)
maskAddr = tryBinaryToDecimal(maskAddr)
this.netmask = new Netmask(`${ipAddr}/${maskAddr}`)
this.ip = `${long2ip(ip2long(ipAddr))}`
}
// 可用地址
available() {
return Math.max(this.netmask.size - 2, 0)
}
// 地址总数
size() {
return this.netmask.size
}
// 网络
base() {
return this.netmask.base
}
first() {
return this.netmask.first
}
last() {
return this.netmask.last
}
broadcast() {
return this.netmask.broadcast || "-"
}
// 当前ip
ipInfo() {
return {
ip: this.ip,
long: `${ip2long(this.ip)}`,
ip2: ipConvert(this.ip, 2),
ip8: ipConvert(this.ip, 8),
ip16: ipConvert(this.ip, 16),
}
}
// 当前掩码
maskInfo() {
const mask = `${long2ip(this.netmask.maskLong)}`;
return {
bit: `${this.netmask.bitmask}`,
long: `${this.netmask.maskLong}`,
mask,
mask2: ipConvert(mask, 2),
mask8: ipConvert(mask, 8),
mask16: ipConvert(mask, 16),
opposite: `${this.netmask.hostmask}`,
}
}
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册