This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"sort"
"strconv"
)
const (
RegionCityStateEnabled = 1 // 已启用
RegionCityStateDisabled = 0 // 已禁用
)
type RegionCityDAO dbs.DAO
func NewRegionCityDAO() *RegionCityDAO {
return dbs.NewDAO(&RegionCityDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeRegionCities",
Model: new(RegionCity),
PkName: "id",
},
}).(*RegionCityDAO)
}
var SharedRegionCityDAO *RegionCityDAO
func init() {
dbs.OnReady(func() {
SharedRegionCityDAO = NewRegionCityDAO()
})
}
// EnableRegionCity 启用条目
func (this *RegionCityDAO) EnableRegionCity(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionCityStateEnabled).
Update()
return err
}
// DisableRegionCity 禁用条目
func (this *RegionCityDAO) DisableRegionCity(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionCityStateDisabled).
Update()
return err
}
// FindEnabledRegionCity 查找启用中的条目
func (this *RegionCityDAO) FindEnabledRegionCity(tx *dbs.Tx, id int64) (*RegionCity, error) {
result, err := this.Query(tx).
Attr("valueId", id).
Attr("state", RegionCityStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*RegionCity), err
}
// FindRegionCityName 根据主键查找名称
func (this *RegionCityDAO) FindRegionCityName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
// FindCityWithDataId 根据数据ID查找城市
func (this *RegionCityDAO) FindCityWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
Result(RegionCityField_ValueId).
FindInt64Col(0)
}
// CreateCity 创建城市
func (this *RegionCityDAO) CreateCity(tx *dbs.Tx, provinceId int64, name string, dataId string) (int64, error) {
var op = NewRegionCityOperator()
op.ProvinceId = provinceId
op.Name = name
op.DataId = dataId
op.State = RegionCityStateEnabled
var codes = []string{name}
codesJSON, err := json.Marshal(codes)
if err != nil {
return 0, err
}
op.Codes = codesJSON
err = this.Save(tx, op)
if err != nil {
return 0, err
}
var cityId = types.Int64(op.Id)
// value id
err = this.Query(tx).
Pk(cityId).
Set(RegionCityField_ValueId, cityId).
UpdateQuickly()
if err != nil {
return 0, err
}
return cityId, nil
}
// FindCityIdWithName 根据城市名查找城市ID
func (this *RegionCityDAO) FindCityIdWithName(tx *dbs.Tx, provinceId int64, cityName string) (int64, error) {
return this.Query(tx).
Attr("provinceId", provinceId).
Where("(name=:cityName OR customName=:cityName OR JSON_CONTAINS(codes, :cityNameJSON) OR JSON_CONTAINS(customCodes, :cityNameJSON))").
Param("cityName", cityName).
Param("cityNameJSON", strconv.Quote(cityName)). // 查询的需要是个JSON字符串所以这里加双引号
Result(RegionCityField_ValueId).
FindInt64Col(0)
}
// FindAllEnabledCities 获取所有城市信息
func (this *RegionCityDAO) FindAllEnabledCities(tx *dbs.Tx) (result []*RegionCity, err error) {
_, err = this.Query(tx).
State(RegionCityStateEnabled).
Slice(&result).
FindAll()
return
}
// FindAllEnabledCitiesWithProvinceId 获取某个省份下的所有城市
func (this *RegionCityDAO) FindAllEnabledCitiesWithProvinceId(tx *dbs.Tx, provinceId int64) (result []*RegionCity, err error) {
_, err = this.Query(tx).
Attr("provinceId", provinceId).
State(RegionCityStateEnabled).
Slice(&result).
FindAll()
return
}
// UpdateCityCustom 自定义城市信息
func (this *RegionCityDAO) UpdateCityCustom(tx *dbs.Tx, cityId int64, customName string, customCodes []string) error {
if customCodes == nil {
customCodes = []string{}
}
customCodesJSON, err := json.Marshal(customCodes)
if err != nil {
return err
}
return this.Query(tx).
Attr(RegionCityField_ValueId, cityId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
}
// FindSimilarCities 查找类似城市名
func (this *RegionCityDAO) FindSimilarCities(cities []*RegionCity, cityName string, size int) (result []*RegionCity) {
if len(cities) == 0 {
return
}
var similarResult = []maps.Map{}
for _, city := range cities {
var similarityList = []float32{}
for _, code := range city.AllCodes() {
var similarity = utils.Similar(cityName, code)
if similarity > 0 {
similarityList = append(similarityList, similarity)
}
}
if len(similarityList) > 0 {
similarResult = append(similarResult, maps.Map{
"similarity": numberutils.Max(similarityList...),
"city": city,
})
}
}
sort.Slice(similarResult, func(i, j int) bool {
return similarResult[i].GetFloat32("similarity") > similarResult[j].GetFloat32("similarity")
})
if len(similarResult) > size {
similarResult = similarResult[:size]
}
for _, r := range similarResult {
result = append(result, r.Get("city").(*RegionCity))
}
return
}

View File

@@ -0,0 +1,6 @@
package regions
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,44 @@
package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionCityField_Id dbs.FieldName = "id" // ID
RegionCityField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionCityField_ProvinceId dbs.FieldName = "provinceId" // 省份ID
RegionCityField_Name dbs.FieldName = "name" // 名称
RegionCityField_Codes dbs.FieldName = "codes" // 代号
RegionCityField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionCityField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionCityField_State dbs.FieldName = "state" // 状态
RegionCityField_DataId dbs.FieldName = "dataId" // 原始数据ID
)
// RegionCity 区域-城市
type RegionCity struct {
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
ProvinceId uint32 `field:"provinceId"` // 省份ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
CustomCodes dbs.JSON `field:"customCodes"` // 自定义代号
State uint8 `field:"state"` // 状态
DataId string `field:"dataId"` // 原始数据ID
}
type RegionCityOperator struct {
Id any // ID
ValueId any // 实际ID
ProvinceId any // 省份ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
}
func NewRegionCityOperator() *RegionCityOperator {
return &RegionCityOperator{}
}

