服务发现基础逻辑
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
package global
|
package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/text/encoding/simplifiedchinese"
|
||||||
|
"golang.org/x/text/transform"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"testing"
|
"testing"
|
||||||
"work_cation/pkg/gormx"
|
"work_cation/pkg/gormx"
|
||||||
@@ -154,3 +157,23 @@ func TestInitDB1(t *testing.T) {
|
|||||||
fmt.Println(ret)
|
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
@@ -2,6 +2,7 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/grandcat/zeroconf"
|
"github.com/grandcat/zeroconf"
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
@@ -12,37 +13,30 @@ type Online struct {
|
|||||||
AddrIPv6 []net.IP `json:"-"`
|
AddrIPv6 []net.IP `json:"-"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"` // 昵称
|
Ip string `json:"ip"`
|
||||||
Avatar string `json:"avatar"` // 头像
|
}
|
||||||
Email string `json:"email"`
|
|
||||||
Phone string `json:"phone"`
|
func (o *Online) Url(router string) string {
|
||||||
Address string `json:"address"` // 工位
|
return fmt.Sprintf("http://%s:%d%s", o.Ip, o.Port, router)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UserTOnlineList(user *Users) []string {
|
func UserTOnlineList(user *Users) []string {
|
||||||
return []string{
|
return []string{
|
||||||
user.ID,
|
user.ID,
|
||||||
user.Name,
|
user.Ip,
|
||||||
user.Avatar,
|
|
||||||
user.Email,
|
|
||||||
user.Phone,
|
|
||||||
user.Address,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOnline(entry *zeroconf.ServiceEntry) (*Online, error) {
|
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 nil, errors.New("invalid online entry")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Online{
|
return &Online{
|
||||||
AddrIPv4: entry.AddrIPv4,
|
AddrIPv4: entry.AddrIPv4,
|
||||||
AddrIPv6: entry.AddrIPv6,
|
AddrIPv6: entry.AddrIPv6,
|
||||||
Port: entry.Port,
|
Port: entry.Port,
|
||||||
ID: entry.Text[0],
|
ID: entry.Text[0],
|
||||||
Name: entry.Text[1],
|
Ip: entry.Text[1],
|
||||||
Avatar: entry.Text[2],
|
|
||||||
Email: entry.Text[3],
|
|
||||||
Phone: entry.Text[4],
|
|
||||||
Address: entry.Text[5],
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-4
@@ -7,11 +7,17 @@ import (
|
|||||||
"work_cation/pkg/utils"
|
"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
|
var users models.Users
|
||||||
ip := utils.IP.Get192Ip()
|
ip := utils.IP.Get192Ip()
|
||||||
db.Where("ip = ?", ip).Find(&users)
|
db.Where("ip = ?", ip).Find(&users)
|
||||||
@@ -32,9 +38,12 @@ func (*userRepo) GetUserInfo(db *gorm.DB) *models.Users {
|
|||||||
}
|
}
|
||||||
db.Create(&users)
|
db.Create(&users)
|
||||||
}
|
}
|
||||||
|
u.isNew = true
|
||||||
|
u.users = users
|
||||||
return &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
|
return db.Model(&models.Users{}).Where("ID = ?", newUser.ID).Updates(newUser).Error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
@@ -53,8 +53,9 @@ func (s *serverService) StatusOffline() error {
|
|||||||
|
|
||||||
func (s *serverService) StartListenServer() error {
|
func (s *serverService) StartListenServer() error {
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
router.GET("/", func(c *gin.Context) {
|
router.GET("/user", func(c *gin.Context) {
|
||||||
c.JSON(200, gin.H{"message": "hello"})
|
user := repo.User.GetUserInfo(global.DB)
|
||||||
|
c.JSON(200, user)
|
||||||
})
|
})
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ func (s *zeroconfService) FindService() (chan *models.Online, error) {
|
|||||||
go func(results <-chan *zeroconf.ServiceEntry) {
|
go func(results <-chan *zeroconf.ServiceEntry) {
|
||||||
for entry := range results {
|
for entry := range results {
|
||||||
if entry.ServiceInstanceName() == fmt.Sprintf("%s._http._tcp.local.", cfg.T.ZeroconfKey) {
|
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)
|
online, err := models.NewOnline(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
|
|||||||
+5
-4
@@ -17,14 +17,15 @@ type Tutorial struct {
|
|||||||
var (
|
var (
|
||||||
// Tutorials 定义每个教程的元数据
|
// Tutorials 定义每个教程的元数据
|
||||||
Tutorials = map[string]Tutorial{
|
Tutorials = map[string]Tutorial{
|
||||||
"welcome": {"主页", "", mainUserViews, true},
|
"welcome": {"主页", "", mainUserViews, true},
|
||||||
"canvas": {"我的", "", allCardsViews, true},
|
"canvas": {"我的", "", allCardsViews, true},
|
||||||
"create": {"新建", "", allCreateCards, true},
|
"create": {"新建", "", allCreateCards, true},
|
||||||
|
"otherUsers": {"同事", "", otherUser, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TutorialIndex 定义我们的教程应该如何在索引树中布局
|
// TutorialIndex 定义我们的教程应该如何在索引树中布局
|
||||||
TutorialIndex = map[string][]string{
|
TutorialIndex = map[string][]string{
|
||||||
"": {"welcome", "canvas", "create"},
|
"": {"welcome", "canvas", "otherUsers", "create"},
|
||||||
//"collections": {"list", "table", "tree"},
|
//"collections": {"list", "table", "tree"},
|
||||||
//"containers": {"apptabs", "border", "box", "center", "doctabs", "grid", "scroll", "split"},
|
//"containers": {"apptabs", "border", "box", "center", "doctabs", "grid", "scroll", "split"},
|
||||||
//"widgets": {"accordion", "button", "card", "entry", "form", "input", "progress", "text", "toolbar"}, 58 * 3 + 106 = 280
|
//"widgets": {"accordion", "button", "card", "entry", "form", "input", "progress", "text", "toolbar"}, 58 * 3 + 106 = 280
|
||||||
|
|||||||
@@ -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
@@ -18,9 +18,10 @@ import (
|
|||||||
"work_cation/models"
|
"work_cation/models"
|
||||||
"work_cation/pkg/utils"
|
"work_cation/pkg/utils"
|
||||||
"work_cation/repo"
|
"work_cation/repo"
|
||||||
|
"work_cation/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func mainUserViews(_ fyne.Window) fyne.CanvasObject {
|
func mainUserViews(w fyne.Window) fyne.CanvasObject {
|
||||||
var userCard = widget.NewCard("", "", nil)
|
var userCard = widget.NewCard("", "", nil)
|
||||||
user1 := repo.User.GetUserInfo(global.DB)
|
user1 := repo.User.GetUserInfo(global.DB)
|
||||||
refresh := func(user *models.Users) {
|
refresh := func(user *models.Users) {
|
||||||
@@ -35,11 +36,34 @@ func mainUserViews(_ fyne.Window) fyne.CanvasObject {
|
|||||||
}
|
}
|
||||||
image.FillMode = canvas.ImageFillContain
|
image.FillMode = canvas.ImageFillContain
|
||||||
userCard.SetImage(image)
|
userCard.SetImage(image)
|
||||||
|
var status = ""
|
||||||
|
if service.Server.Status == service.StatusOnline {
|
||||||
|
status = "在线"
|
||||||
|
} else {
|
||||||
|
status = "离线"
|
||||||
|
}
|
||||||
|
userCard.SetContent(widget.NewLabel(fmt.Sprintf("状态:%s", status)))
|
||||||
}
|
}
|
||||||
refresh(user1)
|
refresh(user1)
|
||||||
return container.NewBorder(widget.NewToolbar(widget.NewToolbarAction(theme.SettingsIcon(), func() {
|
return container.NewBorder(widget.NewToolbar(
|
||||||
mainUserSetWin(refresh)
|
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,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
|
|||||||
Reference in New Issue
Block a user