mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-08 07:50:28 +08:00
优化WAF区域/省份封禁:增加仅允许、增加中国香港澳台、内地等特殊区域
This commit is contained in:
@@ -7,13 +7,12 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ChinaCountryId = 1
|
|
||||||
|
|
||||||
type ProvincesAction struct {
|
type ProvincesAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
@@ -43,7 +42,7 @@ func (this *ProvincesAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||||
RegionCountryId: int64(ChinaCountryId),
|
RegionCountryId: regionconfigs.RegionChinaId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import (
|
|||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ChinaCountryId = 1
|
|
||||||
|
|
||||||
type ProvincesAction struct {
|
type ProvincesAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ func init() {
|
|||||||
Get("/ipadmin/allowList", new(ipadmin.AllowListAction)).
|
Get("/ipadmin/allowList", new(ipadmin.AllowListAction)).
|
||||||
Get("/ipadmin/denyList", new(ipadmin.DenyListAction)).
|
Get("/ipadmin/denyList", new(ipadmin.DenyListAction)).
|
||||||
GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)).
|
GetPost("/ipadmin/countries", new(ipadmin.CountriesAction)).
|
||||||
|
Get("/ipadmin/selectCountriesPopup", new(ipadmin.SelectCountriesPopupAction)).
|
||||||
|
Get("/ipadmin/selectProvincesPopup", new(ipadmin.SelectProvincesPopupAction)).
|
||||||
GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)).
|
GetPost("/ipadmin/provinces", new(ipadmin.ProvincesAction)).
|
||||||
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
|
GetPost("/ipadmin/updateIPPopup", new(ipadmin.UpdateIPPopupAction)).
|
||||||
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
|
Post("/ipadmin/deleteIP", new(ipadmin.DeleteIPAction)).
|
||||||
|
|||||||
@@ -42,9 +42,11 @@ func (this *CountriesAction) RunGet(params struct {
|
|||||||
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var selectedCountryIds = []int64{}
|
var deniedCountryIds = []int64{}
|
||||||
|
var allowedCountryIds = []int64{}
|
||||||
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
||||||
selectedCountryIds = policyConfig.Inbound.Region.DenyCountryIds
|
deniedCountryIds = policyConfig.Inbound.Region.DenyCountryIds
|
||||||
|
allowedCountryIds = policyConfig.Inbound.Region.AllowCountryIds
|
||||||
}
|
}
|
||||||
|
|
||||||
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||||
@@ -52,16 +54,23 @@ func (this *CountriesAction) RunGet(params struct {
|
|||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var countryMaps = []maps.Map{}
|
var deniesCountryMaps = []maps.Map{}
|
||||||
|
var allowedCountryMaps = []maps.Map{}
|
||||||
for _, country := range countriesResp.RegionCountries {
|
for _, country := range countriesResp.RegionCountries {
|
||||||
countryMaps = append(countryMaps, maps.Map{
|
var countryMap = maps.Map{
|
||||||
"id": country.Id,
|
"id": country.Id,
|
||||||
"name": country.DisplayName,
|
"name": country.DisplayName,
|
||||||
"letter": strings.ToUpper(string(country.Pinyin[0][0])),
|
"letter": strings.ToUpper(string(country.Pinyin[0][0])),
|
||||||
"isChecked": lists.ContainsInt64(selectedCountryIds, country.Id),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
this.Data["countries"] = countryMaps
|
if lists.ContainsInt64(deniedCountryIds, country.Id) {
|
||||||
|
deniesCountryMaps = append(deniesCountryMaps, countryMap)
|
||||||
|
}
|
||||||
|
if lists.ContainsInt64(allowedCountryIds, country.Id) {
|
||||||
|
allowedCountryMaps = append(allowedCountryMaps, countryMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["deniedCountries"] = deniesCountryMaps
|
||||||
|
this.Data["allowedCountries"] = allowedCountryMaps
|
||||||
|
|
||||||
// except & only URL Patterns
|
// except & only URL Patterns
|
||||||
this.Data["exceptURLPatterns"] = []*shared.URLPattern{}
|
this.Data["exceptURLPatterns"] = []*shared.URLPattern{}
|
||||||
@@ -88,7 +97,8 @@ func (this *CountriesAction) RunGet(params struct {
|
|||||||
|
|
||||||
func (this *CountriesAction) RunPost(params struct {
|
func (this *CountriesAction) RunPost(params struct {
|
||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
CountryIds []int64
|
DenyCountryIds []int64
|
||||||
|
AllowCountryIds []int64
|
||||||
|
|
||||||
ExceptURLPatternsJSON []byte
|
ExceptURLPatternsJSON []byte
|
||||||
OnlyURLPatternsJSON []byte
|
OnlyURLPatternsJSON []byte
|
||||||
@@ -98,6 +108,8 @@ func (this *CountriesAction) RunPost(params struct {
|
|||||||
// 日志
|
// 日志
|
||||||
defer this.CreateLogInfo(codes.WAF_LogUpdateForbiddenCountries, params.FirewallPolicyId)
|
defer this.CreateLogInfo(codes.WAF_LogUpdateForbiddenCountries, params.FirewallPolicyId)
|
||||||
|
|
||||||
|
// TODO validate denied and allowed countries
|
||||||
|
|
||||||
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
policyConfig, err := dao.SharedHTTPFirewallPolicyDAO.FindEnabledHTTPFirewallPolicyConfig(this.AdminContext(), params.FirewallPolicyId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
@@ -116,7 +128,8 @@ func (this *CountriesAction) RunPost(params struct {
|
|||||||
IsOn: true,
|
IsOn: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
policyConfig.Inbound.Region.DenyCountryIds = params.CountryIds
|
policyConfig.Inbound.Region.DenyCountryIds = params.DenyCountryIds
|
||||||
|
policyConfig.Inbound.Region.AllowCountryIds = params.AllowCountryIds
|
||||||
|
|
||||||
// 例外URL
|
// 例外URL
|
||||||
var exceptURLPatterns = []*shared.URLPattern{}
|
var exceptURLPatterns = []*shared.URLPattern{}
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ChinaCountryId = 1
|
|
||||||
|
|
||||||
type ProvincesAction struct {
|
type ProvincesAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
@@ -42,27 +41,36 @@ func (this *ProvincesAction) RunGet(params struct {
|
|||||||
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
this.NotFound("firewallPolicy", params.FirewallPolicyId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var selectedProvinceIds = []int64{}
|
var deniedProvinceIds = []int64{}
|
||||||
|
var allowedProvinceIds = []int64{}
|
||||||
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
if policyConfig.Inbound != nil && policyConfig.Inbound.Region != nil {
|
||||||
selectedProvinceIds = policyConfig.Inbound.Region.DenyProvinceIds
|
deniedProvinceIds = policyConfig.Inbound.Region.DenyProvinceIds
|
||||||
|
allowedProvinceIds = policyConfig.Inbound.Region.AllowProvinceIds
|
||||||
}
|
}
|
||||||
|
|
||||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||||
RegionCountryId: int64(ChinaCountryId),
|
RegionCountryId: regionconfigs.RegionChinaId,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var provinceMaps = []maps.Map{}
|
var deniedProvinceMaps = []maps.Map{}
|
||||||
|
var allowedProvinceMaps = []maps.Map{}
|
||||||
for _, province := range provincesResp.RegionProvinces {
|
for _, province := range provincesResp.RegionProvinces {
|
||||||
provinceMaps = append(provinceMaps, maps.Map{
|
var provinceMap = maps.Map{
|
||||||
"id": province.Id,
|
"id": province.Id,
|
||||||
"name": province.DisplayName,
|
"name": province.DisplayName,
|
||||||
"isChecked": lists.ContainsInt64(selectedProvinceIds, province.Id),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
this.Data["provinces"] = provinceMaps
|
if lists.ContainsInt64(deniedProvinceIds, province.Id) {
|
||||||
|
deniedProvinceMaps = append(deniedProvinceMaps, provinceMap)
|
||||||
|
}
|
||||||
|
if lists.ContainsInt64(allowedProvinceIds, province.Id) {
|
||||||
|
allowedProvinceMaps = append(allowedProvinceMaps, provinceMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["deniedProvinces"] = deniedProvinceMaps
|
||||||
|
this.Data["allowedProvinces"] = allowedProvinceMaps
|
||||||
|
|
||||||
// except & only URL Patterns
|
// except & only URL Patterns
|
||||||
this.Data["exceptURLPatterns"] = []*shared.URLPattern{}
|
this.Data["exceptURLPatterns"] = []*shared.URLPattern{}
|
||||||
@@ -89,7 +97,8 @@ func (this *ProvincesAction) RunGet(params struct {
|
|||||||
|
|
||||||
func (this *ProvincesAction) RunPost(params struct {
|
func (this *ProvincesAction) RunPost(params struct {
|
||||||
FirewallPolicyId int64
|
FirewallPolicyId int64
|
||||||
ProvinceIds []int64
|
DenyProvinceIds []int64
|
||||||
|
AllowProvinceIds []int64
|
||||||
|
|
||||||
ExceptURLPatternsJSON []byte
|
ExceptURLPatternsJSON []byte
|
||||||
OnlyURLPatternsJSON []byte
|
OnlyURLPatternsJSON []byte
|
||||||
@@ -117,7 +126,8 @@ func (this *ProvincesAction) RunPost(params struct {
|
|||||||
IsOn: true,
|
IsOn: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
policyConfig.Inbound.Region.DenyProvinceIds = params.ProvinceIds
|
policyConfig.Inbound.Region.DenyProvinceIds = params.DenyProvinceIds
|
||||||
|
policyConfig.Inbound.Region.AllowProvinceIds = params.AllowProvinceIds
|
||||||
|
|
||||||
// 例外URL
|
// 例外URL
|
||||||
var exceptURLPatterns = []*shared.URLPattern{}
|
var exceptURLPatterns = []*shared.URLPattern{}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SelectCountriesPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectCountriesPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectCountriesPopupAction) RunGet(params struct {
|
||||||
|
Type string
|
||||||
|
SelectedCountryIds string
|
||||||
|
}) {
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
var selectedCountryIds = utils.SplitNumbers(params.SelectedCountryIds)
|
||||||
|
|
||||||
|
countriesResp, err := this.RPC().RegionCountryRPC().FindAllRegionCountries(this.AdminContext(), &pb.FindAllRegionCountriesRequest{})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// special regions
|
||||||
|
|
||||||
|
var countryMaps = []maps.Map{}
|
||||||
|
for _, country := range countriesResp.RegionCountries {
|
||||||
|
countryMaps = append(countryMaps, maps.Map{
|
||||||
|
"id": country.Id,
|
||||||
|
"name": country.DisplayName,
|
||||||
|
"letter": strings.ToUpper(string(country.Pinyin[0][0])),
|
||||||
|
"pinyin": country.Pinyin,
|
||||||
|
"codes": country.Codes,
|
||||||
|
"isCommon": country.IsCommon,
|
||||||
|
"isChecked": lists.ContainsInt64(selectedCountryIds, country.Id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["countries"] = countryMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package ipadmin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SelectProvincesPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectProvincesPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *SelectProvincesPopupAction) RunGet(params struct {
|
||||||
|
Type string
|
||||||
|
SelectedProvinceIds string
|
||||||
|
}) {
|
||||||
|
this.Data["type"] = params.Type
|
||||||
|
|
||||||
|
var selectedProvinceIds = utils.SplitNumbers(params.SelectedProvinceIds)
|
||||||
|
|
||||||
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{
|
||||||
|
RegionCountryId: regionconfigs.RegionChinaId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var provinceMaps = []maps.Map{}
|
||||||
|
for _, province := range provincesResp.RegionProvinces {
|
||||||
|
provinceMaps = append(provinceMaps, maps.Map{
|
||||||
|
"id": province.Id,
|
||||||
|
"name": province.DisplayName,
|
||||||
|
"isChecked": lists.ContainsInt64(selectedProvinceIds, province.Id),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.Data["provinces"] = provinceMaps
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ type ProvinceOptionsAction struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *ProvinceOptionsAction) RunPost(params struct{}) {
|
func (this *ProvinceOptionsAction) RunPost(params struct{}) {
|
||||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{RegionCountryId: ChinaCountryId})
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{RegionCountryId: regionconfigs.RegionChinaId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,13 +4,12 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
|
||||||
"github.com/iwind/TeaGo/actions"
|
"github.com/iwind/TeaGo/actions"
|
||||||
"github.com/iwind/TeaGo/lists"
|
"github.com/iwind/TeaGo/lists"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ChinaCountryId = 1
|
|
||||||
|
|
||||||
type SelectProvincesPopupAction struct {
|
type SelectProvincesPopupAction struct {
|
||||||
actionutils.ParentAction
|
actionutils.ParentAction
|
||||||
}
|
}
|
||||||
@@ -24,7 +23,7 @@ func (this *SelectProvincesPopupAction) RunGet(params struct {
|
|||||||
}) {
|
}) {
|
||||||
var selectedProvinceIds = utils.SplitNumbers(params.ProvinceIds)
|
var selectedProvinceIds = utils.SplitNumbers(params.ProvinceIds)
|
||||||
|
|
||||||
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{RegionCountryId: ChinaCountryId})
|
provincesResp, err := this.RPC().RegionProvinceRPC().FindAllRegionProvincesWithRegionCountryId(this.AdminContext(), &pb.FindAllRegionProvincesWithRegionCountryIdRequest{RegionCountryId: regionconfigs.RegionChinaId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
return
|
return
|
||||||
|
|||||||
33
web/public/js/components/common/search-box.js
Normal file
33
web/public/js/components/common/search-box.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Vue.component("search-box", {
|
||||||
|
props: ["placeholder", "width"],
|
||||||
|
data: function () {
|
||||||
|
let width = this.width
|
||||||
|
if (width == null) {
|
||||||
|
width = "10em"
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
realWidth: width,
|
||||||
|
realValue: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onInput: function () {
|
||||||
|
this.$emit("input", { value: this.realValue})
|
||||||
|
this.$emit("change", { value: this.realValue})
|
||||||
|
},
|
||||||
|
clearValue: function () {
|
||||||
|
this.realValue = ""
|
||||||
|
this.focus()
|
||||||
|
this.onInput()
|
||||||
|
},
|
||||||
|
focus: function () {
|
||||||
|
this.$refs.valueRef.focus()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<div class="ui input small" :class="{'right labeled': realValue.length > 0}">
|
||||||
|
<input type="text" :placeholder="placeholder" :style="{width: realWidth}" @input="onInput" v-model="realValue" ref="valueRef"/>
|
||||||
|
<a href="" class="ui label blue" v-if="realValue.length > 0" @click.prevent="clearValue" style="padding-right: 0"><i class="icon remove"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
Vue.component("http-firewall-province-selector", {
|
||||||
|
props: ["v-type", "v-provinces"],
|
||||||
|
data: function () {
|
||||||
|
let provinces = this.vProvinces
|
||||||
|
if (provinces == null) {
|
||||||
|
provinces = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
listType: this.vType,
|
||||||
|
provinces: provinces
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addProvince: function () {
|
||||||
|
let selectedProvinceIds = this.provinces.map(function (province) {
|
||||||
|
return province.id
|
||||||
|
})
|
||||||
|
let that = this
|
||||||
|
teaweb.popup("/servers/server/settings/waf/ipadmin/selectProvincesPopup?type=" + this.listType + "&selectedProvinceIds=" + selectedProvinceIds.join(","), {
|
||||||
|
width: "50em",
|
||||||
|
height: "26em",
|
||||||
|
callback: function (resp) {
|
||||||
|
that.provinces = resp.data.selectedProvinces
|
||||||
|
that.$forceUpdate()
|
||||||
|
that.notifyChange()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeProvince: function (index) {
|
||||||
|
this.provinces.$remove(index)
|
||||||
|
this.notifyChange()
|
||||||
|
},
|
||||||
|
resetProvinces: function () {
|
||||||
|
this.provinces = []
|
||||||
|
this.notifyChange()
|
||||||
|
},
|
||||||
|
notifyChange: function () {
|
||||||
|
this.$emit("change", {
|
||||||
|
"provinces": this.provinces
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<span v-if="provinces.length == 0" class="disabled">暂时没有选择<span v-if="listType =='allow'">允许</span><span v-else>封禁</span>的省份。</span>
|
||||||
|
<div v-show="provinces.length > 0">
|
||||||
|
<div class="ui label tiny basic" v-for="(province, index) in provinces" style="margin-bottom: 0.5em">
|
||||||
|
<input type="hidden" :name="listType + 'ProvinceIds'" :value="province.id"/>
|
||||||
|
{{province.name}} <a href="" @click.prevent="removeProvince(index)" title="删除"><i class="icon remove"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<button type="button" class="ui button tiny" @click.prevent="addProvince">修改</button> <button type="button" class="ui button tiny" v-show="provinces.length > 0" @click.prevent="resetProvinces">清空</button>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
Vue.component("http-firewall-region-selector", {
|
||||||
|
props: ["v-type", "v-countries"],
|
||||||
|
data: function () {
|
||||||
|
let countries = this.vCountries
|
||||||
|
if (countries == null) {
|
||||||
|
countries = []
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
listType: this.vType,
|
||||||
|
countries: countries
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addCountry: function () {
|
||||||
|
let selectedCountryIds = this.countries.map(function (country) {
|
||||||
|
return country.id
|
||||||
|
})
|
||||||
|
let that = this
|
||||||
|
teaweb.popup("/servers/server/settings/waf/ipadmin/selectCountriesPopup?type=" + this.listType + "&selectedCountryIds=" + selectedCountryIds.join(","), {
|
||||||
|
width: "52em",
|
||||||
|
height: "30em",
|
||||||
|
callback: function (resp) {
|
||||||
|
that.countries = resp.data.selectedCountries
|
||||||
|
that.$forceUpdate()
|
||||||
|
that.notifyChange()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
removeCountry: function (index) {
|
||||||
|
this.countries.$remove(index)
|
||||||
|
this.notifyChange()
|
||||||
|
},
|
||||||
|
resetCountries: function () {
|
||||||
|
this.countries = []
|
||||||
|
this.notifyChange()
|
||||||
|
},
|
||||||
|
notifyChange: function () {
|
||||||
|
this.$emit("change", {
|
||||||
|
"countries": this.countries
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<span v-if="countries.length == 0" class="disabled">暂时没有选择<span v-if="listType =='allow'">允许</span><span v-else>封禁</span>的区域。</span>
|
||||||
|
<div v-show="countries.length > 0">
|
||||||
|
<div class="ui label tiny basic" v-for="(country, index) in countries" style="margin-bottom: 0.5em">
|
||||||
|
<input type="hidden" :name="listType + 'CountryIds'" :value="country.id"/>
|
||||||
|
({{country.letter}}){{country.name}} <a href="" @click.prevent="removeCountry(index)" title="删除"><i class="icon remove"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<button type="button" class="ui button tiny" @click.prevent="addCountry">修改</button> <button type="button" class="ui button tiny" v-show="countries.length > 0" @click.prevent="resetCountries">清空</button>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
.region-letter-group .item {
|
|
||||||
padding-left: 1em !important;
|
|
||||||
padding-right: 1em !important;
|
|
||||||
}
|
|
||||||
.country-group {
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
.country-group .country-list .item {
|
|
||||||
float: left;
|
|
||||||
width: 12em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
.country-group .country-list .item .checkbox label {
|
|
||||||
font-size: 12px !important;
|
|
||||||
cursor: pointer !important;
|
|
||||||
}
|
|
||||||
/*# sourceMappingURL=countries.css.map */
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["countries.less"],"names":[],"mappings":"AAAA,oBACC;EACC,4BAAA;EACA,6BAAA;;AAIF;EAcC,mBAAA;;AAdD,cACC,cACC;EACC,WAAA;EACA,WAAA;EACA,oBAAA;;AALH,cACC,cACC,MAKC,UAAU;EACT,0BAAA;EACA,0BAAA","file":"countries.css"}
|
|
||||||
@@ -16,45 +16,22 @@
|
|||||||
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(onlyURLPatterns)"/>
|
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(onlyURLPatterns)"/>
|
||||||
<table class="ui table selectable definition">
|
<table class="ui table selectable definition">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">已封禁</td>
|
<td class="title">仅允许的区域</td>
|
||||||
<td>
|
<td>
|
||||||
<span v-if="countSelectedCountries == 0" class="disabled">暂时没有选择封禁区域。</span>
|
<http-firewall-region-selector :v-countries="allowedCountries" :v-type="'allow'" @change="changeAllowedCountries"></http-firewall-region-selector>
|
||||||
<div class="ui label tiny basic" v-for="country in countries" v-if="country.isChecked" style="margin-bottom: 0.5em">
|
|
||||||
<input type="hidden" name="countryIds" :value="country.id"/>
|
|
||||||
({{country.letter}}){{country.name}} <a href="" @click.prevent="deselectCountry(country)" title="取消封禁"><i class="icon remove"></i></a>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>选择封禁区域 *</td>
|
<td class="title">仅封禁的区域</td>
|
||||||
<td>
|
<td>
|
||||||
<more-options-indicator><span v-if="!moreOptionsVisible">选择区域</span><span v-else>完成选择</span></more-options-indicator>
|
<p class="comment" v-if="allowedCountries.length > 0">由于你已设置"仅允许的区域",所以不需要再设置封禁区域。</p>
|
||||||
|
<http-firewall-region-selector :v-countries="deniedCountries" :v-type="'deny'" v-show="allowedCountries.length == 0"></http-firewall-region-selector>
|
||||||
<div class="ui menu tabular tiny region-letter-group" v-show="moreOptionsVisible">
|
|
||||||
<a href="" v-for="group in letterGroups" class="item" :class="{active: group == selectedGroup}" @click.prevent="selectGroup(group)">{{group}}</a>
|
|
||||||
<div class="item right">
|
|
||||||
<div class="ui checkbox" @click.prevent="checkAll">
|
|
||||||
<input type="checkbox" v-model="isCheckingAll"/>
|
|
||||||
<label>全选</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-for="group in letterGroups" v-show="moreOptionsVisible">
|
|
||||||
<div v-for="letter in group" v-if="letterCountries[letter] != null && group == selectedGroup" class="country-group">
|
|
||||||
<h4>{{letter}}</h4>
|
|
||||||
<div class="country-list">
|
|
||||||
<div class="item" v-for="country in letterCountries[letter]">
|
|
||||||
<div class="ui checkbox" @click.prevent="selectCountry(country)">
|
|
||||||
<input type="checkbox" v-model="country.isChecked"/>
|
|
||||||
<label>{{country.name}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clear"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
|
</tr>
|
||||||
|
<tbody v-show="moreOptionsVisible">
|
||||||
<tr>
|
<tr>
|
||||||
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
||||||
<td><url-patterns-box v-model="exceptURLPatterns"></url-patterns-box></td>
|
<td><url-patterns-box v-model="exceptURLPatterns"></url-patterns-box></td>
|
||||||
@@ -63,6 +40,7 @@
|
|||||||
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
||||||
<td><url-patterns-box v-model="onlyURLPatterns"></url-patterns-box></td>
|
<td><url-patterns-box v-model="onlyURLPatterns"></url-patterns-box></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,54 +1,11 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.letterGroups = [
|
|
||||||
"ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VWX", "YZ"
|
|
||||||
];
|
|
||||||
this.selectedGroup = "ABC"
|
|
||||||
this.letterCountries = {}
|
|
||||||
let that = this
|
|
||||||
this.countSelectedCountries = this.countries.$count(function (k, country) {
|
|
||||||
return country.isChecked
|
|
||||||
})
|
|
||||||
this.countries.forEach(function (country) {
|
|
||||||
if (typeof (that.letterCountries[country.letter]) == "undefined") {
|
|
||||||
that.letterCountries[country.letter] = []
|
|
||||||
}
|
|
||||||
that.letterCountries[country.letter].push(country)
|
|
||||||
})
|
|
||||||
this.isCheckingAll = false
|
|
||||||
|
|
||||||
this.selectGroup = function (group) {
|
|
||||||
this.selectedGroup = group
|
|
||||||
}
|
|
||||||
|
|
||||||
this.selectCountry = function (country) {
|
|
||||||
country.isChecked = !country.isChecked
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deselectCountry = function (country) {
|
|
||||||
country.isChecked = false
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.checkAll = function () {
|
|
||||||
this.isCheckingAll = !this.isCheckingAll
|
|
||||||
|
|
||||||
this.countries.forEach(function (country) {
|
|
||||||
country.isChecked = that.isCheckingAll
|
|
||||||
})
|
|
||||||
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.success = function () {
|
this.success = function () {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
teaweb.reload()
|
teaweb.reload()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.change = function () {
|
this.changeAllowedCountries = function (event) {
|
||||||
this.countSelectedCountries = this.countries.$count(function (k, country) {
|
this.allowedCountries = event.countries
|
||||||
return country.isChecked
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
.region-letter-group {
|
|
||||||
.item {
|
|
||||||
padding-left: 1em !important;
|
|
||||||
padding-right: 1em !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.country-group {
|
|
||||||
.country-list {
|
|
||||||
.item {
|
|
||||||
float: left;
|
|
||||||
width: 12em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
|
|
||||||
.checkbox label {
|
|
||||||
font-size: 12px !important;
|
|
||||||
cursor: pointer !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
padding-bottom: 1em;
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"version":3,"sources":["provinces.less"],"names":[],"mappings":"AAAA,cACC;EACC,WAAA;EACA,WAAA;EACA,oBAAA;;AAJF,cACC,MAKC,UAAU;EACT,0BAAA;EACA,0BAAA","file":"provinces.css"}
|
|
||||||
@@ -16,40 +16,22 @@
|
|||||||
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(onlyURLPatterns)"/>
|
<input type="hidden" name="onlyURLPatternsJSON" :value="JSON.stringify(onlyURLPatterns)"/>
|
||||||
<table class="ui table selectable definition">
|
<table class="ui table selectable definition">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">已封禁</td>
|
<td class="title">仅允许的省份</td>
|
||||||
<td>
|
<td>
|
||||||
<span v-if="countSelectedProvinces == 0" class="disabled">暂时没有选择封禁省份。</span>
|
<http-firewall-province-selector :v-provinces="allowedProvinces" :v-type="'allow'" @change="changeAllowedProvinces"></http-firewall-province-selector>
|
||||||
<div class="ui label tiny basic" v-for="province in provinces" v-if="province.isChecked" style="margin-bottom: 0.5em">
|
|
||||||
<input type="hidden" name="provinceIds" :value="province.id"/>
|
|
||||||
{{province.name}} <a href="" @click.prevent="deselectProvince(province)" title="取消封禁"><i class="icon remove"></i></a>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>选择封禁区域</td>
|
<td class="title">仅封禁的省份</td>
|
||||||
<td>
|
<td>
|
||||||
|
<p class="comment" v-if="allowedProvinces.length > 0">由于你已设置"仅允许的省份",所以不需要再设置封禁省份。</p>
|
||||||
<first-menu>
|
<http-firewall-province-selector :v-provinces="deniedProvinces" :v-type="'deny'" v-show="allowedProvinces.length == 0"></http-firewall-province-selector>
|
||||||
<menu-item><more-options-indicator><span v-if="!moreOptionsVisible">选择省份/自治区</span><span v-else>完成选择</span></more-options-indicator></menu-item>
|
|
||||||
<div class="item right" v-show="moreOptionsVisible">
|
|
||||||
<div class="ui checkbox" @click.prevent="checkAll">
|
|
||||||
<input type="checkbox" v-model="isCheckingAll"/>
|
|
||||||
<label>全选</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</first-menu>
|
|
||||||
|
|
||||||
<div class="province-list" v-show="moreOptionsVisible" style="margin-top:0.5em">
|
|
||||||
<div class="item" v-for="province in provinces">
|
|
||||||
<div class="ui checkbox" @click.prevent="selectProvince(province)">
|
|
||||||
<input type="checkbox" v-model="province.isChecked"/>
|
|
||||||
<label>{{province.name}}</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clear"></div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
|
</tr>
|
||||||
|
<tbody v-show="moreOptionsVisible">
|
||||||
<tr>
|
<tr>
|
||||||
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
<td>例外URL <tip-icon content="对这些URL将不做任何限制。"></tip-icon></td>
|
||||||
<td><url-patterns-box v-model="exceptURLPatterns"></url-patterns-box></td>
|
<td><url-patterns-box v-model="exceptURLPatterns"></url-patterns-box></td>
|
||||||
@@ -58,6 +40,7 @@
|
|||||||
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
<td>限制URL <tip-icon content="只对这些URL做限制。"></tip-icon></td>
|
||||||
<td><url-patterns-box v-model="onlyURLPatterns"></url-patterns-box></td>
|
<td><url-patterns-box v-model="onlyURLPatterns"></url-patterns-box></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,40 +1,11 @@
|
|||||||
Tea.context(function () {
|
Tea.context(function () {
|
||||||
this.isCheckingAll = false
|
|
||||||
|
|
||||||
this.countSelectedProvinces = this.provinces.$count(function (k, province) {
|
|
||||||
return province.isChecked
|
|
||||||
})
|
|
||||||
|
|
||||||
this.selectProvince = function (province) {
|
|
||||||
province.isChecked = !province.isChecked
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deselectProvince = function (province) {
|
|
||||||
province.isChecked = false
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.checkAll = function () {
|
|
||||||
this.isCheckingAll = !this.isCheckingAll
|
|
||||||
let that = this
|
|
||||||
this.provinces.forEach(function (province) {
|
|
||||||
province.isChecked = that.isCheckingAll
|
|
||||||
})
|
|
||||||
|
|
||||||
this.change()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.success = function () {
|
this.success = function () {
|
||||||
teaweb.success("保存成功", function () {
|
teaweb.success("保存成功", function () {
|
||||||
teaweb.reload()
|
teaweb.reload()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.changeAllowedProvinces = function (event) {
|
||||||
this.change = function () {
|
this.allowedProvinces = event.provinces
|
||||||
this.countSelectedProvinces = this.provinces.$count(function (k, province) {
|
|
||||||
return province.isChecked
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
.region-letter-group .item {
|
||||||
|
padding-left: 0.8em !important;
|
||||||
|
padding-right: 0.8em !important;
|
||||||
|
}
|
||||||
|
.region-letter-group .item .count {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
.country-groups {
|
||||||
|
max-height: 23em;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
.country-groups .country-group {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
.country-groups .country-group .country-list .item {
|
||||||
|
float: left;
|
||||||
|
width: 9em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.country-groups .country-group .country-list .item .checkbox label {
|
||||||
|
font-size: 12px !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
.country-groups::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=selectCountriesPopup.css.map */
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["selectCountriesPopup.less"],"names":[],"mappings":"AAAA,oBACC;EACC,mBAAA;EACA,oBAAA;;AAHF,oBACC,MAIC;EACC,gBAAA;EACA,WAAA;;AAKH;EACC,gBAAA;EACA,gBAAA;;AAFD,eAIC;EACC,mBAAA;;AALF,eAIC,eAGC,cACC;EACC,WAAA;EACA,UAAA;EACA,oBAAA;;AAXJ,eAIC,eAGC,cACC,MAKC,UAAU;EACT,0BAAA;EACA,0BAAA;;AAOL,eAAe;EACd,UAAA","file":"selectCountriesPopup.css"}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3 v-show="type == 'allow'">选择允许的区域</h3>
|
||||||
|
<h3 v-show="type == 'deny'">选择封禁的区域</h3>
|
||||||
|
<form class="ui form">
|
||||||
|
<div class="ui menu tabular tiny region-letter-group attached">
|
||||||
|
<a href="" v-for="group in letterGroups" class="item" :class="{active: group.code == selectedGroup, disabled: group.countMatched == 0}" @click.prevent="selectGroup(group)">{{group.code}}<span v-if="group.count > 0" class="count"> ({{group.count}})</span></a>
|
||||||
|
<div class="item right">
|
||||||
|
<div class="ui checkbox" @click.prevent="checkAll">
|
||||||
|
<input type="checkbox" v-model="isCheckingAll"/>
|
||||||
|
<label>全选</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="country-groups ui segment attached">
|
||||||
|
<div v-for="group in letterGroups">
|
||||||
|
<div v-if="group.code == commonGroupName && group.code == selectedGroup">
|
||||||
|
<div class="country-group">
|
||||||
|
<div class="country-list">
|
||||||
|
<div class="item" v-for="country in letterCountries[commonGroupName]">
|
||||||
|
<div class="ui checkbox" @click.prevent="selectCountry(country)">
|
||||||
|
<input type="checkbox" v-model="country.isChecked"/>
|
||||||
|
<label><span :class="{blue: country.isMatched}">{{country.name}}</span></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div v-for="letter in group.code" v-if="letterCountries[letter] != null && group.code == selectedGroup" class="country-group">
|
||||||
|
<h4>{{letter}}</h4>
|
||||||
|
<div class="country-list">
|
||||||
|
<div class="item" v-for="country in letterCountries[letter]">
|
||||||
|
<div class="ui checkbox" @click.prevent="selectCountry(country)">
|
||||||
|
<input type="checkbox" v-model="country.isChecked"/>
|
||||||
|
<label><span :class="{blue: country.isMatched}">{{country.name}}</span></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="margin"></div>
|
||||||
|
<div class="ui menu text basic">
|
||||||
|
<div class="item">
|
||||||
|
<button class="ui button primary" @click.prevent="submit">确定</button>
|
||||||
|
</div>
|
||||||
|
<div class="item right" v-show="!searchBoxVisible">
|
||||||
|
<a href="" @click.prevent="showSearchBox"><i class="icon search"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="item right" v-show="searchBoxVisible">
|
||||||
|
<search-box placeholder="关键词" ref="searchBox" @change="changeKeyword"></search-box>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
var commonGroupName = "常用"
|
||||||
|
this.letterGroups = [
|
||||||
|
{
|
||||||
|
"code": commonGroupName,
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ABC",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "DEF",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GHI",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "JKL",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MNO",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PQR",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "STU",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VWX",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "YZ",
|
||||||
|
"count": 0,
|
||||||
|
"countMatched": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
this.commonGroupName = commonGroupName
|
||||||
|
this.selectedGroup = commonGroupName
|
||||||
|
this.letterCountries = {}
|
||||||
|
let that = this
|
||||||
|
this.countSelectedCountries = this.countries.$count(function (k, country) {
|
||||||
|
return country.isChecked
|
||||||
|
})
|
||||||
|
this.countries.forEach(function (country) {
|
||||||
|
// letter
|
||||||
|
if (typeof (that.letterCountries[country.letter]) == "undefined") {
|
||||||
|
that.letterCountries[country.letter] = []
|
||||||
|
}
|
||||||
|
that.letterCountries[country.letter].push(country)
|
||||||
|
|
||||||
|
// common
|
||||||
|
if (country.isCommon) {
|
||||||
|
if (typeof that.letterCountries[commonGroupName] == "undefined") {
|
||||||
|
that.letterCountries[commonGroupName] = []
|
||||||
|
}
|
||||||
|
that.letterCountries[commonGroupName].push(country)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.isCheckingAll = false
|
||||||
|
|
||||||
|
this.$delay(function () {
|
||||||
|
this.change()
|
||||||
|
})
|
||||||
|
|
||||||
|
this.checkAll = function () {
|
||||||
|
this.isCheckingAll = !this.isCheckingAll
|
||||||
|
|
||||||
|
this.countries.forEach(function (country) {
|
||||||
|
country.isChecked = that.isCheckingAll
|
||||||
|
})
|
||||||
|
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectGroup = function (group) {
|
||||||
|
this.selectedGroup = group.code
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectCountry = function (country) {
|
||||||
|
country.isChecked = !country.isChecked
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deselectCountry = function (country) {
|
||||||
|
country.isChecked = false
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change = function () {
|
||||||
|
let that = this
|
||||||
|
this.letterGroups.forEach(function (group) {
|
||||||
|
group.count = 0
|
||||||
|
group.countMatched = 0
|
||||||
|
})
|
||||||
|
this.countries.forEach(function (country) {
|
||||||
|
that.letterGroups.forEach(function (group) {
|
||||||
|
if (group.code.indexOf(country.letter) >= 0 || (group.code == commonGroupName && country.isCommon)) {
|
||||||
|
if (country.isChecked) {
|
||||||
|
group.count++
|
||||||
|
}
|
||||||
|
if (that.matchCountry(country)) {
|
||||||
|
country.isMatched = (that.keyword.length > 0)
|
||||||
|
group.countMatched++
|
||||||
|
} else {
|
||||||
|
country.isMatched = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submit = function () {
|
||||||
|
let selectedCountries = []
|
||||||
|
this.countries.forEach(function (country) {
|
||||||
|
if (country.isChecked) {
|
||||||
|
selectedCountries.push(country)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
NotifyPopup({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
selectedCountries: selectedCountries
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* searching
|
||||||
|
*/
|
||||||
|
this.searchBoxVisible = false
|
||||||
|
this.keyword = ""
|
||||||
|
|
||||||
|
this.showSearchBox = function () {
|
||||||
|
this.searchBoxVisible = true
|
||||||
|
this.$delay(function () {
|
||||||
|
this.$refs.searchBox.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.changeKeyword = function (event) {
|
||||||
|
this.keyword = event.value.trim()
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.matchCountry = function (country) {
|
||||||
|
if (this.keyword.length == 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (teaweb.match(country.name, this.keyword)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (country.pinyin != null && country.pinyin.length > 0) {
|
||||||
|
let matched = false
|
||||||
|
let that = this
|
||||||
|
country.pinyin.forEach(function (code) {
|
||||||
|
if (teaweb.match(code, that.keyword)) {
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (matched) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (country.codes != null && country.codes.length > 0) {
|
||||||
|
let matched = false
|
||||||
|
let that = this
|
||||||
|
country.codes.forEach(function (code) {
|
||||||
|
if (teaweb.match(code, that.keyword)) {
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (matched) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
.region-letter-group {
|
||||||
|
.item {
|
||||||
|
padding-left: 0.8em !important;
|
||||||
|
padding-right: 0.8em !important;
|
||||||
|
|
||||||
|
.count {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.country-groups {
|
||||||
|
max-height: 23em;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.country-group {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
|
||||||
|
.country-list {
|
||||||
|
.item {
|
||||||
|
float: left;
|
||||||
|
width: 9em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
|
.checkbox label {
|
||||||
|
font-size: 12px !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.country-groups::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
}
|
||||||
@@ -7,4 +7,4 @@
|
|||||||
font-size: 12px !important;
|
font-size: 12px !important;
|
||||||
cursor: pointer !important;
|
cursor: pointer !important;
|
||||||
}
|
}
|
||||||
/*# sourceMappingURL=provinces.css.map */
|
/*# sourceMappingURL=selectProvincesPopup.css.map */
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["selectProvincesPopup.less"],"names":[],"mappings":"AAAA,cACC;EACC,WAAA;EACA,WAAA;EACA,oBAAA;;AAJF,cACC,MAKC,UAAU;EACT,0BAAA;EACA,0BAAA","file":"selectProvincesPopup.css"}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<h3 v-show="type == 'allow'">选择允许的省份</h3>
|
||||||
|
<h3 v-show="type == 'deny'">选择封禁的省份</h3>
|
||||||
|
|
||||||
|
<form class="ui form">
|
||||||
|
<table class="ui table">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<first-menu>
|
||||||
|
<div class="item right">
|
||||||
|
<div class="ui checkbox" @click.prevent="checkAll">
|
||||||
|
<input type="checkbox" v-model="isCheckingAll"/>
|
||||||
|
<label>全选</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</first-menu>
|
||||||
|
|
||||||
|
<div class="province-list" style="margin-top:0.5em">
|
||||||
|
<div class="item" v-for="province in provinces">
|
||||||
|
<div class="ui checkbox" @click.prevent="selectProvince(province)">
|
||||||
|
<input type="checkbox" v-model="province.isChecked"/>
|
||||||
|
<label>{{province.name}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="clear"></div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button class="ui button primary" type="button" @click.prevent="submit">确定</button>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.isCheckingAll = false
|
||||||
|
|
||||||
|
this.countSelectedProvinces = this.provinces.$count(function (k, province) {
|
||||||
|
return province.isChecked
|
||||||
|
})
|
||||||
|
|
||||||
|
this.selectProvince = function (province) {
|
||||||
|
province.isChecked = !province.isChecked
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deselectProvince = function (province) {
|
||||||
|
province.isChecked = false
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkAll = function () {
|
||||||
|
this.isCheckingAll = !this.isCheckingAll
|
||||||
|
let that = this
|
||||||
|
this.provinces.forEach(function (province) {
|
||||||
|
province.isChecked = that.isCheckingAll
|
||||||
|
})
|
||||||
|
|
||||||
|
this.change()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.change = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submit = function () {
|
||||||
|
let selectedProvinces = []
|
||||||
|
this.provinces.forEach(function (province) {
|
||||||
|
if (province.isChecked) {
|
||||||
|
selectedProvinces.push(province)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
NotifyPopup({
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
selectedProvinces: selectedProvinces
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user