View File

@@ -0,0 +1,57 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/iwind/TeaGo/lists"
)
func (this *RegionCity) DecodeCodes() []string {
if len(this.Codes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.Codes, &result)
if err != nil {
remotelogs.Error("RegionCity.DecodeCodes", err.Error())
}
return result
}
func (this *RegionCity) DecodeCustomCodes() []string {
if len(this.CustomCodes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.CustomCodes, &result)
if err != nil {
remotelogs.Error("RegionCity.DecodeCustomCodes", err.Error())
}
return result
}
func (this *RegionCity) DisplayName() string {
if len(this.CustomName) > 0 {
return this.CustomName
}
return this.Name
}
func (this *RegionCity) AllCodes() []string {
var codes = this.DecodeCodes()
if len(this.Name) > 0 && !lists.ContainsString(codes, this.Name) {
codes = append(codes, this.Name)
}
if len(this.CustomName) > 0 && !lists.ContainsString(codes, this.CustomName) {
codes = append(codes, this.CustomName)
}
for _, code := range this.DecodeCustomCodes() {
if !lists.ContainsString(codes, code) {
codes = append(codes, code)
}
}
return codes
}

View File

@@ -0,0 +1,284 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/regionconfigs"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"github.com/mozillazg/go-pinyin"
"sort"
"strconv"
"strings"
)
const (
RegionCountryStateEnabled = 1 // 已启用
RegionCountryStateDisabled = 0 // 已禁用
)
var regionCountryIdAndNameCacheMap = map[int64]string{} // country id => name
type RegionCountryDAO dbs.DAO
func NewRegionCountryDAO() *RegionCountryDAO {
return dbs.NewDAO(&RegionCountryDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeRegionCountries",
Model: new(RegionCountry),
PkName: "id",
},
}).(*RegionCountryDAO)
}
var SharedRegionCountryDAO *RegionCountryDAO
func init() {
dbs.OnReady(func() {
SharedRegionCountryDAO = NewRegionCountryDAO()
})
}
// EnableRegionCountry 启用条目
func (this *RegionCountryDAO) EnableRegionCountry(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionCountryStateEnabled).
Update()
return err
}
// DisableRegionCountry 禁用条目
func (this *RegionCountryDAO) DisableRegionCountry(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionCountryStateDisabled).
Update()
return err
}
// FindEnabledRegionCountry 查找启用中的条目
func (this *RegionCountryDAO) FindEnabledRegionCountry(tx *dbs.Tx, id int64) (*RegionCountry, error) {
result, err := this.Query(tx).
Attr("valueId", id).
Attr("state", RegionCountryStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*RegionCountry), err
}
// FindRegionCountryName 根据主键查找名称
func (this *RegionCountryDAO) FindRegionCountryName(tx *dbs.Tx, id int64) (string, error) {
SharedCacheLocker.Lock()
defer SharedCacheLocker.Unlock()
name, ok := regionCountryIdAndNameCacheMap[id]
if ok {
return name, nil
}
name, err := this.Query(tx).
Attr("valueId", id).
Result("name").
FindStringCol("")
if err != nil {
return "", err
}
if len(name) > 0 {
regionCountryIdAndNameCacheMap[id] = name
}
return name, nil
}
// FindRegionCountryRouteCode 查找国家|地区线路代号
func (this *RegionCountryDAO) FindRegionCountryRouteCode(tx *dbs.Tx, countryId int64) (string, error) {
return this.Query(tx).
Attr("valueId", countryId).
Result("routeCode").
FindStringCol("")
}
// FindCountryIdWithDataId 根据数据ID查找国家
func (this *RegionCountryDAO) FindCountryIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
Result(RegionCountryField_ValueId).
FindInt64Col(0)
}
// FindCountryIdWithName 根据国家名查找国家ID
func (this *RegionCountryDAO) FindCountryIdWithName(tx *dbs.Tx, countryName string) (int64, error) {
return this.Query(tx).
Where("(name=:countryName OR JSON_CONTAINS(codes, :countryNameJSON) OR customName=:countryName OR JSON_CONTAINS(customCodes, :countryNameJSON))").
Param("countryName", countryName).
Param("countryNameJSON", strconv.Quote(countryName)). // 查询的需要是个JSON字符串所以这里加双引号
Result(RegionCountryField_ValueId).
FindInt64Col(0)
}
// CreateCountry 根据数据ID创建国家
func (this *RegionCountryDAO) CreateCountry(tx *dbs.Tx, name string, dataId string) (int64, error) {
var op = NewRegionCountryOperator()
op.Name = name
pinyinPieces := pinyin.Pinyin(name, pinyin.NewArgs())
pinyinResult := []string{}
for _, piece := range pinyinPieces {
pinyinResult = append(pinyinResult, strings.Join(piece, " "))
}
pinyinJSON, err := json.Marshal([]string{strings.Join(pinyinResult, " ")})
if err != nil {
return 0, err
}
op.Pinyin = pinyinJSON
codes := []string{name}
codesJSON, err := json.Marshal(codes)
if err != nil {
return 0, err
}
op.Codes = codesJSON
op.DataId = dataId
op.State = RegionCountryStateEnabled
err = this.Save(tx, op)
if err != nil {
return 0, err
}
var countryId = types.Int64(op.Id)
err = this.Query(tx).
Pk(countryId).
Set(RegionCountryField_ValueId, countryId).
UpdateQuickly()
if err != nil {
return 0, err
}
return countryId, nil
}
// FindAllEnabledCountriesOrderByPinyin 查找所有可用的国家并按拼音排序
func (this *RegionCountryDAO) FindAllEnabledCountriesOrderByPinyin(tx *dbs.Tx) (result []*RegionCountry, err error) {
ones, err := this.Query(tx).
State(RegionCountryStateEnabled).
Asc("JSON_EXTRACT(pinyin, '$[0]')").
FindAll()
if err != nil {
return nil, err
}
// resort China special regions
var chinaRegionMap = map[int64]*RegionCountry{} // countryId => *RegionCountry
for _, one := range ones {
var country = one.(*RegionCountry)
var valueId = int64(country.ValueId)
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
chinaRegionMap[valueId] = country
}
}
for _, one := range ones {
var country = one.(*RegionCountry)
var valueId = int64(country.ValueId)
if valueId == regionconfigs.RegionChinaId {
result = append(result, country)
// add hk, tw, mo, mainland ...
for _, subRegionId := range regionconfigs.FindAllGreaterChinaSubRegionIds() {
subRegion, ok := chinaRegionMap[subRegionId]
if ok {
result = append(result, subRegion)
}
}
continue
}
if regionconfigs.CheckRegionIsInGreaterChina(valueId) {
continue
}
result = append(result, country)
}
return
}
// FindAllCountries 查找所有可用的国家
func (this *RegionCountryDAO) FindAllCountries(tx *dbs.Tx) (result []*RegionCountry, err error) {
_, err = this.Query(tx).
State(RegionCountryStateEnabled).
Slice(&result).
Asc(RegionCountryField_ValueId).
FindAll()
return
}
// UpdateCountryCustom 修改国家/地区自定义
func (this *RegionCountryDAO) UpdateCountryCustom(tx *dbs.Tx, countryId int64, customName string, customCodes []string) error {
if customCodes == nil {
customCodes = []string{}
}
customCodesJSON, err := json.Marshal(customCodes)
if err != nil {
return err
}
defer func() {
SharedCacheLocker.Lock()
regionCountryIdAndNameCacheMap = map[int64]string{}
SharedCacheLocker.Unlock()
}()
return this.Query(tx).
Attr("valueId", countryId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
}
// FindSimilarCountries 查找类似国家/地区名
func (this *RegionCountryDAO) FindSimilarCountries(countries []*RegionCountry, countryName string, size int) (result []*RegionCountry) {
if len(countries) == 0 {
return
}
var similarResult = []maps.Map{}
for _, country := range countries {
var similarityList = []float32{}
for _, code := range country.AllCodes() {
var similarity = utils.Similar(countryName, code)
if similarity > 0 {
similarityList = append(similarityList, similarity)
}
}
if len(similarityList) > 0 {
similarResult = append(similarResult, maps.Map{
"similarity": numberutils.Max(similarityList...),
"country": country,
})
}
}
sort.Slice(similarResult, func(i, j int) bool {
return similarResult[i].GetFloat32("similarity") > similarResult[j].GetFloat32("similarity")
})
if len(similarResult) > size {
similarResult = similarResult[:size]
}
for _, r := range similarResult {
result = append(result, r.Get("country").(*RegionCountry))
}
return
}

View File

@@ -0,0 +1,47 @@
package regions
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
"github.com/iwind/TeaGo/dbs"
"testing"
)
func TestRegionCountryDAO_FindCountryIdWithName(t *testing.T) {
dbs.NotifyReady()
for _, name := range []string{
"中国",
"中华人民共和国",
"美国",
"美利坚合众国",
"美利坚",
} {
countryId, err := SharedRegionCountryDAO.FindCountryIdWithName(nil, name)
if err != nil {
t.Fatal(err)
}
t.Log(name, ":", countryId)
}
}
func TestRegionCountryDAO_FindSimilarCountries(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
countries, err := SharedRegionCountryDAO.FindAllCountries(tx)
if err != nil {
t.Fatal(err)
}
for _, countryName := range []string{"中国", "布基纳法索", "哥伦比亚", "德意志共和国", "美利坚", "刚果金"} {
t.Log("====" + countryName + "====")
var countries = SharedRegionCountryDAO.FindSimilarCountries(countries, countryName, 5)
if err != nil {
t.Fatal(err)
}
for _, country := range countries {
t.Log(country.Name, country.AllCodes())
}
}
}

