服务发现基础逻辑

This commit is contained in:
2024-10-12 00:38:18 +08:00
parent d1d7f56ce4
commit e6f5aaa02f
10 changed files with 216 additions and 31 deletions
+23
View File
@@ -1,8 +1,11 @@
package global
import (
"bytes"
"encoding/json"
"fmt"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
"gorm.io/gorm"
"testing"
"work_cation/pkg/gormx"
@@ -154,3 +157,23 @@ func TestInitDB1(t *testing.T) {
fmt.Println(ret)
}
func TestString(t *testing.T) {
var name string = "苏通"
newName, _ := convertToUTF8(name)
fmt.Printf(name)
fmt.Printf(newName)
}
func convertToUTF8(input string) (string, error) {
// 定义其他编码到 UTF-8 的转换器
reader := transform.NewReader(bytes.NewReader([]byte(input)), simplifiedchinese.GBK.NewDecoder())
// 读取转换后的数据
buf := new(bytes.Buffer)
buf.ReadFrom(reader)
utf8Str := buf.String()
return utf8Str, nil
}
+10 -16
View File
@@ -2,6 +2,7 @@ package models
import (
"errors"
"fmt"
"github.com/grandcat/zeroconf"
"net"
)
@@ -12,37 +13,30 @@ type Online struct {
AddrIPv6 []net.IP `json:"-"`
Port int `json:"port"`
ID string `json:"id"`
Name string `json:"name"` // 昵称
Avatar string `json:"avatar"` // 头像
Email string `json:"email"`
Phone string `json:"phone"`
Address string `json:"address"` // 工位
Ip string `json:"ip"`
}
func (o *Online) Url(router string) string {
return fmt.Sprintf("http://%s:%d%s", o.Ip, o.Port, router)
}
func UserTOnlineList(user *Users) []string {
return []string{
user.ID,
user.Name,
user.Avatar,
user.Email,
user.Phone,
user.Address,
user.Ip,
}
}
func NewOnline(entry *zeroconf.ServiceEntry) (*Online, error) {
if len(entry.Text) != 6 {
if len(entry.Text) != 2 {
return nil, errors.New("invalid online entry")
}
return &Online{
AddrIPv4: entry.AddrIPv4,
AddrIPv6: entry.AddrIPv6,
Port: entry.Port,
ID: entry.Text[0],
Name: entry.Text[1],
Avatar: entry.Text[2],
Email: entry.Text[3],
Phone: entry.Text[4],
Address: entry.Text[5],
Ip: entry.Text[1],
}, nil
}
+13 -4
View File
@@ -7,11 +7,17 @@ import (
"work_cation/pkg/utils"
)
type userRepo struct{}
type userRepo struct {
isNew bool
users models.Users
}
var User *userRepo
var User = &userRepo{}
func (*userRepo) GetUserInfo(db *gorm.DB) *models.Users {
func (u *userRepo) GetUserInfo(db *gorm.DB) *models.Users {
if u.isNew {
return &u.users
}
var users models.Users
ip := utils.IP.Get192Ip()
db.Where("ip = ?", ip).Find(&users)
@@ -32,9 +38,12 @@ func (*userRepo) GetUserInfo(db *gorm.DB) *models.Users {
}
db.Create(&users)
}
u.isNew = true
u.users = users
return &users
}
func (*userRepo) Update(db *gorm.DB, newUser *models.Users) error {
func (u *userRepo) Update(db *gorm.DB, newUser *models.Users) error {
u.isNew = false
return db.Model(&models.Users{}).Where("ID = ?", newUser.ID).Updates(newUser).Error
}
+26
View File
@@ -0,0 +1,26 @@
package repo
import (
"gorm.io/gorm"
"work_cation/models"
)
type userFollowRepo struct{}
var UserFollow = &userFollowRepo{}
func (u *userFollowRepo) Follow(db *gorm.DB, user *models.UserFollows) error {
return db.Create(user).Error
}
func (u *userFollowRepo) GetUser(db *gorm.DB, uuid string) *models.UserFollows {
var user models.UserFollows
err := db.Model(&models.UserFollows{}).Where("id = ?", uuid).Find(&user).Error
if err != nil {
return nil
}
if user.ID == "" {
return nil
}
return &user
}
+31
View File
@@ -0,0 +1,31 @@
package service
import (
"encoding/json"
"io"
"net/http"
"work_cation/models"
)
type ClientService struct {
}
var Client = &ClientService{}
func (c *ClientService) GetUser(online *models.Online) (*models.Users, error) {
var user models.Users
resp, err := http.Get(online.Url("/user"))
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &user)
if err != nil {
return nil, err
}
return &user, nil
}
+3 -2
View File
@@ -53,8 +53,9 @@ func (s *serverService) StatusOffline() error {
func (s *serverService) StartListenServer() error {
router := gin.New()
router.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "hello"})
router.GET("/user", func(c *gin.Context) {
user := repo.User.GetUserInfo(global.DB)
c.JSON(200, user)
})
srv := &http.Server{
-1
View File
@@ -48,7 +48,6 @@ func (s *zeroconfService) FindService() (chan *models.Online, error) {
go func(results <-chan *zeroconf.ServiceEntry) {
for entry := range results {
if entry.ServiceInstanceName() == fmt.Sprintf("%s._http._tcp.local.", cfg.T.ZeroconfKey) {
//fmt.Printf("发现服务: %s \nIP:%s:%d \nInfo: %v\n", entry.ServiceInstanceName(), entry.AddrIPv4, entry.Port, entry.Text)
online, err := models.NewOnline(entry)
if err != nil {
continue
+5 -4
View File
@@ -17,14 +17,15 @@ type Tutorial struct {
var (
// Tutorials 定义每个教程的元数据
Tutorials = map[string]Tutorial{
"welcome": {"主页", "", mainUserViews, true},
"canvas": {"我的", "", allCardsViews, true},
"create": {"新建", "", allCreateCards, true},
"welcome": {"主页", "", mainUserViews, true},
"canvas": {"我的", "", allCardsViews, true},
"create": {"新建", "", allCreateCards, true},
"otherUsers": {"同事", "", otherUser, true},
}
// TutorialIndex 定义我们的教程应该如何在索引树中布局
TutorialIndex = map[string][]string{
"": {"welcome", "canvas", "create"},
"": {"welcome", "canvas", "otherUsers", "create"},
//"collections": {"list", "table", "tree"},
//"containers": {"apptabs", "border", "box", "center", "doctabs", "grid", "scroll", "split"},
//"widgets": {"accordion", "button", "card", "entry", "form", "input", "progress", "text", "toolbar"}, 58 * 3 + 106 = 280
+77
View File
@@ -0,0 +1,77 @@
package views
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"work_cation/global"
"work_cation/models"
"work_cation/repo"
"work_cation/service"
)
func otherUser(w fyne.Window) fyne.CanvasObject {
gridWrap := container.NewGridWrap(fyne.NewSize(200, 190))
findService, err := service.Zeroconf.FindService()
if err != nil {
return widget.NewLabel("网络异常请稍后尝试")
}
go func() {
for online := range findService {
var (
onlineCopy = online
)
baseCardV, err := itemOnlineUserView(w, onlineCopy)
if err != nil {
continue
}
gridWrap.Add(baseCardV)
}
}()
scroll := container.NewScroll(gridWrap)
return container.NewBorder(nil, nil, nil, nil, scroll)
}
func itemOnlineUserView(w fyne.Window, data *models.Online) (fyne.CanvasObject, error) {
u := repo.UserFollow.GetUser(global.DB, data.ID)
var followLabel *widget.Label
const (
noFollow = "未关注"
isFollow = "已关注"
)
if u == nil {
followLabel = widget.NewLabel(noFollow)
} else {
followLabel = widget.NewLabel(isFollow)
}
user, err := service.Client.GetUser(data)
if err != nil {
return nil, err
}
followButton := widget.NewButton("关注", func() {
if followLabel.Text == isFollow {
dialog.ShowInformation("结果", "已关注成功", w)
return
}
err = repo.UserFollow.Follow(global.DB, &models.UserFollows{Users: *user})
if err != nil {
dialog.ShowInformation("关注失败", err.Error(), w)
return
}
dialog.ShowInformation("结果", "关注成功", w)
followLabel.SetText(isFollow)
})
showErrButton := widget.NewButton("查看主页", func() {
dialog.ShowInformation("错误", "", w)
})
card := widget.NewCard(user.Name, user.Ip, container.NewVBox(followLabel, showErrButton, followButton))
return card, nil
}
+28 -4
View File
@@ -18,9 +18,10 @@ import (
"work_cation/models"
"work_cation/pkg/utils"
"work_cation/repo"
"work_cation/service"
)
func mainUserViews(_ fyne.Window) fyne.CanvasObject {
func mainUserViews(w fyne.Window) fyne.CanvasObject {
var userCard = widget.NewCard("", "", nil)
user1 := repo.User.GetUserInfo(global.DB)
refresh := func(user *models.Users) {
@@ -35,11 +36,34 @@ func mainUserViews(_ fyne.Window) fyne.CanvasObject {
}
image.FillMode = canvas.ImageFillContain
userCard.SetImage(image)
var status = ""
if service.Server.Status == service.StatusOnline {
status = "在线"
} else {
status = "离线"
}
userCard.SetContent(widget.NewLabel(fmt.Sprintf("状态:%s", status)))
}
refresh(user1)
return container.NewBorder(widget.NewToolbar(widget.NewToolbarAction(theme.SettingsIcon(), func() {
mainUserSetWin(refresh)
})),
return container.NewBorder(widget.NewToolbar(
widget.NewToolbarAction(theme.SettingsIcon(), func() { mainUserSetWin(refresh) }),
widget.NewToolbarAction(theme.LoginIcon(), func() {
err := service.Server.Online()
if err != nil {
dialog.ShowInformation("登录失败", err.Error(), w)
return
}
refresh(user1)
}),
widget.NewToolbarAction(theme.LogoutIcon(), func() {
err := service.Server.StatusOffline()
if err != nil {
dialog.ShowInformation("离线失败", err.Error(), w)
return
}
refresh(user1)
}),
),
nil,
nil,
nil,