下载相机图片功能
This commit is contained in:
1 parent
ff9315ba63
commit
083857d130
13 files changed
+929
-25
No files matched your search
@@ -9,3 +9,5 @@ piVideo
|
||||
initFunc/piserver_root.crt
|
||||
frontend/src/assets
|
||||
build/darwin/Info.dev.plist
|
||||
downloads
|
||||
take_photos
|
||||
@@ -0,0 +1,47 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"changeme/cameraFunc"
|
||||
"changeme/util/response"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
func DownLoadCameraJpg(r *ghttp.Request) {
|
||||
deviceId := r.Get("device_id").String()
|
||||
fileType := r.Get("file_type").String()
|
||||
id := r.Get("id").String()
|
||||
if deviceId == "" || id == "" {
|
||||
response.FailJson(true, r,"参数错误")
|
||||
return
|
||||
}
|
||||
if fileType == "" {
|
||||
err1 := cameraFunc.DownLoadCameraJpgByFtp(id,deviceId,"1")
|
||||
err2 := cameraFunc.DownLoadCameraJpgByFtp(id,deviceId,"2")
|
||||
|
||||
if err1 != nil && err2 != nil {
|
||||
response.FailJson(true, r,"下载失败",[]string{err1.Error(),err2.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err1 != nil && err2 == nil {
|
||||
response.FailJson(true, r,"预览图下载失败,高清图下载成功",[]string{err1.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err1 == nil && err2 != nil {
|
||||
response.FailJson(true, r,"预览图下载成功,高清图下载失败",[]string{err2.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
response.SusJson(true, r, "下载成功")
|
||||
|
||||
}else{
|
||||
err := cameraFunc.DownLoadCameraJpgByFtp(id,deviceId,fileType)
|
||||
if err != nil {
|
||||
response.FailJson(true, r,"下载失败",[]string{err.Error()})
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "下载成功")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"changeme/masterFunc"
|
||||
"changeme/util/response"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
func DownLoadMasterJpg(r *ghttp.Request) {
|
||||
id := r.Get("id").Int()
|
||||
if id == 0 {
|
||||
response.FailJson(true, r, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
err := masterFunc.DownLoadMasterJpgBySftp(id)
|
||||
if err != nil {
|
||||
response.FailJson(true, r, "下载失败", []string{err.Error()})
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "下载成功")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"changeme/db"
|
||||
"changeme/model"
|
||||
"changeme/util/response"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
)
|
||||
|
||||
func AddDbData(r *ghttp.Request) {
|
||||
var req *model.AddData
|
||||
//获取参数&参数校验
|
||||
if err := r.Parse(&req); err != nil {
|
||||
//fmt.Fprintf(w,gconv.String(g.Map{"code":"-1","msg":err.Error()}))
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
DBFunc := db.GetInstance()
|
||||
err := DBFunc.Add(req)
|
||||
if err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "查询成功")
|
||||
}
|
||||
|
||||
func Page(r *ghttp.Request) {
|
||||
var req *model.PageReqData
|
||||
//获取参数&参数校验
|
||||
if err := r.Parse(&req); err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
DBFunc := db.GetInstance()
|
||||
list,err := DBFunc.List(req)
|
||||
if err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "查询成功",list)
|
||||
}
|
||||
|
||||
func UpdateDbData(r *ghttp.Request) {
|
||||
var req *model.Data
|
||||
//获取参数&参数校验
|
||||
if err := r.Parse(&req); err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
DBFunc := db.GetInstance()
|
||||
err := DBFunc.Update(req)
|
||||
if err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "更新成功")
|
||||
}
|
||||
|
||||
|
||||
|
||||
func DeleteDbData(r *ghttp.Request) {
|
||||
var req *model.DeleteReqData
|
||||
//获取参数&参数校验
|
||||
if err := r.Parse(&req); err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
DBFunc := db.GetInstance()
|
||||
err := DBFunc.Delete(req)
|
||||
if err != nil {
|
||||
response.FailJson(true, r, err.Error())
|
||||
return
|
||||
}
|
||||
response.SusJson(true, r, "操作成功")
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package cameraFunc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/jlaffaye/ftp"
|
||||
)
|
||||
|
||||
//连接到相机 FTP 服务器,下载文件
|
||||
func DownLoadCameraJpgByFtp(id,deviceId string,fileType string) error {
|
||||
ip := "192.168.88."+deviceId+":21"
|
||||
// 连接到 FTP 服务器
|
||||
c, err := ftp.Dial(ip) // 替换为你的 FTP 服务器地址
|
||||
if err != nil {
|
||||
g.Dump("ftp.Dial(ip) error:",err)
|
||||
return err
|
||||
}
|
||||
defer c.Quit()
|
||||
// 登录到 FTP 服务器
|
||||
err = c.Login("icatch", "icatch") // 替换为你的用户名和密码
|
||||
if err != nil {
|
||||
g.Dump("c.Login error:",err)
|
||||
return err
|
||||
}
|
||||
//现在本地创建文件夹和文件
|
||||
fileName := id+"_"+deviceId+"_"+fileType+".jpg"
|
||||
file,err := IsExistDirAndFileForCreate(id,fileName)
|
||||
if err != nil {
|
||||
defer file.Close()
|
||||
g.Dump("IsExistDirAndFileForCreate error:",err)
|
||||
return err
|
||||
}
|
||||
// 从 FTP 服务器获取文件
|
||||
r,err := c.Retr("jpg/"+fileName) // 远程文件名
|
||||
if err != nil {
|
||||
g.Dump("c.Retr error:",err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
defer r.Close()
|
||||
_, err = io.Copy(file, r)
|
||||
if err != nil {
|
||||
g.Dump("io.Copy error:",err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
//判断当前根目录是否存在指定的文件夹和文件夹下的文件,没有则创建
|
||||
func IsExistDirAndFileForCreate(id string,fileName string) (file *os.File,err error) {
|
||||
// 指定的目录和文件名
|
||||
dirPath := "downloads_new/"+id // 目标文件夹
|
||||
//fileName := "myfile.txt" // 目标文件
|
||||
// 检查目录是否存在
|
||||
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
|
||||
// 目录不存在,创建目录
|
||||
err := os.MkdirAll(dirPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
}
|
||||
// 检查文件是否存在
|
||||
filePath := filepath.Join(dirPath, fileName)
|
||||
// 文件不存在,创建文件
|
||||
file, err = os.Create(filePath)
|
||||
if err != nil {
|
||||
return nil,err
|
||||
}
|
||||
// 关闭文件
|
||||
return file,nil
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"changeme/model"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
// DB 结构体
|
||||
type DB struct {
|
||||
*sql.DB
|
||||
}
|
||||
|
||||
var (
|
||||
instance *DB
|
||||
once sync.Once
|
||||
)
|
||||
var TableName = "photo_studio_shoot_order"
|
||||
// GetInstance 返回数据库单例实例
|
||||
func GetInstance() *DB {
|
||||
once.Do(func() {
|
||||
db, err := sql.Open("sqlite3", "test.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
instance = &DB{db}
|
||||
//检测表是否存在
|
||||
checkTableSQL := `SELECT count(*) FROM sqlite_master WHERE type='table' AND name='`+TableName+`';`
|
||||
var count int
|
||||
if err := instance.QueryRow(checkTableSQL).Scan(&count); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if count > 0 {
|
||||
return
|
||||
}
|
||||
// 创建表
|
||||
createTableSQL := `CREATE TABLE "`+TableName+`" (
|
||||
"id" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"customer_id" INTEGER NOT NULL,
|
||||
"customer_name" TEXT NOT NULL,
|
||||
"status" INTEGER NOT NULL,
|
||||
"order_id" INTEGER NOT NULL,
|
||||
"digital_order_id" INTEGER NOT NULL,
|
||||
"digital_type" INTEGER NOT NULL,
|
||||
"cover_path" TEXT NOT NULL,
|
||||
"cover_rotate_deg" INTEGER NOT NULL,
|
||||
"shoot_at_count" INTEGER NOT NULL,
|
||||
"shoot_done_count" INTEGER NOT NULL,
|
||||
"upload_cover_count" INTEGER NOT NULL,
|
||||
"upload_highmode_count" INTEGER NOT NULL,
|
||||
"upload_yuv_count" INTEGER NOT NULL,
|
||||
"first_shoot_at" DATETIME NULL,
|
||||
"first_shoot_done_at" DATETIME NULL,
|
||||
"last_shoot_at" DATETIME NULL,
|
||||
"last_shoot_done_at" DATETIME NULL,
|
||||
"check_status" INTEGER NOT NULL,
|
||||
"check_fail_reason" TEXT NOT NULL,
|
||||
"check_at" DATETIME NULL,
|
||||
"shop_id" INTEGER NOT NULL,
|
||||
"eq_id" INTEGER NOT NULL,
|
||||
"master_ver" TEXT NOT NULL,
|
||||
"eq_type" INTEGER NOT NULL,
|
||||
"created_at" DATETIME NULL,
|
||||
"upload_done_at" DATETIME NULL,
|
||||
"minipreview_upload_done_at" DATETIME NULL,
|
||||
"updated_at" DATETIME NULL,
|
||||
"is_privary" INTEGER NOT NULL,
|
||||
"cancel_at" DATETIME NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);`
|
||||
if _, err = instance.Exec(createTableSQL); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
return instance
|
||||
}
|
||||
|
||||
|
||||
//Add 新增数据
|
||||
func (db *DB) Add(addData *model.AddData) error {
|
||||
v := reflect.ValueOf(addData)
|
||||
// 确保传入的参数是指向结构体的指针
|
||||
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
|
||||
return errors.New("invalid input")
|
||||
}
|
||||
// 获取结构体的类型和字段
|
||||
t := v.Elem().Type()
|
||||
fields := []string{}
|
||||
placeholders := []string{}
|
||||
values := []interface{}{}
|
||||
|
||||
for i := 0; i < v.Elem().NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
value := v.Elem().Field(i)
|
||||
// 使用 db 标签作为字段名
|
||||
dbTag := field.Tag.Get("json")
|
||||
fields = append(fields, dbTag)
|
||||
placeholders = append(placeholders, "?")
|
||||
values = append(values, value.Interface())
|
||||
}
|
||||
// 生成 SQL 语句
|
||||
sqlStatement := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)",
|
||||
TableName,
|
||||
strings.Join(fields, ", "),
|
||||
strings.Join(placeholders, ", "))
|
||||
// 执行 SQL 语句
|
||||
_, err := db.Exec(sqlStatement, values...)
|
||||
return err
|
||||
}
|
||||
|
||||
//根据查询列表数据
|
||||
// List 方法
|
||||
func (db *DB) List(req *model.PageReqData) (list []*model.Data, err error) {
|
||||
// 基本的 SQL 查询语句
|
||||
query := "SELECT cover_path,pid,customer_name FROM "+TableName+" WHERE 1=1"
|
||||
var args []interface{}
|
||||
|
||||
// 根据请求参数动态构建查询条件
|
||||
if req.Pid > 0 {
|
||||
query += " AND pid = ?"
|
||||
args = append(args, req.Pid)
|
||||
}
|
||||
if req.CustomerId > 0 {
|
||||
query += " AND customer_id = ?"
|
||||
args = append(args, req.CustomerId)
|
||||
}
|
||||
if req.CustomerName != "" {
|
||||
query += " AND customer_name LIKE ?"
|
||||
args = append(args, "%"+req.CustomerName+"%")
|
||||
}
|
||||
if req.Status > 0 {
|
||||
query += " AND status = ?"
|
||||
args = append(args, req.Status)
|
||||
}
|
||||
|
||||
// 添加分页条件
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.Size <= 0 {
|
||||
req.Size = 20
|
||||
}
|
||||
offset := (req.Page - 1) * req.Size
|
||||
query += fmt.Sprintf(" LIMIT %d OFFSET %d", req.Size, offset)
|
||||
// 执行查询
|
||||
rows, err := db.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
// 读取查询结果
|
||||
for rows.Next() {
|
||||
var addData model.Data
|
||||
if err := rows.Scan(&addData.CoverPath, &addData.Pid, &addData.CustomerName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list = append(list, &addData)
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (db *DB) Delete(req *model.DeleteReqData) (err error) {
|
||||
if req.Pid == 0 && req.Id == 0 {
|
||||
return errors.New("参数不能为空")
|
||||
}
|
||||
query := "DELETE FROM "+TableName+" WHERE 1=1"
|
||||
var args []interface{}
|
||||
if req.Pid > 0 {
|
||||
query += " AND pid = ?"
|
||||
args = append(args, req.Pid)
|
||||
}
|
||||
if req.Id > 0 {
|
||||
query += " AND id = ?"
|
||||
args = append(args, req.Id)
|
||||
}
|
||||
_, err = db.Exec(query, args...)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) Update(addData *model.Data) error {
|
||||
v := reflect.ValueOf(addData)
|
||||
// 确保传入的参数是指向结构体的指针
|
||||
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
|
||||
return errors.New("invalid input")
|
||||
}
|
||||
|
||||
// 获取结构体的类型和字段
|
||||
t := v.Elem().Type()
|
||||
fields := []string{}
|
||||
values := []interface{}{}
|
||||
|
||||
for i := 0; i < v.Elem().NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
value := v.Elem().Field(i)
|
||||
// 使用 db 标签作为字段名
|
||||
dbTag := field.Tag.Get("json")
|
||||
if gconv.String(value.Interface()) != "" && gconv.String(value.Interface()) != "0" && dbTag != "id" {
|
||||
fields = append(fields, fmt.Sprintf("%s = ?", dbTag))
|
||||
values = append(values, value.Interface())
|
||||
}
|
||||
}
|
||||
// 生成 Update SQL 语句
|
||||
sqlStatement := fmt.Sprintf("UPDATE %s SET %s WHERE id = %s",
|
||||
TableName,
|
||||
strings.Join(fields, ", "),
|
||||
gconv.String(addData.Id),
|
||||
)
|
||||
// 执行 SQL 语句
|
||||
_, err := db.Exec(sqlStatement, values...)
|
||||
return err
|
||||
}
|
||||
@@ -6,7 +6,11 @@ toolchain go1.21.6
|
||||
|
||||
require (
|
||||
github.com/gogf/gf/v2 v2.6.2
|
||||
github.com/wailsapp/wails/v2 v2.8.0
|
||||
github.com/jlaffaye/ftp v0.2.0
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/pkg/sftp v1.13.7
|
||||
github.com/wailsapp/wails/v2 v2.7.1
|
||||
golang.org/x/crypto v0.29.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -22,7 +26,10 @@ require (
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/labstack/echo/v4 v4.10.2 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/leaanthony/go-ansi-parser v1.6.0 // indirect
|
||||
@@ -41,16 +48,15 @@ require (
|
||||
github.com/tkrajina/go-reflector v0.5.6 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.10 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.16 // indirect
|
||||
github.com/wailsapp/mimetype v1.4.1 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
|
||||
@@ -30,8 +30,16 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck=
|
||||
github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
|
||||
github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg=
|
||||
github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
@@ -61,12 +69,16 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM=
|
||||
github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -75,9 +87,12 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
|
||||
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
|
||||
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
|
||||
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
@@ -85,42 +100,79 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w=
|
||||
github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
|
||||
github.com/wailsapp/go-webview2 v1.0.16 h1:wffnvnkkLvhRex/aOrA3R7FP7rkvOqL/bir1br7BekU=
|
||||
github.com/wailsapp/go-webview2 v1.0.16/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
|
||||
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
|
||||
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
|
||||
github.com/wailsapp/wails/v2 v2.8.0 h1:b2NNn99uGPiN6P5bDsnPwOJZWtAOUhNLv7Vl+YxMTr4=
|
||||
github.com/wailsapp/wails/v2 v2.8.0/go.mod h1:EFUGWkUX3KofO4fmKR/GmsLy3HhPH7NbyOEaMt8lBF0=
|
||||
github.com/wailsapp/wails/v2 v2.7.1 h1:HAzp2c5ODOzsLC6ZMDVtNOB72ozM7/SJecJPB2Ur+UU=
|
||||
github.com/wailsapp/wails/v2 v2.7.1/go.mod h1:oIJVwwso5fdOgprBYWXBBqtx6PaSvxg8/KTQHNGkadc=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"changeme/api"
|
||||
"changeme/initFunc"
|
||||
"context"
|
||||
"embed"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu"
|
||||
"github.com/wailsapp/wails/v2/pkg/menu/keys"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
@@ -37,6 +41,7 @@ func main() {
|
||||
//开启视频监控的exe
|
||||
go initFunc.RunPiServerExe()
|
||||
go initFunc.SetupCert()
|
||||
go HttpServer()
|
||||
wilsJon,_ := wailsjson.ReadFile("wails.json")
|
||||
wailsConfig = gconv.Map(wilsJon)
|
||||
//读取wails.json配置文件
|
||||
@@ -51,10 +56,10 @@ func main() {
|
||||
|
||||
//增加菜单
|
||||
AppMenu := menu.NewMenu()
|
||||
SubMenu := AppMenu.AddSubmenu("工具")
|
||||
SubMenu.AddText("刷新", keys.CmdOrCtrl("F5"), func(_ *menu.CallbackData) {
|
||||
runtime.Reload(app.ctx)
|
||||
})
|
||||
// SubMenu := AppMenu.AddSubmenu("工具")
|
||||
// SubMenu.AddText("刷新", keys.CmdOrCtrl("F5"), func(_ *menu.CallbackData) {
|
||||
// runtime.Reload(app.ctx)
|
||||
// })
|
||||
|
||||
|
||||
// Create application with options
|
||||
@@ -104,3 +109,62 @@ func (a *App) ShopUrl() string {
|
||||
}
|
||||
return domain+"?oem_id="+gconv.String(wailsConfigOem["id"])+"&t="+gconv.String(gtime.TimestampMilli())
|
||||
}
|
||||
|
||||
func releasePort(port int) error {
|
||||
var cmd *exec.Cmd
|
||||
|
||||
// 根据操作系统选择不同的命令
|
||||
if runtime.GOOS == "windows" {
|
||||
// Windows: 使用 netstat 查找占用端口的 PID
|
||||
// netstat -ano | findstr :<port> 获取对应的 PID,然后使用 taskkill 杀死进程
|
||||
cmd = exec.Command("cmd", "/C", fmt.Sprintf("netstat -ano | findstr :%d", port))
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error running netstat: %v", err)
|
||||
}
|
||||
|
||||
// 在 Windows 上,输出格式是:TCP [::]:<port> [::]:0 LISTENING <PID>
|
||||
// 需要提取出 PID
|
||||
lines := string(output)
|
||||
for _, line := range strings.Split(lines, "\n") {
|
||||
if strings.Contains(line, fmt.Sprintf(":%d", port)) {
|
||||
// 提取 PID(PID 是最后一个字段)
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 5 {
|
||||
pid := fields[len(fields)-1]
|
||||
// 使用 taskkill 结束进程
|
||||
cmdKill := exec.Command("taskkill", "/PID", pid, "/F")
|
||||
err := cmdKill.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to kill process with PID %s: %v", pid, err)
|
||||
}
|
||||
fmt.Printf("Killed process with PID %s on port %d\n", pid, port)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("no process found listening on port %d", port)
|
||||
|
||||
} else {
|
||||
// Linux/MacOS: 使用 lsof 和 kill 杀死占用端口的进程
|
||||
exec.Command("bash", "-c", "lsof -i :${port} | grep LISTEN | awk '{print 8383}' | xargs kill -9")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func HttpServer(){
|
||||
|
||||
releasePort(8383)
|
||||
s := ghttp.GetServer()
|
||||
// 处理 /take_photo_page 路由
|
||||
s.BindHandler("/take_photo_page",api.Page)
|
||||
s.BindHandler("/add_take_photo",api.AddDbData)
|
||||
s.BindHandler("/update_take_photo",api.UpdateDbData)
|
||||
s.BindHandler("/delete_take_photo",api.DeleteDbData)
|
||||
s.BindHandler("/download_camera_jpg",api.DownLoadCameraJpg)
|
||||
s.BindHandler("/download_master_jpg",api.DownLoadMasterJpg)
|
||||
|
||||
s.SetPort(8383)
|
||||
s.Run()
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package masterFunc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// DownLoadCameraJpgBySftp 使用 SFTP 连接下载远程文件
|
||||
func DownLoadMasterJpgBySftp(id int) error {
|
||||
ip := "192.168.88.2:22" // SFTP 服务器地址 (通常是 SSH 协议端口)
|
||||
username := "pi"
|
||||
password := "picc2008"
|
||||
|
||||
// 配置 SSH 客户端
|
||||
sshConfig := &ssh.ClientConfig{
|
||||
User: username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(password),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥验证(不建议用于生产环境)
|
||||
}
|
||||
|
||||
// 连接到 SSH 服务器
|
||||
client, err := ssh.Dial("tcp", ip, sshConfig)
|
||||
if err != nil {
|
||||
fmt.Println("ssh.Dial error:", err)
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 创建 SFTP 客户端
|
||||
sftpClient, err := sftp.NewClient(client)
|
||||
if err != nil {
|
||||
fmt.Println("sftp.NewClient error:", err)
|
||||
return err
|
||||
}
|
||||
defer sftpClient.Close()
|
||||
|
||||
fmt.Println("id:", id)
|
||||
|
||||
// 设定远程目录路径
|
||||
remotePath := "/home/pi/photos/" + fmt.Sprint(id)
|
||||
// 本地目录路径
|
||||
localPathPhoto1 := "./downloads/" + fmt.Sprint(id) + "/photo1"
|
||||
localPathPhoto2 := "./downloads/" + fmt.Sprint(id) + "/photo2"
|
||||
|
||||
// 创建本地目录
|
||||
err = os.MkdirAll(localPathPhoto1, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Println("os.MkdirAll error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.MkdirAll(localPathPhoto2, os.ModePerm)
|
||||
if err != nil {
|
||||
fmt.Println("os.MkdirAll error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 获取远程目录中的文件和子目录
|
||||
entries, err := sftpClient.ReadDir(remotePath)
|
||||
if err != nil {
|
||||
fmt.Println("sftpClient.ReadDir error:", err)
|
||||
return err
|
||||
}
|
||||
g.Dump("entries", entries, remotePath)
|
||||
|
||||
// 遍历远程目录中的所有文件
|
||||
for _, entry := range entries {
|
||||
localFilePath := ""
|
||||
|
||||
// 判断文件名称是否包含 _1.jpg
|
||||
if strings.Contains(entry.Name(), "_1.jpg") {
|
||||
// 生成本地文件路径
|
||||
localFilePath = filepath.Join(localPathPhoto1, entry.Name())
|
||||
}
|
||||
|
||||
// 判断文件名称是否包含 _8.jpg
|
||||
if strings.Contains(entry.Name(), "_8.jpg") {
|
||||
localFilePath = filepath.Join(localPathPhoto2, entry.Name())
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
err := DownloadFile(sftpClient, remotePath+"/"+entry.Name(), localFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DownloadFile 下载单个文件
|
||||
func DownloadFile(client *sftp.Client, remoteFile, localFile string) error {
|
||||
// 创建本地文件
|
||||
file, err := os.Create(localFile)
|
||||
if err != nil {
|
||||
fmt.Println("os.Create error:", err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 打开远程文件
|
||||
remoteFileHandle, err := client.Open(remoteFile)
|
||||
if err != nil {
|
||||
fmt.Println("client.Open error:", err)
|
||||
return err
|
||||
}
|
||||
defer remoteFileHandle.Close()
|
||||
|
||||
// 将文件内容从远程文件复制到本地文件
|
||||
_, err = io.Copy(file, remoteFileHandle)
|
||||
if err != nil {
|
||||
fmt.Println("io.Copy error:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Downloaded file:", localFile)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
package model
|
||||
|
||||
// CREATE TABLE "photo_studio_shoot_order" (
|
||||
// "id" INTEGER NOT NULL,
|
||||
// "pid" INTEGER NOT NULL,
|
||||
// "customer_id" INTEGER NOT NULL,
|
||||
// "customer_name" TEXT NOT NULL,
|
||||
// "status" INTEGER NOT NULL,
|
||||
// "order_id" INTEGER NOT NULL,
|
||||
// "digital_order_id" INTEGER NOT NULL,
|
||||
// "digital_type" INTEGER NOT NULL,
|
||||
// "cover_path" TEXT NOT NULL,
|
||||
// "cover_rotate_deg" INTEGER NOT NULL,
|
||||
// "shoot_at_count" INTEGER NOT NULL,
|
||||
// "shoot_done_count" INTEGER NOT NULL,
|
||||
// "upload_cover_count" INTEGER NOT NULL,
|
||||
// "upload_highmode_count" INTEGER NOT NULL,
|
||||
// "upload_yuv_count" INTEGER NOT NULL,
|
||||
// "first_shoot_at" DATETIME NULL,
|
||||
// "first_shoot_done_at" DATETIME NULL,
|
||||
// "last_shoot_at" DATETIME NULL,
|
||||
// "last_shoot_done_at" DATETIME NULL,
|
||||
// "check_status" INTEGER NOT NULL,
|
||||
// "check_fail_reason" TEXT NOT NULL,
|
||||
// "check_at" DATETIME NULL,
|
||||
// "shop_id" INTEGER NOT NULL,
|
||||
// "eq_id" INTEGER NOT NULL,
|
||||
// "master_ver" TEXT NOT NULL,
|
||||
// "eq_type" INTEGER NOT NULL,
|
||||
// "created_at" DATETIME NULL,
|
||||
// "upload_done_at" DATETIME NULL,
|
||||
// "minipreview_upload_done_at" DATETIME NULL,
|
||||
// "updated_at" DATETIME NULL,
|
||||
// "is_privary" INTEGER NOT NULL,
|
||||
// "cancel_at" DATETIME NULL,
|
||||
// PRIMARY KEY ("id")
|
||||
// );
|
||||
|
||||
type AddData struct {
|
||||
Pid int `json:"pid"`
|
||||
CustomerId int `json:"customer_id"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
Status int `json:"status"`
|
||||
OrderId int `json:"order_id"`
|
||||
DigitalOrderId int `json:"digital_order_id"`
|
||||
DigitalType int `json:"digital_type"`
|
||||
CoverPath string `json:"cover_path"`
|
||||
CoverRotateDeg int `json:"cover_rotate_deg"`
|
||||
ShootAtCount int `json:"shoot_at_count"`
|
||||
ShootDoneCount int `json:"shoot_done_count"`
|
||||
UploadCoverCount int `json:"upload_cover_count"`
|
||||
UploadHighmodeCount int `json:"upload_highmode_count"`
|
||||
UploadYuvCount int `json:"upload_yuv_count"`
|
||||
FirstShootAt string `json:"first_shoot_at"`
|
||||
FirstShootDoneAt string `json:"first_shoot_done_at"`
|
||||
LastShootAt string `json:"last_shoot_at"`
|
||||
LastShootDoneAt string `json:"last_shoot_done_at"`
|
||||
CheckStatus int `json:"check_status"`
|
||||
CheckFailReason string `json:"check_fail_reason"`
|
||||
CheckAt string `json:"check_at"`
|
||||
ShopId int `json:"shop_id"`
|
||||
EqId int `json:"eq_id"`
|
||||
MasterVer string `json:"master_ver"`
|
||||
EqType int `json:"eq_type"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UploadDoneAt string `json:"upload_done_at"`
|
||||
MinipreviewUploadDoneAt string `json:"minipreview_upload_done_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
IsPrivary int `json:"is_privary"`
|
||||
CancelAt string `json:"cancel_at"`
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
Id int `json:"id"`
|
||||
Pid int `json:"pid"`
|
||||
CustomerId int `json:"customer_id"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
Status int `json:"status"`
|
||||
OrderId int `json:"order_id"`
|
||||
DigitalOrderId int `json:"digital_order_id"`
|
||||
DigitalType int `json:"digital_type"`
|
||||
CoverPath string `json:"cover_path"`
|
||||
CoverRotateDeg int `json:"cover_rotate_deg"`
|
||||
ShootAtCount int `json:"shoot_at_count"`
|
||||
ShootDoneCount int `json:"shoot_done_count"`
|
||||
UploadCoverCount int `json:"upload_cover_count"`
|
||||
UploadHighmodeCount int `json:"upload_highmode_count"`
|
||||
UploadYuvCount int `json:"upload_yuv_count"`
|
||||
FirstShootAt string `json:"first_shoot_at"`
|
||||
FirstShootDoneAt string `json:"first_shoot_done_at"`
|
||||
LastShootAt string `json:"last_shoot_at"`
|
||||
LastShootDoneAt string `json:"last_shoot_done_at"`
|
||||
CheckStatus int `json:"check_status"`
|
||||
CheckFailReason string `json:"check_fail_reason"`
|
||||
CheckAt string `json:"check_at"`
|
||||
ShopId int `json:"shop_id"`
|
||||
EqId int `json:"eq_id"`
|
||||
MasterVer string `json:"master_ver"`
|
||||
EqType int `json:"eq_type"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UploadDoneAt string `json:"upload_done_at"`
|
||||
MinipreviewUploadDoneAt string `json:"minipreview_upload_done_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
IsPrivary int `json:"is_privary"`
|
||||
CancelAt string `json:"cancel_at"`
|
||||
}
|
||||
|
||||
type PageResData struct {
|
||||
Total int `json:"total"`
|
||||
Rows []AddData `json:"rows"`
|
||||
}
|
||||
|
||||
type PageReqData struct {
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
Pid int `json:"pid"`
|
||||
CustomerId int `json:"customer_id"`
|
||||
CustomerName string `json:"customer_name"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
type DeleteReqData struct {
|
||||
Pid int `json:"pid"`
|
||||
Id int `json:"id"`
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gmutex"
|
||||
)
|
||||
|
||||
const (
|
||||
SuccessCode int = 1000
|
||||
ErrorCode int = -1
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
// 代码
|
||||
Code int `json:"code" example:"200"`
|
||||
// 数据集
|
||||
Data interface{} `json:"data"`
|
||||
// 消息
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
var (
|
||||
response = new(Response)
|
||||
mu = gmutex.New()
|
||||
)
|
||||
|
||||
|
||||
func RJson(r *ghttp.Request, code int, message string, data ...interface{}) {
|
||||
response.RJson(r, code, message, data...)
|
||||
}
|
||||
|
||||
func SusJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) {
|
||||
// message = lang.ToKey(r.GetCtx(), message)
|
||||
response.SusJson(isExit, r, message, data...)
|
||||
}
|
||||
|
||||
func FailJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) {
|
||||
// message = lang.ToKey(r.GetCtx(), message)
|
||||
response.FailJson(isExit, r, message, data...)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 返回JSON数据并退出当前HTTP执行函数。
|
||||
func (res *Response) JsonExit(r *ghttp.Request, code int, message string, data ...interface{}) {
|
||||
res.RJson(r, code, message, data...)
|
||||
r.Exit()
|
||||
}
|
||||
|
||||
|
||||
// 标准返回结果数据结构封装。
|
||||
// 返回固定数据结构的JSON:
|
||||
// code: 状态码(200:成功,302跳转,和http请求状态码一至);
|
||||
// message: 请求结果信息;
|
||||
// data: 请求结果,根据不同接口返回结果的数据结构不同;
|
||||
func (res *Response) RJson(r *ghttp.Request, code int, message string, data ...interface{}) {
|
||||
responseData := interface{}(nil)
|
||||
if len(data) > 0 {
|
||||
responseData = data[0]
|
||||
}
|
||||
response = &Response{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Data: responseData,
|
||||
}
|
||||
r.SetParam("apiReturnRes", response)
|
||||
r.Response.WriteJson(response)
|
||||
}
|
||||
|
||||
// 成功返回JSON
|
||||
func (res *Response) SusJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) {
|
||||
if isExit {
|
||||
res.JsonExit(r, SuccessCode, message, data...)
|
||||
}
|
||||
res.RJson(r, SuccessCode, message, data...)
|
||||
}
|
||||
|
||||
// 失败返回JSON
|
||||
func (res *Response) FailJson(isExit bool, r *ghttp.Request, message string, data ...interface{}) {
|
||||
if isExit {
|
||||
res.JsonExit(r, ErrorCode, message, data...)
|
||||
}
|
||||
res.RJson(r, ErrorCode, message, data...)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user