View File

@@ -0,0 +1,53 @@
package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionCountryField_Id dbs.FieldName = "id" // ID
RegionCountryField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionCountryField_ValueCode dbs.FieldName = "valueCode" // 值代号
RegionCountryField_Name dbs.FieldName = "name" // 名称
RegionCountryField_Codes dbs.FieldName = "codes" // 代号
RegionCountryField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionCountryField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionCountryField_State dbs.FieldName = "state" // 状态
RegionCountryField_DataId dbs.FieldName = "dataId" // 原始数据ID
RegionCountryField_Pinyin dbs.FieldName = "pinyin" // 拼音
RegionCountryField_IsCommon dbs.FieldName = "isCommon" // 是否常用
RegionCountryField_RouteCode dbs.FieldName = "routeCode" // 线路代号
)
// RegionCountry 区域-国家/地区
type RegionCountry struct {
Id uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
ValueCode string `field:"valueCode"` // 值代号
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
CustomCodes dbs.JSON `field:"customCodes"` // 自定义代号
State uint8 `field:"state"` // 状态
DataId string `field:"dataId"` // 原始数据ID
Pinyin dbs.JSON `field:"pinyin"` // 拼音
IsCommon bool `field:"isCommon"` // 是否常用
RouteCode string `field:"routeCode"` // 线路代号
}
type RegionCountryOperator struct {
Id any // ID
ValueId any // 实际ID
ValueCode any // 值代号
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
Pinyin any // 拼音
IsCommon any // 是否常用
RouteCode any // 线路代号
}
func NewRegionCountryOperator() *RegionCountryOperator {
return &RegionCountryOperator{}
}

