diff --git a/web/public/js/components/common/combo-box.js b/web/public/js/components/common/combo-box.js index e5fb65be..82965f7b 100644 --- a/web/public/js/components/common/combo-box.js +++ b/web/public/js/components/common/combo-box.js @@ -200,7 +200,7 @@ Vue.component("combo-box", {
diff --git a/web/public/js/components/ns/ns-route-ranges-box.js b/web/public/js/components/ns/ns-route-ranges-box.js index f5fdd64c..93809415 100644 --- a/web/public/js/components/ns/ns-route-ranges-box.js +++ b/web/public/js/components/ns/ns-route-ranges-box.js @@ -10,21 +10,46 @@ Vue.component("ns-route-ranges-box", { isAdding: false, isAddingBatch: false, + // 类型 + rangeType: "ipRange", + isReverse: false, + // IP范围 ipRangeFrom: "", ipRangeTo: "", - batchIPRange: "" + batchIPRange: "", + + // CIDR + ipCIDR: "", + batchIPCIDR: "", + + // region + regions: [], + regionType: "country" } }, methods: { - add: function () { + addIPRange: function () { this.isAdding = true let that = this setTimeout(function () { that.$refs.ipRangeFrom.focus() }, 100) }, + addCIDR: function () { + this.isAdding = true + let that = this + setTimeout(function () { + that.$refs.ipCIDR.focus() + }, 100) + }, + addRegions: function () { + this.isAdding = true + }, + addRegion: function (regionType) { + this.regionType = regionType + }, remove: function (index) { this.ranges.$remove(index) }, @@ -32,6 +57,18 @@ Vue.component("ns-route-ranges-box", { this.isAdding = false this.ipRangeFrom = "" this.ipRangeTo = "" + this.isReverse = false + }, + cancelIPCIDR: function () { + this.isAdding = false + this.ipCIDR = "" + this.isReverse = false + }, + cancelRegions: function () { + this.isAdding = false + this.regions = [] + this.regionType = "country" + this.isReverse = false }, confirmIPRange: function () { // 校验IP @@ -56,21 +93,74 @@ Vue.component("ns-route-ranges-box", { type: "ipRange", params: { ipFrom: this.ipRangeFrom, - ipTo: this.ipRangeTo + ipTo: this.ipRangeTo, + isReverse: this.isReverse } }) this.cancelIPRange() }, - addBatch: function () { + confirmIPCIDR: function () { + let that = this + if (this.ipCIDR.length == 0) { + teaweb.warn("请填写CIDR", function () { + that.$refs.ipCIDR.focus() + }) + return + } + if (!this.validateCIDR(this.ipCIDR)) { + teaweb.warn("请输入正确的CIDR", function () { + that.$refs.ipCIDR.focus() + }) + return + } + + + this.ranges.push({ + type: "cidr", + params: { + cidr: this.ipCIDR, + isReverse: this.isReverse + } + }) + this.cancelIPCIDR() + }, + confirmRegions: function () { + if (this.regions.length == 0) { + this.cancelRegions() + return + } + this.ranges.push({ + type: "region", + params: { + regions: this.regions, + isReverse: this.isReverse + } + }) + this.cancelRegions() + }, + addBatchIPRange: function () { this.isAddingBatch = true let that = this setTimeout(function () { that.$refs.batchIPRange.focus() }, 100) }, + addBatchCIDR: function () { + this.isAddingBatch = true + let that = this + setTimeout(function () { + that.$refs.batchIPCIDR.focus() + }, 100) + }, cancelBatchIPRange: function () { this.isAddingBatch = false this.batchIPRange = "" + this.isReverse = false + }, + cancelBatchIPCIDR: function () { + this.isAddingBatch = false + this.batchIPCIDR = "" + this.isReverse = false }, confirmBatchIPRange: function () { let that = this @@ -105,7 +195,8 @@ Vue.component("ns-route-ranges-box", { type: "ipRange", params: { ipFrom: ipFrom, - ipTo: ipTo + ipTo: ipTo, + isReverse: that.isReverse } }) }) @@ -120,7 +211,114 @@ Vue.component("ns-route-ranges-box", { }) this.cancelBatchIPRange() }, + confirmBatchIPCIDR: function () { + let that = this + let rangesText = this.batchIPCIDR + if (rangesText.length == 0) { + teaweb.warn("请填写要加入的CIDR", function () { + that.$refs.batchIPCIDR.focus() + }) + return + } + + let validRanges = [] + let invalidLine = "" + rangesText.split("\n").forEach(function (line) { + let cidr = line.trim() + if (cidr.length == 0) { + return + } + if (!that.validateCIDR(cidr)) { + invalidLine = line + return + } + validRanges.push({ + type: "cidr", + params: { + cidr: cidr, + isReverse: that.isReverse + } + }) + }) + if (invalidLine.length > 0) { + teaweb.warn("'" + invalidLine + "'格式错误", function () { + that.$refs.batchIPCIDR.focus() + }) + return + } + validRanges.forEach(function (v) { + that.ranges.push(v) + }) + this.cancelBatchIPCIDR() + }, + selectRegionCountry: function (country) { + if (country == null) { + return + } + this.regions.push({ + type: "country", + id: country.id, + name: country.name + }) + this.$refs.regionCountryComboBox.clear() + }, + selectRegionProvince: function (province) { + if (province == null) { + return + } + this.regions.push({ + type: "province", + id: province.id, + name: province.name + }) + this.$refs.regionProvinceComboBox.clear() + }, + selectRegionCity: function (city) { + if (city == null) { + return + } + this.regions.push({ + type: "city", + id: city.id, + name: city.name + }) + this.$refs.regionCityComboBox.clear() + }, + selectRegionProvider: function (provider) { + if (provider == null) { + return + } + this.regions.push({ + type: "provider", + id: provider.id, + name: provider.name + }) + this.$refs.regionProviderComboBox.clear() + }, + removeRegion: function (index) { + this.regions.$remove(index) + }, validateIP: function (ip) { + if (ip.length == 0) { + return + } + + // IPv6 + if (ip.indexOf(":") >= 0) { + let pieces = ip.split(":") + if (pieces.length > 8) { + return false + } + let isOk = true + pieces.forEach(function (piece) { + if (!/^[\da-fA-F]{0,4}$/.test(piece)) { + isOk = false + } + }) + + return isOk + } + if (!ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) { return false } @@ -133,50 +331,215 @@ Vue.component("ns-route-ranges-box", { } }) return isOk + }, + validateCIDR: function (cidr) { + let pieces = cidr.split("/") + if (pieces.length != 2) { + return false + } + let ip = pieces[0] + if (!this.validateIP(ip)) { + return false + } + let mask = pieces[1] + if (!/^\d{1,3}$/.test(mask)) { + return false + } + mask = parseInt(mask, 10) + if (cidr.indexOf(":") >= 0) { // IPv6 + return mask <= 128 + } + return mask <= 32 + }, + updateRangeType: function (rangeType) { + this.rangeType = rangeType } }, template: `