Files
bj_power/bj_power_mes/bj_power_mes.go
T

238 lines
6.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//go:build windows
package main
import (
"embed"
"errors"
"flag"
"fmt"
"io/fs"
"log/slog"
"net/http"
"os"
"os/exec"
"os/signal"
"path/filepath"
"syscall"
"time"
"bj_power_mes/internal/handler"
"bj_power_mes/internal/middleware"
xhttp "bj_power_mes/common/httpx"
xlog "bj_power_mes/common/logx"
"bj_power_mes/internal/config"
"bj_power_mes/internal/svc"
"github.com/dromara/carbon/v2"
"github.com/getlantern/systray"
"github.com/pkg/browser"
"github.com/zeromicro/go-zero/core/conf"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest"
"github.com/zeromicro/go-zero/rest/httpx"
"golang.org/x/sys/windows"
)
const AppName = "bj_power_mes"
var configFile = flag.String("f", "etc/bj_power_mes-api.yaml", "the config file")
var AppPath, _ = filepath.Abs(os.Args[0])
var baseUrl string
//go:embed public
var public embed.FS
//go:embed app.ico
var icon []byte
func main() {
flag.Parse()
// 业务影å“:所有时间显示使用北京时é—? carbon.SetDefault(carbon.Default{
Layout: carbon.DateTimeLayout,
Timezone: carbon.PRC,
Locale: "zh-CN",
WeekStartsAt: carbon.Monday,
})
var c config.Config
conf.MustLoad(*configFile, &c)
baseUrl = fmt.Sprintf("http://127.0.0.1:%d", c.Port)
logger := xlog.NewLogger(c.Logger)
xlog.SetDefault(logger)
logx.SetWriter(logger)
// 业务影å“ï¼šé˜²æ­¢åŒæ—¶å¯åŠ¨å¤šä¸ªå®žä¾‹ï¼Œé¿å…端å£å†²çªå’?PLC 连接冲çª
mutex, err := createMutex(AppName)
if err != nil {
if errors.Is(err, ErrAlreadyExists) {
_ = browser.OpenURL(baseUrl)
return
}
MessageBox("错误", err.Error())
return
}
defer procCloseHandle.Call(mutex)
// 业务影å“:首次è¿è¡Œæ—¶è‡ªåŠ¨åˆ›å»ºæ¡Œé¢å’Œå¼€å§‹èœå•å¿«æ·æ–¹å¼? createShortcuts()
// 业务影å“:自动写入注册表开机å¯åŠ¨ï¼Œæ— éœ€ç”¨æˆ·æ‰‹åŠ¨å‹¾é€? if err := setAutoStart(AppName, AppPath); err != nil {
slog.Warn("开机å¯åŠ¨è®¾ç½®å¤±è´? " + err.Error())
}
// 业务影å“:åˆå§‹åŒ–æ•°æ®åº“连接ã€PLC 连接
svcCtx := svc.NewServiceContext(c)
spaHandler := xhttp.NewNotFoundHandler(http.FS(mustSub(public, "public")))
server := rest.MustNewServer(
c.RestConf,
rest.WithCors("*"),
rest.WithNotFoundHandler(spaHandler),
)
logx.DisableStat()
logx.SetWriter(logger)
defer server.Stop()
handler.RegisterHandlers(server, svcCtx)
// 写æ“作审计中间件(兜底覆盖系统管ç†ç±» CRUD 等所有写接å£ï¼? server.Use(middleware.WriteAudit(svcCtx))
// 业务影å“:统一错误å“应格å¼ï¼Œå‰ç«¯ä¸ç”¨å¤„ç†å¤šç§é”™è¯¯æ ¼å¼? httpx.SetValidator(xhttp.NewValidator())
httpx.SetOkHandler(xhttp.OkJsonCtx)
httpx.SetErrorHandlerCtx(xhttp.ErrorCtx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
slog.Info(fmt.Sprintf("Starting server at %s:%d...", c.Host, c.Port))
go server.Start()
// 等待æœåС噍å¯åŠ¨å®ŒæˆåŽå†æ‰“å¼€æµè§ˆå™¨ï¼Œé¿å… 404
go func() {
for i := 0; i < 50; i++ {
resp, err := http.Get(baseUrl)
if err == nil {
resp.Body.Close()
_ = browser.OpenURL(baseUrl)
return
}
time.Sleep(200 * time.Millisecond)
}
slog.Warn("server å¯åŠ¨è¶…æ—¶ï¼Œè·³è¿‡è‡ªåŠ¨æ‰“å¼€æµè§ˆå™?)
}()
// 业务影å“:Windows åŽå°è¿è¡Œï¼Œé€šè¿‡æ‰˜ç›˜å›¾æ ‡æŽ§åˆ¶é€€å‡?打开网页
systray.Run(onReady, func() {
slog.Info("onExit")
})
}
func mustSub(fsFS embed.FS, dir string) fs.FS {
sub, err := fs.Sub(fsFS, dir)
if err != nil {
panic(err)
}
return sub
}
// onReady ç³»ç»Ÿæ‰˜ç›˜ï¼šç”¨æˆ·å¯æ‰“开网页ã€åˆ‡æ¢å¼€æœºè‡ªå¯ï¼ˆéœ€ç®¡ç†å‘˜æƒé™ï¼‰ã€é€€å‡ºç¨‹åº?func onReady() {
systray.SetIcon(icon)
systray.SetTemplateIcon(icon, icon)
systray.SetTitle("åŒäº¬çµåŠç®¡æŽ§ç³»ç»Ÿ")
systray.SetTooltip("åŒäº¬çµåŠç®¡æŽ§ç³»ç»Ÿ")
mOpen := systray.AddMenuItem("打开管ç页é¢", "")
systray.AddSeparator()
mAutoStart := systray.AddMenuItem("开机å¯åŠ?, "")
mQuit := systray.AddMenuItem("退å‡?, "é€€åºæœåŠ?)
// 业务影å“ï¼šè¯»å–æ³¨å†Œè¡¨æ¢å¤ä¸Šæ¬¡çš„开机å¯åŠ¨è®¾ç½®çŠ¶æ€? if isAutoStartEnabled(AppName) {
mAutoStart.Check()
}
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
for {
select {
case s := <-signalChan:
slog.Info("receive signal: " + s.String())
systray.Quit()
return
case <-mQuit.ClickedCh:
systray.Quit()
return
case <-mOpen.ClickedCh:
err := browser.OpenURL(baseUrl)
if err != nil {
logx.Error(err.Error())
}
case <-mAutoStart.ClickedCh:
if mAutoStart.Checked() {
if err := removeAutoStart(AppName); err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
MessageBox("错误", "请用管ç†å‘˜æƒé™è¿è¡Œæ­¤ç¨‹åºã€?)
} else {
MessageBox("错误", err.Error())
}
slog.Error("设置失败�" + err.Error())
} else {
mAutoStart.Uncheck()
slog.Info("å·²ç»æˆåŠŸåæˆèªåЍè¿è¡Œã€?)
}
} else {
if err := setAutoStart(AppName, AppPath); err != nil {
if errors.Is(err, windows.ERROR_ACCESS_DENIED) {
MessageBox("错误", "请用管ç†å‘˜æƒé™è¿è¡Œæ­¤ç¨‹åºã€?)
} else {
MessageBox("错误", err.Error())
}
slog.Error("设置失败�" + err.Error())
} else {
mAutoStart.Check()
slog.Info("å·²ç»æˆåŠŸè®¾ç½®ä¸ºèªåЍè¿è¡Œã€?)
}
}
}
}
}()
}
// createShortcuts 首次è¿è¡Œæ—¶è‡ªåŠ¨åˆ›å»ºæ¡Œé¢å’Œå¼€å§‹èœå•å¿«æ·æ–¹å¼ã€?// å¦‚æžœå¿«æ·æ–¹å¼å·²å­˜åœ¨åˆ™è·³è¿‡ï¼Œåˆ›å»ºå¤±è´¥ä¸é˜»å¡žç¨‹åºå¯åЍã€?func createShortcuts() {
shortcutName := "北京电力管控系统"
exePath, err := os.Executable()
if err != nil {
return
}
exeDir := filepath.Dir(exePath)
iconPath := filepath.Join(exeDir, "app.ico")
// 桌é¢å¿«æ·æ–¹å¼
desktopDir, _ := os.UserHomeDir()
desktopPath := filepath.Join(desktopDir, "Desktop", shortcutName+".lnk")
makeShortcut(desktopPath, exePath, exeDir, iconPath)
// 开始èœå•å¿«æ·æ–¹å¼? startMenuPath := filepath.Join(os.Getenv("APPDATA"),
"Microsoft", "Windows", "Start Menu", "Programs", shortcutName+".lnk")
makeShortcut(startMenuPath, exePath, exeDir, iconPath)
}
// makeShortcut 通过 PowerShell 创建 .lnk å¿«æ·æ–¹å¼ã€?// 如果文件已存在则跳过,创建失败ä¸é˜»å¡žã€?func makeShortcut(shortcutPath, targetPath, workDir, iconPath string) {
if _, err := os.Stat(shortcutPath); err == nil {
return // 已存在,跳过
}
script := fmt.Sprintf(
`$s=(New-Object -ComObject WScript.Shell).CreateShortcut('%s');$s.TargetPath='%s';$s.WorkingDirectory='%s';$s.IconLocation='%s';$s.Save()`,
shortcutPath, targetPath, workDir, iconPath,
)
cmd := exec.Command("powershell", "-ExecutionPolicy", "Bypass", "-NoProfile", "-Command", script)
_ = cmd.Run() // 创建失败ä¸é˜»å¡žå¯åŠ?}