View File

@@ -0,0 +1,57 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/iwind/TeaGo/lists"
)
func (this *RegionCountry) DecodeCodes() []string {
if len(this.Codes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.Codes, &result)
if err != nil {
remotelogs.Error("RegionCountry.DecodeCodes", err.Error())
}
return result
}
func (this *RegionCountry) DecodeCustomCodes() []string {
if len(this.CustomCodes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.CustomCodes, &result)
if err != nil {
remotelogs.Error("RegionCountry.DecodeCustomCodes", err.Error())
}
return result
}
func (this *RegionCountry) DisplayName() string {
if len(this.CustomName) > 0 {
return this.CustomName
}
return this.Name
}
func (this *RegionCountry) AllCodes() []string {
var codes = this.DecodeCodes()
if len(this.Name) > 0 && !lists.ContainsString(codes, this.Name) {
codes = append(codes, this.Name)
}
if len(this.CustomName) > 0 && !lists.ContainsString(codes, this.CustomName) {
codes = append(codes, this.CustomName)
}
for _, code := range this.DecodeCustomCodes() {
if !lists.ContainsString(codes, code) {
codes = append(codes, code)
}
}
return codes
}

View File

@@ -0,0 +1,178 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"sort"
"strconv"
)
const (
RegionProviderStateEnabled = 1 // 已启用
RegionProviderStateDisabled = 0 // 已禁用
)
type RegionProviderDAO dbs.DAO
func NewRegionProviderDAO() *RegionProviderDAO {
return dbs.NewDAO(&RegionProviderDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeRegionProviders",
Model: new(RegionProvider),
PkName: "id",
},
}).(*RegionProviderDAO)
}
var SharedRegionProviderDAO *RegionProviderDAO
func init() {
dbs.OnReady(func() {
SharedRegionProviderDAO = NewRegionProviderDAO()
})
}
// EnableRegionProvider 启用条目
func (this *RegionProviderDAO) EnableRegionProvider(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionProviderStateEnabled).
Update()
return err
}
// DisableRegionProvider 禁用条目
func (this *RegionProviderDAO) DisableRegionProvider(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionProviderStateDisabled).
Update()
return err
}
// FindEnabledRegionProvider 查找启用中的条目
func (this *RegionProviderDAO) FindEnabledRegionProvider(tx *dbs.Tx, id int64) (*RegionProvider, error) {
result, err := this.Query(tx).
Attr("valueId", id).
Attr("state", RegionProviderStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*RegionProvider), err
}
// FindRegionProviderName 根据主键查找名称
func (this *RegionProviderDAO) FindRegionProviderName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
// FindProviderIdWithName 根据服务商名称查找服务商ID
func (this *RegionProviderDAO) FindProviderIdWithName(tx *dbs.Tx, providerName string) (int64, error) {
return this.Query(tx).
Where("(name=:providerName OR customName=:providerName OR JSON_CONTAINS(codes, :providerNameJSON) OR JSON_CONTAINS(customCodes, :providerNameJSON))").
Param("providerName", providerName).
Param("providerNameJSON", strconv.Quote(providerName)). // 查询的需要是个JSON字符串所以这里加双引号
Result(RegionProviderField_ValueId).
FindInt64Col(0)
}
// CreateProvider 创建Provider
func (this *RegionProviderDAO) CreateProvider(tx *dbs.Tx, name string) (int64, error) {
var op = NewRegionProviderOperator()
op.Name = name
codesJSON, err := json.Marshal([]string{name})
if err != nil {
return 0, err
}
op.Codes = codesJSON
providerId, err := this.SaveInt64(tx, op)
if err != nil {
return 0, err
}
err = this.Query(tx).
Pk(providerId).
Set(RegionProviderField_ValueId, providerId).
UpdateQuickly()
if err != nil {
return 0, err
}
return providerId, nil
}
// FindAllEnabledProviders 查找所有服务商
func (this *RegionProviderDAO) FindAllEnabledProviders(tx *dbs.Tx) (result []*RegionProvider, err error) {
_, err = this.Query(tx).
State(RegionProviderStateEnabled).
Slice(&result).
FindAll()
return
}
// UpdateProviderCustom 修改ISP自定义信息
func (this *RegionProviderDAO) UpdateProviderCustom(tx *dbs.Tx, providerId int64, customName string, customCodes []string) error {
if customCodes == nil {
customCodes = []string{}
}
customCodesJSON, err := json.Marshal(customCodes)
if err != nil {
return err
}
return this.Query(tx).
Attr("valueId", providerId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
}
// FindSimilarProviders 查找类似ISP运营商
func (this *RegionProviderDAO) FindSimilarProviders(providers []*RegionProvider, providerName string, size int) (result []*RegionProvider) {
if len(providers) == 0 {
return
}
var similarResult = []maps.Map{}
for _, provider := range providers {
var similarityList = []float32{}
for _, code := range provider.AllCodes() {
var similarity = utils.Similar(providerName, code)
if similarity > 0 {
similarityList = append(similarityList, similarity)
}
}
if len(similarityList) > 0 {
similarResult = append(similarResult, maps.Map{
"similarity": numberutils.Max(similarityList...),
"provider": provider,
})
}
}
sort.Slice(similarResult, func(i, j int) bool {
return similarResult[i].GetFloat32("similarity") > similarResult[j].GetFloat32("similarity")
})
if len(similarResult) > size {
similarResult = similarResult[:size]
}
for _, r := range similarResult {
result = append(result, r.Get("provider").(*RegionProvider))
}
return
}

View File

@@ -0,0 +1,6 @@
package regions
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,38 @@
package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionProviderField_Id dbs.FieldName = "id" // ID
RegionProviderField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionProviderField_Name dbs.FieldName = "name" // 名称
RegionProviderField_Codes dbs.FieldName = "codes" // 代号
RegionProviderField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionProviderField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionProviderField_State dbs.FieldName = "state" // 状态
)
// RegionProvider 区域-运营商
type RegionProvider struct {
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
CustomCodes dbs.JSON `field:"customCodes"` // 自定义代号
State uint8 `field:"state"` // 状态
}
type RegionProviderOperator struct {
Id any // ID
ValueId any // 实际ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
}
func NewRegionProviderOperator() *RegionProviderOperator {
return &RegionProviderOperator{}
}

View File

@@ -0,0 +1,57 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/iwind/TeaGo/lists"
)
func (this *RegionProvider) DecodeCodes() []string {
if len(this.Codes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.Codes, &result)
if err != nil {
remotelogs.Error("RegionProvider.DecodeCodes", err.Error())
}
return result
}
func (this *RegionProvider) DecodeCustomCodes() []string {
if len(this.CustomCodes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.CustomCodes, &result)
if err != nil {
remotelogs.Error("RegionProvider.DecodeCustomCodes", err.Error())
}
return result
}
func (this *RegionProvider) DisplayName() string {
if len(this.CustomName) > 0 {
return this.CustomName
}
return this.Name
}
func (this *RegionProvider) AllCodes() []string {
var codes = this.DecodeCodes()
if len(this.Name) > 0 && !lists.ContainsString(codes, this.Name) {
codes = append(codes, this.Name)
}
if len(this.CustomName) > 0 && !lists.ContainsString(codes, this.CustomName) {
codes = append(codes, this.CustomName)
}
for _, code := range this.DecodeCustomCodes() {
if !lists.ContainsString(codes, code) {
codes = append(codes, code)
}
}
return codes
}

View File

@@ -0,0 +1,247 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"sort"
"strconv"
"strings"
)
const (
RegionProvinceStateEnabled = 1 // 已启用
RegionProvinceStateDisabled = 0 // 已禁用
)
var RegionProvinceSuffixes = []string{"省", "州", "区", "大区", "特区", "港", "岛", "环礁", "谷地", "山", "口岸", "郡", "县", "城", "河", "河畔", "市"}
type RegionProvinceDAO dbs.DAO
func NewRegionProvinceDAO() *RegionProvinceDAO {
return dbs.NewDAO(&RegionProvinceDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeRegionProvinces",
Model: new(RegionProvince),
PkName: "id",
},
}).(*RegionProvinceDAO)
}
var SharedRegionProvinceDAO *RegionProvinceDAO
func init() {
dbs.OnReady(func() {
SharedRegionProvinceDAO = NewRegionProvinceDAO()
})
}
// EnableRegionProvince 启用条目
func (this *RegionProvinceDAO) EnableRegionProvince(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionProvinceStateEnabled).
Update()
return err
}
// DisableRegionProvince 禁用条目
func (this *RegionProvinceDAO) DisableRegionProvince(tx *dbs.Tx, id int64) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionProvinceStateDisabled).
Update()
return err
}
// FindEnabledRegionProvince 查找启用中的条目
func (this *RegionProvinceDAO) FindEnabledRegionProvince(tx *dbs.Tx, id int64) (*RegionProvince, error) {
result, err := this.Query(tx).
Attr("valueId", id).
Attr("state", RegionProvinceStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*RegionProvince), err
}
// FindRegionProvinceName 根据主键查找名称
func (this *RegionProvinceDAO) FindRegionProvinceName(tx *dbs.Tx, id int64) (string, error) {
return this.Query(tx).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
// FindRegionCountryId 获取省份对应的国家|地区
func (this *RegionProvinceDAO) FindRegionCountryId(tx *dbs.Tx, provinceId int64) (int64, error) {
return this.Query(tx).
Attr("valueId", provinceId).
Result("countryId").
FindInt64Col(0)
}
// FindProvinceIdWithDataId 根据数据ID查找省份
func (this *RegionProvinceDAO) FindProvinceIdWithDataId(tx *dbs.Tx, dataId string) (int64, error) {
return this.Query(tx).
Attr("dataId", dataId).
Result(RegionProvinceField_ValueId).
FindInt64Col(0)
}
// FindProvinceIdWithName 根据省份名查找省份ID
func (this *RegionProvinceDAO) FindProvinceIdWithName(tx *dbs.Tx, countryId int64, provinceName string) (int64, error) {
{
provinceId, err := this.findProvinceIdWithExactName(tx, countryId, provinceName)
if err != nil {
return 0, err
}
if provinceId > 0 {
return provinceId, nil
}
}
// 候选词
for _, suffix := range RegionProvinceSuffixes {
var name string
if strings.HasSuffix(provinceName, suffix) {
name = strings.TrimSuffix(provinceName, suffix)
} else {
name = provinceName + suffix
}
provinceId, err := this.findProvinceIdWithExactName(tx, countryId, name)
if err != nil {
return 0, err
}
if provinceId > 0 {
return provinceId, nil
}
}
return 0, nil
}
func (this *RegionProvinceDAO) findProvinceIdWithExactName(tx *dbs.Tx, countryId int64, provinceName string) (int64, error) {
return this.Query(tx).
Attr("countryId", countryId).
Where("(name=:provinceName OR customName=:provinceName OR JSON_CONTAINS(codes, :provinceNameJSON) OR JSON_CONTAINS(customCodes, :provinceNameJSON))").
Param("provinceName", provinceName).
Param("provinceNameJSON", strconv.Quote(provinceName)). // 查询的需要是个JSON字符串所以这里加双引号
Result(RegionProvinceField_ValueId).
FindInt64Col(0)
}
// CreateProvince 创建省份
func (this *RegionProvinceDAO) CreateProvince(tx *dbs.Tx, countryId int64, name string, dataId string) (int64, error) {
var op = NewRegionProvinceOperator()
op.CountryId = countryId
op.Name = name
op.DataId = dataId
op.State = RegionProvinceStateEnabled
var codes = []string{name}
codesJSON, err := json.Marshal(codes)
if err != nil {
return 0, err
}
op.Codes = codesJSON
err = this.Save(tx, op)
if err != nil {
return 0, err
}
var provinceId = types.Int64(op.Id)
err = this.Query(tx).
Pk(provinceId).
Set(RegionProvinceField_ValueId, provinceId).
UpdateQuickly()
if err != nil {
return 0, err
}
return provinceId, nil
}
// FindAllEnabledProvincesWithCountryId 查找某个国家/地区的所有省份
func (this *RegionProvinceDAO) FindAllEnabledProvincesWithCountryId(tx *dbs.Tx, countryId int64) (result []*RegionProvince, err error) {
_, err = this.Query(tx).
State(RegionProvinceStateEnabled).
Attr("countryId", countryId).
Asc(RegionProvinceField_ValueId).
Slice(&result).
FindAll()
return
}
// FindAllEnabledProvinces 查找所有省份
func (this *RegionProvinceDAO) FindAllEnabledProvinces(tx *dbs.Tx) (result []*RegionProvince, err error) {
_, err = this.Query(tx).
State(RegionProvinceStateEnabled).
Asc(RegionProvinceField_ValueId).
Slice(&result).
FindAll()
return
}
// UpdateProvinceCustom 修改自定义省份信息
func (this *RegionProvinceDAO) UpdateProvinceCustom(tx *dbs.Tx, provinceId int64, customName string, customCodes []string) error {
if customCodes == nil {
customCodes = []string{}
}
customCodesJSON, err := json.Marshal(customCodes)
if err != nil {
return err
}
return this.Query(tx).
Attr("valueId", provinceId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
}
// FindSimilarProvinces 查找类似省份名
func (this *RegionProvinceDAO) FindSimilarProvinces(provinces []*RegionProvince, provinceName string, size int) (result []*RegionProvince) {
if len(provinces) == 0 {
return
}
var similarResult = []maps.Map{}
for _, province := range provinces {
var similarityList = []float32{}
for _, code := range province.AllCodes() {
var similarity = utils.Similar(provinceName, code)
if similarity > 0 {
similarityList = append(similarityList, similarity)
}
}
if len(similarityList) > 0 {
similarResult = append(similarResult, maps.Map{
"similarity": numberutils.Max(similarityList...),
"province": province,
})
}
}
sort.Slice(similarResult, func(i, j int) bool {
return similarResult[i].GetFloat32("similarity") > similarResult[j].GetFloat32("similarity")
})
if len(similarResult) > size {
similarResult = similarResult[:size]
}
for _, r := range similarResult {
result = append(result, r.Get("province").(*RegionProvince))
}
return
}

View File

@@ -0,0 +1,74 @@
package regions
import (
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/dbs"
"testing"
)
func TestRegionProvinceDAO_FindProvinceIdWithName(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
for _, name := range []string{
"安徽",
"安徽省",
"广西",
"广西省",
"广西壮族自治区",
"皖",
} {
provinceId, err := SharedRegionProvinceDAO.FindProvinceIdWithName(tx, 1, name)
if err != nil {
t.Fatal(err)
}
t.Log(name, "=>", provinceId)
}
}
func TestRegionProvinceDAO_FindProvinceIdWithName_Suffix(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
for _, name := range []string{
"维埃纳",
"维埃纳省",
"维埃纳大区",
"维埃纳市",
"维埃纳小区", // expect 0
} {
provinceId, err := SharedRegionProvinceDAO.FindProvinceIdWithName(tx, 74, name)
if err != nil {
t.Fatal(err)
}
t.Log(name, "=>", provinceId)
}
}
func TestRegionProvinceDAO_FindSimilarProvinces(t *testing.T) {
dbs.NotifyReady()
var tx *dbs.Tx
var countryId int64 = 1
provinces, err := SharedRegionProvinceDAO.FindAllEnabledProvincesWithCountryId(tx, countryId)
if err != nil {
t.Fatal(err)
}
for _, provinceName := range []string{
"北京",
"北京市",
"安徽",
"安徽省",
"大北京",
} {
t.Log("====" + provinceName + "====")
var provinces = SharedRegionProvinceDAO.FindSimilarProvinces(provinces, provinceName, 5)
if err != nil {
t.Fatal(err)
}
for _, province := range provinces {
t.Log(province.Name, province.AllCodes())
}
}
}

View File

@@ -0,0 +1,47 @@
package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionProvinceField_Id dbs.FieldName = "id" // ID
RegionProvinceField_ValueId dbs.FieldName = "valueId" // 实际ID
RegionProvinceField_CountryId dbs.FieldName = "countryId" // 国家ID
RegionProvinceField_Name dbs.FieldName = "name" // 名称
RegionProvinceField_Codes dbs.FieldName = "codes" // 代号
RegionProvinceField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionProvinceField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionProvinceField_State dbs.FieldName = "state" // 状态
RegionProvinceField_DataId dbs.FieldName = "dataId" // 原始数据ID
RegionProvinceField_RouteCode dbs.FieldName = "routeCode" // 线路代号
)
// RegionProvince 区域-省份
type RegionProvince struct {
Id uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 实际ID
CountryId uint32 `field:"countryId"` // 国家ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
CustomCodes dbs.JSON `field:"customCodes"` // 自定义代号
State uint8 `field:"state"` // 状态
DataId string `field:"dataId"` // 原始数据ID
RouteCode string `field:"routeCode"` // 线路代号
}
type RegionProvinceOperator struct {
Id any // ID
ValueId any // 实际ID
CountryId any // 国家ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
RouteCode any // 线路代号
}
func NewRegionProvinceOperator() *RegionProvinceOperator {
return &RegionProvinceOperator{}
}

View File

@@ -0,0 +1,57 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/iwind/TeaGo/lists"
)
func (this *RegionProvince) DecodeCodes() []string {
if len(this.Codes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.Codes, &result)
if err != nil {
remotelogs.Error("RegionProvince.DecodeCodes", err.Error())
}
return result
}
func (this *RegionProvince) DecodeCustomCodes() []string {
if len(this.CustomCodes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.CustomCodes, &result)
if err != nil {
remotelogs.Error("RegionProvince.DecodeCustomCodes", err.Error())
}
return result
}
func (this *RegionProvince) DisplayName() string {
if len(this.CustomName) > 0 {
return this.CustomName
}
return this.Name
}
func (this *RegionProvince) AllCodes() []string {
var codes = this.DecodeCodes()
if len(this.Name) > 0 && !lists.ContainsString(codes, this.Name) {
codes = append(codes, this.Name)
}
if len(this.CustomName) > 0 && !lists.ContainsString(codes, this.CustomName) {
codes = append(codes, this.CustomName)
}
for _, code := range this.DecodeCustomCodes() {
if !lists.ContainsString(codes, code) {
codes = append(codes, code)
}
}
return codes
}

View File

@@ -0,0 +1,193 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/utils"
"github.com/TeaOSLab/EdgeAPI/internal/utils/numberutils"
_ "github.com/go-sql-driver/mysql"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/dbs"
"github.com/iwind/TeaGo/maps"
"sort"
"strconv"
)
const (
RegionTownStateEnabled = 1 // 已启用
RegionTownStateDisabled = 0 // 已禁用
)
type RegionTownDAO dbs.DAO
func NewRegionTownDAO() *RegionTownDAO {
return dbs.NewDAO(&RegionTownDAO{
DAOObject: dbs.DAOObject{
DB: Tea.Env,
Table: "edgeRegionTowns",
Model: new(RegionTown),
PkName: "id",
},
}).(*RegionTownDAO)
}
var SharedRegionTownDAO *RegionTownDAO
func init() {
dbs.OnReady(func() {
SharedRegionTownDAO = NewRegionTownDAO()
})
}
// EnableRegionTown 启用条目
func (this *RegionTownDAO) EnableRegionTown(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionTownStateEnabled).
Update()
return err
}
// DisableRegionTown 禁用条目
func (this *RegionTownDAO) DisableRegionTown(tx *dbs.Tx, id uint32) error {
_, err := this.Query(tx).
Attr("valueId", id).
Set("state", RegionTownStateDisabled).
Update()
return err
}
// FindEnabledRegionTown 查找启用中的区县
func (this *RegionTownDAO) FindEnabledRegionTown(tx *dbs.Tx, id int64) (*RegionTown, error) {
result, err := this.Query(tx).
Attr("valueId", id).
Attr("state", RegionTownStateEnabled).
Find()
if result == nil {
return nil, err
}
return result.(*RegionTown), err
}
// FindAllRegionTowns 获取所有的区县
func (this *RegionTownDAO) FindAllRegionTowns(tx *dbs.Tx) (result []*RegionTown, err error) {
_, err = this.Query(tx).
State(RegionTownStateEnabled).
Asc(RegionTownField_ValueId).
Slice(&result).
FindAll()
return
}
// FindAllRegionTownsWithCityId 根据城市查找区县
func (this *RegionTownDAO) FindAllRegionTownsWithCityId(tx *dbs.Tx, cityId int64) (result []*RegionTown, err error) {
_, err = this.Query(tx).
State(RegionTownStateEnabled).
Attr("cityId", cityId).
Asc(RegionTownField_ValueId).
Slice(&result).
FindAll()
return
}
// FindTownIdWithName 根据区县名查找区县ID
func (this *RegionTownDAO) FindTownIdWithName(tx *dbs.Tx, cityId int64, townName string) (int64, error) {
return this.Query(tx).
Attr("cityId", cityId).
Where("(name=:townName OR customName=:townName OR JSON_CONTAINS(codes, :townNameJSON) OR JSON_CONTAINS(customCodes, :townNameJSON))").
Param("townName", townName).
Param("townNameJSON", strconv.Quote(townName)). // 查询的需要是个JSON字符串所以这里加双引号
Result(RegionTownField_ValueId).
FindInt64Col(0)
}
// FindRegionTownName 根据主键查找名称
func (this *RegionTownDAO) FindRegionTownName(tx *dbs.Tx, id uint32) (string, error) {
return this.Query(tx).
Attr("valueId", id).
Result("name").
FindStringCol("")
}
// UpdateTownCustom 修改自定义县级信息
func (this *RegionTownDAO) UpdateTownCustom(tx *dbs.Tx, townId int64, customName string, customCodes []string) error {
if customCodes == nil {
customCodes = []string{}
}
customCodesJSON, err := json.Marshal(customCodes)
if err != nil {
return err
}
return this.Query(tx).
Attr("valueId", townId).
Set("customName", customName).
Set("customCodes", customCodesJSON).
UpdateQuickly()
}
// FindSimilarTowns 查找类似区县
func (this *RegionTownDAO) FindSimilarTowns(towns []*RegionTown, townName string, size int) (result []*RegionTown) {
if len(towns) == 0 {
return
}
var similarResult = []maps.Map{}
for _, town := range towns {
var similarityList = []float32{}
for _, code := range town.AllCodes() {
var similarity = utils.Similar(townName, code)
if similarity > 0 {
similarityList = append(similarityList, similarity)
}
}
if len(similarityList) > 0 {
similarResult = append(similarResult, maps.Map{
"similarity": numberutils.Max(similarityList...),
"town": town,
})
}
}
sort.Slice(similarResult, func(i, j int) bool {
return similarResult[i].GetFloat32("similarity") > similarResult[j].GetFloat32("similarity")
})
if len(similarResult) > size {
similarResult = similarResult[:size]
}
for _, r := range similarResult {
result = append(result, r.Get("town").(*RegionTown))
}
return
}
// CreateTown 创建区县
func (this *RegionTownDAO) CreateTown(tx *dbs.Tx, cityId int64, townName string) (int64, error) {
var op = NewRegionTownOperator()
op.CityId = cityId
op.Name = townName
codes, err := json.Marshal([]string{townName})
if err != nil {
return 0, err
}
op.Codes = codes
op.State = RegionTownStateEnabled
townId, err := this.SaveInt64(tx, op)
if err != nil {
return 0, err
}
err = this.Query(tx).
Pk(townId).
Set(RegionTownField_ValueId, townId).
UpdateQuickly()
if err != nil {
return 0, err
}
return townId, nil
}

View File

@@ -0,0 +1,6 @@
package regions_test
import (
_ "github.com/go-sql-driver/mysql"
_ "github.com/iwind/TeaGo/bootstrap"
)

View File

@@ -0,0 +1,44 @@
package regions
import "github.com/iwind/TeaGo/dbs"
const (
RegionTownField_Id dbs.FieldName = "id" // ID
RegionTownField_ValueId dbs.FieldName = "valueId" // 真实ID
RegionTownField_CityId dbs.FieldName = "cityId" // 城市ID
RegionTownField_Name dbs.FieldName = "name" // 名称
RegionTownField_Codes dbs.FieldName = "codes" // 代号
RegionTownField_CustomName dbs.FieldName = "customName" // 自定义名称
RegionTownField_CustomCodes dbs.FieldName = "customCodes" // 自定义代号
RegionTownField_State dbs.FieldName = "state" // 状态
RegionTownField_DataId dbs.FieldName = "dataId" // 原始数据ID
)
// RegionTown 区域-省份
type RegionTown struct {
Id1 uint32 `field:"id"` // ID
ValueId uint32 `field:"valueId"` // 真实ID
CityId uint32 `field:"cityId"` // 城市ID
Name string `field:"name"` // 名称
Codes dbs.JSON `field:"codes"` // 代号
CustomName string `field:"customName"` // 自定义名称
CustomCodes dbs.JSON `field:"customCodes"` // 自定义代号
State uint8 `field:"state"` // 状态
DataId string `field:"dataId"` // 原始数据ID
}
type RegionTownOperator struct {
Id any // ID
ValueId any // 真实ID
CityId any // 城市ID
Name any // 名称
Codes any // 代号
CustomName any // 自定义名称
CustomCodes any // 自定义代号
State any // 状态
DataId any // 原始数据ID
}
func NewRegionTownOperator() *RegionTownOperator {
return &RegionTownOperator{}
}

View File

@@ -0,0 +1,57 @@
package regions
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
"github.com/iwind/TeaGo/lists"
)
func (this *RegionTown) DecodeCodes() []string {
if len(this.Codes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.Codes, &result)
if err != nil {
remotelogs.Error("RegionTown.DecodeCodes", err.Error())
}
return result
}
func (this *RegionTown) DecodeCustomCodes() []string {
if len(this.CustomCodes) == 0 {
return []string{}
}
var result = []string{}
err := json.Unmarshal(this.CustomCodes, &result)
if err != nil {
remotelogs.Error("RegionTown.DecodeCustomCodes", err.Error())
}
return result
}
func (this *RegionTown) DisplayName() string {
if len(this.CustomName) > 0 {
return this.CustomName
}
return this.Name
}
func (this *RegionTown) AllCodes() []string {
var codes = this.DecodeCodes()
if len(this.Name) > 0 && !lists.ContainsString(codes, this.Name) {
codes = append(codes, this.Name)
}
if len(this.CustomName) > 0 && !lists.ContainsString(codes, this.CustomName) {
codes = append(codes, this.CustomName)
}
for _, code := range this.DecodeCustomCodes() {
if !lists.ContainsString(codes, code) {
codes = append(codes, code)
}
}
return codes
}

View File

@@ -0,0 +1,5 @@
package regions
import "sync"
var SharedCacheLocker = sync.RWMutex{}