修正基本架构逻辑,基本实现离线功能

This commit is contained in:
2024-10-11 01:03:17 +08:00
parent 1a0a9466d8
commit 0716c82833
14 changed files with 331 additions and 96 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ type Config struct {
var T = Config{
DbPath: "./data/data.db",
CardDir: "./data",
CardInfo: "info.json",
CardInfo: "package.json",
}
func init() {
-1
View File
@@ -17,7 +17,6 @@ func InitDB() {
panic(err)
}
err = DB.AutoMigrate(
&models.ErlangCards{},
&models.ErlangCardCollections{},
&models.History{},
&models.Users{},
+156
View File
@@ -0,0 +1,156 @@
package global
import (
"encoding/json"
"fmt"
"gorm.io/gorm"
"testing"
"work_cation/pkg/gormx"
)
type TestModel struct {
gorm.Model
Value []byte
}
func InitDb() *gorm.DB {
const testDbPath = "./test_data.db"
db, err := gormx.New(gormx.Config{DSN: testDbPath, Type: "sqlite3"})
if err != nil {
panic(err)
}
db.AutoMigrate(&TestModel{})
return db
}
func TestP1(t *testing.T) {
db := InitDb()
for i := 0; i < 100; i++ {
db.Create(&TestModel{Value: []byte(fmt.Sprintf("%d", i))})
}
}
func TestP2(t *testing.T) {
db := InitDb()
var (
row []TestModel
id = []int{1, 2}
)
f := func(tx *gorm.DB) *gorm.DB {
// Find SELECT `id`,`value` FROM `test_models` WHERE id = 1 AND `test_models`.`deleted_at` IS NULL ORDER BY ID desc
// First SELECT `id`,`value` FROM `test_models` WHERE id = 1 AND `test_models`.`deleted_at` IS NULL ORDER BY ID desc,`test_models`.`id` LIMIT 1
// row value misused 滥用
return tx.
Where("id in ?", id).
//Or("id = ? ", id+1).
Select("value").
Order("ID desc").Find(&row)
}
testSql(db, f)
fmt.Println("row:", row)
}
func TestP3(t *testing.T) {
db := InitDb()
var (
row []TestModel
//id = []int{1, 2}
)
f := func(tx *gorm.DB) *gorm.DB {
// Update `test_models` SET `value`="[1 2]",`updated_at`="2024-10-05 13:21:47.253" WHERE id in (1,2) AND `test_models`.`deleted_at` IS NULL 返回个数:2 err: <nil>
// Save SELECT `id`,`value` FROM `test_models` WHERE id = 1 AND `test_models`.`deleted_at` IS NULL ORDER BY ID desc,`test_models`.`id` LIMIT 1
// row value misused 滥用
return tx.Model(&TestModel{}).
Where("id in ?", 5).
Save(TestModel{Model: gorm.Model{ID: 5}, Value: []byte("1")})
//Where("id in ?", id).
//Limit(1).
//Update("value", []byte(fmt.Sprintf("%d", id)))
//Or("id = ? ", id+1).
//Select("value").
//Order("ID desc").Find(&row)
}
testSql(db, f)
fmt.Println("row:", row)
}
func testSql(db *gorm.DB, fun func(db *gorm.DB) *gorm.DB) {
sql := db.ToSQL(func(tx *gorm.DB) *gorm.DB {
return fun(tx)
})
db1 := fun(db)
var sum int64
err := db1.Count(&sum).Error
fmt.Printf("接收的sql语句:%s 返回个数:%d err: %v\n", sql, sum, err)
}
type KeyValueModel struct {
Key string `gorm:"primarykey"`
Value []byte
}
func InitMode(name string, db *gorm.DB) error {
return db.Table(name).Migrator().CreateTable(&KeyValueModel{})
}
func Get[T any](db *gorm.DB, tableName, key string) *T {
db = db.Table(tableName)
var valueM = KeyValueModel{}
db.Where("key = ?", key).First(&valueM)
var result T
err := json.Unmarshal(valueM.Value, &result)
if err != nil {
return nil
}
return &result
}
func Set(db *gorm.DB, tableName, key string, value any) error {
var valueM = KeyValueModel{Key: key}
var err error
valueM.Value, err = json.Marshal(value)
if err != nil {
return err
}
var sum int64
db.Table(tableName).Where("key = ?", key).Count(&sum)
if sum == 0 {
return db.Create(&valueM).Error
}
return db.Table(tableName).Where("key = ?", key).Save(&valueM).Error // ambiguous column name: key
}
type TestMode1 struct {
Name string
Level int
}
func TestInitDB1(t *testing.T) {
const tableName = "role1"
db := InitDb()
err := InitMode(tableName, db)
fmt.Println("auto create table:", err)
err = Set(db, tableName, "1", TestMode1{"测试1", 1})
if err != nil {
panic(err)
}
ret := Get[TestMode1](db, tableName, "1")
err = Set(db, tableName, "1", TestMode1{"测试1", 2})
if err != nil {
panic(err)
}
ret = Get[TestMode1](db, tableName, "1")
fmt.Println(ret)
}
+3 -2
View File
@@ -20,8 +20,9 @@ type BaseCard struct {
}
const (
ToolTypeErlang = "erlangCard" // 卡片
ToolTypeExecFiles = "execFiles" // 可执行文件
ToolTypeErlang = "erlangCard" // 卡片
ToolTypeNoVarErlang = "erlangNoVarCard"
ToolTypeExecFiles = "execFiles" // 可执行文件
)
func NewBaseCard(t, userId string) BaseCard {
+1 -5
View File
@@ -3,11 +3,7 @@ package models
import "work_cation/pkg/gormx"
type ErlangCards struct {
UUID string `json:"uuid"` // id ip加时间戳生成
UserID string `json:"user_id"` // 用户id
Title string `json:"title"` // 标题
Text string `json:"text"` // 内容
Covers gormx.ListString `json:"covers"` // 封面
BaseCard
Template string `json:"template"` // 模版
VarName gormx.ListString `json:"var_name"` // 变量
VarContent gormx.ListString `json:"var_content"` // 变量内容
+17
View File
@@ -2,6 +2,9 @@ package service
import (
"gorm.io/gorm"
"os"
"path/filepath"
"work_cation/cfg"
"work_cation/models"
"work_cation/repo"
)
@@ -13,3 +16,17 @@ var BaseCard = &BaseCardService{}
func (*BaseCardService) Create(db *gorm.DB, baseCard models.BaseCard) {
repo.BaseCard.Create(db, &baseCard)
}
func (*BaseCardService) Update(db *gorm.DB, updateCard models.BaseCard) {
}
func (*BaseCardService) Delete(db *gorm.DB, deleteCard models.BaseCard) error {
fileDir := filepath.Join(cfg.T.CardDir, deleteCard.UUID)
err := os.RemoveAll(fileDir)
if err != nil {
return err
}
err = db.Model(&models.BaseCard{}).Where("uuid = ?", deleteCard.UUID).Delete(&deleteCard).Error
return err
}
+6 -18
View File
@@ -5,7 +5,6 @@ import (
"gorm.io/gorm"
"os"
"path/filepath"
"time"
"work_cation/cfg"
"work_cation/global"
"work_cation/models"
@@ -17,6 +16,9 @@ type erlangCardService struct{}
var ErlangCard = &erlangCardService{}
func (*erlangCardService) Create(erlangCard *models.ErlangCards) error {
if len(erlangCard.VarName) == 0 {
erlangCard.ToolType = models.ToolTypeNoVarErlang
}
err := os.Mkdir(filepath.Join(cfg.T.CardDir, erlangCard.UUID), os.ModeDir)
if err != nil {
return err
@@ -25,6 +27,7 @@ func (*erlangCardService) Create(erlangCard *models.ErlangCards) error {
if err != nil {
return err
}
defer info.Close()
jsonB, err := json.Marshal(erlangCard)
if err != nil {
return err
@@ -33,24 +36,9 @@ func (*erlangCardService) Create(erlangCard *models.ErlangCards) error {
if err != nil {
return err
}
return global.DB.Transaction(func(tx *gorm.DB) error {
err = repo.ErlangCardRepo.Create(global.DB, erlangCard)
if err != nil {
return err
}
var baseCard = models.BaseCard{
UUID: erlangCard.UUID,
UserID: erlangCard.UserID,
Title: erlangCard.Title,
Text: erlangCard.Text,
Covers: erlangCard.Covers,
ToolType: models.ToolTypeErlang,
UpdateTx: time.Now(),
Number: 0,
Goods: 0,
Collection: 0,
}
var baseCard = erlangCard.BaseCard
err = repo.BaseCard.Create(global.DB, &baseCard)
return err
})
+14 -12
View File
@@ -7,23 +7,25 @@ import (
"sort"
)
// CreateCards 创建卡片列表
func CreateCards(_ fyne.Window) fyne.CanvasObject {
// allCreateCards 创建卡片列表
func allCreateCards(_ fyne.Window) fyne.CanvasObject {
var itemList []fyne.CanvasObject
keys := make([]string, 0, len(CardTypeMap))
for key, _ := range CardTypeMap {
keys := make([]string, 0, len(cardTypeMap))
for key, _ := range cardTypeMap {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
info := CardTypeMap[key]
itemList = append(itemList, widget.NewButton(info.Name, func() {
cWin := fyne.CurrentApp().NewWindow(info.Name)
cWin.SetContent(info.createView(cWin))
cWin.Resize(info.createSize)
cWin.CenterOnScreen()
cWin.Show()
}))
info := cardTypeMap[key]
if info.createView != nil {
itemList = append(itemList, widget.NewButton(info.Name, func() {
cWin := fyne.CurrentApp().NewWindow(info.Name)
cWin.SetContent(info.createView(cWin))
cWin.Resize(info.createSize)
cWin.CenterOnScreen()
cWin.Show()
}))
}
}
return container.NewCenter(container.NewVBox(itemList...))
}
+4 -11
View File
@@ -9,23 +9,17 @@ import (
"fyne.io/fyne/v2/widget"
"regexp"
"strings"
"time"
"work_cation/global"
"work_cation/models"
"work_cation/pkg/utils"
"work_cation/repo"
"work_cation/service"
)
var erlangCard *models.ErlangCards
func CreateErlangCard(w fyne.Window) fyne.CanvasObject {
if erlangCard == nil {
erlangCard = &models.ErlangCards{
UUID: utils.Uuid.CreateUUID(),
UserID: repo.User.GetUserInfo(global.DB).ID,
}
}
var (
// 创建数据
erlangCard = &models.ErlangCards{BaseCard: models.NewBaseCard(models.ToolTypeErlang, repo.User.GetUserInfo(global.DB).ID)}
// 基础表单
formBase = &widget.Form{}
// 变量表单
@@ -49,8 +43,7 @@ func CreateErlangCard(w fyne.Window) fyne.CanvasObject {
return
}
dialog.ShowInformation("ok", "创建成功", w)
// 更换
erlangCard.UUID = utils.Uuid.CreateUUID()
time.AfterFunc(2*time.Second, func() { w.Close() })
})
return container.NewBorder(container.NewHBox(widget.NewLabel("新建"), widget.NewSeparator()),
+22 -7
View File
@@ -4,6 +4,7 @@ import (
"fyne.io/fyne/v2"
"work_cation/models"
"work_cation/views/createView"
"work_cation/views/showView"
)
// Tutorial 定义教程的数据结构
@@ -16,9 +17,9 @@ type Tutorial struct {
var (
// Tutorials 定义每个教程的元数据
Tutorials = map[string]Tutorial{
"welcome": {"主页", "", UserViews, true},
"canvas": {"我的", "", myCardsViews, true},
"create": {"新建", "", CreateCards, true},
"welcome": {"主页", "", mainUserViews, true},
"canvas": {"我的", "", allCardsViews, true},
"create": {"新建", "", allCreateCards, true},
}
// TutorialIndex 定义我们的教程应该如何在索引树中布局
@@ -26,7 +27,7 @@ var (
"": {"welcome", "canvas", "create"},
//"collections": {"list", "table", "tree"},
//"containers": {"apptabs", "border", "box", "center", "doctabs", "grid", "scroll", "split"},
//"widgets": {"accordion", "button", "card", "entry", "form", "input", "progress", "text", "toolbar"},
//"widgets": {"accordion", "button", "card", "entry", "form", "input", "progress", "text", "toolbar"}, 58 * 3 + 106 = 280
}
)
@@ -34,11 +35,25 @@ type cardInfo struct {
Name string
createView func(w fyne.Window) fyne.CanvasObject
createSize fyne.Size
showView func(fyne.Window, *models.BaseCard) (fyne.CanvasObject, error)
}
var (
CardTypeMap = map[string]cardInfo{
models.ToolTypeErlang: {"Erlang代码脚本模版", createView.CreateErlangCard, fyne.NewSize(600, 400)},
models.ToolTypeExecFiles: {"自定义可执行工具", createView.CreateExecFile, fyne.NewSize(600, 520)},
cardTypeMap = map[string]cardInfo{
models.ToolTypeNoVarErlang: {
"Erlang代码脚本",
nil,
fyne.NewSize(0, 0),
showView.ErlangCardNoVarView},
models.ToolTypeErlang: {
"Erlang代码脚本模版",
createView.CreateErlangCard,
fyne.NewSize(600, 400),
showView.ErlangCardView},
models.ToolTypeExecFiles: {
"自定义可执行工具",
createView.CreateExecFile,
fyne.NewSize(600, 520),
showView.ExecFileCardView},
}
)
+56 -11
View File
@@ -3,24 +3,69 @@ package views
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"work_cation/global"
"work_cation/models"
"work_cation/repo"
"work_cation/views/showView"
"work_cation/service"
)
func myCardsViews(w fyne.Window) fyne.CanvasObject {
var items []fyne.CanvasObject
// 卡片展示界面
func allCardsViews(w fyne.Window) fyne.CanvasObject {
//var items []fyne.CanvasObject
gridWrap := container.NewGridWrap(fyne.NewSize(200, 200))
for _, baseCard := range repo.BaseCard.FindAll(global.DB) {
switch baseCard.ToolType {
case models.ToolTypeErlang:
erlangCard := repo.ErlangCardRepo.Find(global.DB, baseCard.UUID)
items = append(items, showView.ErlangCardView(w, &erlangCard))
case models.ToolTypeExecFiles:
if info, is := cardTypeMap[baseCard.ToolType]; is {
var baseCardCopy = baseCard
items = append(items, showView.ExecFileCardView(w, &baseCardCopy))
view, err := info.showView(w, &baseCardCopy)
if err != nil {
view = errorCardView(w, &baseCardCopy, err)
}
var baseCardV *widget.Card
baseCardV = baseCardView(w, baseCardV, baseCardCopy, gridWrap, view)
gridWrap.Add(baseCardV)
}
}
return container.NewBorder(nil, nil, nil, nil, container.NewScroll(
container.NewGridWrap(fyne.NewSize(200, 200), items...)))
scroll := container.NewScroll(gridWrap)
return container.NewBorder(nil, nil, nil, nil, scroll)
}
// 单卡界面
func baseCardView(
w fyne.Window,
baseCardV *widget.Card,
baseCardCopy models.BaseCard,
gridWrap *fyne.Container,
view fyne.CanvasObject) *widget.Card {
baseCardV = widget.NewCard(baseCardCopy.Title, baseCardCopy.Text, container.NewBorder(nil, widget.NewToolbar(
widget.NewToolbarAction(theme.ContentAddIcon(), func() {}),
widget.NewToolbarAction(theme.DeleteIcon(), func() {
err := service.BaseCard.Delete(global.DB, baseCardCopy)
if err != nil {
dialog.ShowInformation("删除失败", err.Error(), w)
return
}
gridWrap.Remove(baseCardV)
}),
widget.NewToolbarAction(theme.SettingsIcon(), func() {}),
widget.NewToolbarAction(theme.ViewRefreshIcon(), func() {
}),
), nil, nil, view))
return baseCardV
}
func errorCardView(w fyne.Window, data *models.BaseCard, err error) fyne.CanvasObject {
cardButton := widget.NewButton("出错尝试修复", func() {
dialog.ShowInformation("结果", "修复失败", w)
})
showErrButton := widget.NewButton("工具解析错误", func() {
dialog.ShowInformation("错误", err.Error(), w)
})
card := widget.NewCard(data.Title, data.Text, container.NewVBox(showErrButton, cardButton))
return card
}
+47 -24
View File
@@ -1,44 +1,67 @@
package showView
import (
"encoding/json"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/data/binding"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
"github.com/atotto/clipboard"
"os"
"path/filepath"
"strings"
"work_cation/cfg"
"work_cation/models"
)
func ErlangCardView(w fyne.Window, data *models.ErlangCards) fyne.CanvasObject {
if len(data.VarName) == 0 {
return widget.NewCard(data.Title, data.Text, widget.NewButton("复制", func() {
cleanedText := strings.ReplaceAll(data.Template, "\r", "")
cleanedText = strings.ReplaceAll(cleanedText, "\n", "")
err := clipboard.WriteAll(cleanedText)
if err != nil {
dialog.ShowError(err, w)
return
}
dialog.NewInformation("复制脚本成功", data.Template, w).Show()
}))
}
txtBound := binding.NewString()
txtBound.Set(data.Template)
txtWid := widget.NewEntryWithData(txtBound)
txtWid.Wrapping = fyne.TextWrapOff
cardButton := widget.NewButton("OPEN", func() {
go UseErlangCard(data)
func ErlangCardNoVarView(w fyne.Window, baseInfo *models.BaseCard) (fyne.CanvasObject, error) {
button := widget.NewButton("复制", func() {
// 读取类型文件数据
infoPath := filepath.Join(cfg.T.CardDir, baseInfo.UUID, cfg.T.CardInfo)
bytes, err := os.ReadFile(infoPath)
if err != nil {
dialog.ShowError(err, w)
return
}
var data models.ErlangCards
err = json.Unmarshal(bytes, &data)
if err != nil {
dialog.ShowError(err, w)
return
}
cleanedText := strings.ReplaceAll(data.Template, "\r", "")
cleanedText = strings.ReplaceAll(cleanedText, "\n", "")
err = clipboard.WriteAll(cleanedText)
if err != nil {
dialog.ShowError(err, w)
return
}
dialog.NewInformation("复制脚本成功", data.Template, w).Show()
})
return button, nil
}
card := widget.NewCard(data.Title, data.Text, cardButton)
func ErlangCardView(w fyne.Window, baseInfo *models.BaseCard) (fyne.CanvasObject, error) {
cardButton := widget.NewButton("OPEN", func() {
// 读取类型文件数据
infoPath := filepath.Join(cfg.T.CardDir, baseInfo.UUID, cfg.T.CardInfo)
bytes, err := os.ReadFile(infoPath)
if err != nil {
dialog.ShowError(err, w)
return
}
var data models.ErlangCards
err = json.Unmarshal(bytes, &data)
if err != nil {
dialog.ShowError(err, w)
return
}
go UseErlangCard(&data)
})
//image := canvas.NewImageFromResource(assets.LogoDataSR)
//image.FillMode = canvas.ImageFillContain
//card.SetImage(image)
return card
return cardButton, nil
}
func UseErlangCard(data *models.ErlangCards) {
+3 -3
View File
@@ -13,12 +13,12 @@ import (
"work_cation/models"
)
func ExecFileCardView(w fyne.Window, data *models.BaseCard) fyne.CanvasObject {
func ExecFileCardView(w fyne.Window, data *models.BaseCard) (fyne.CanvasObject, error) {
cardButton := widget.NewButton("启动", func() { runExecFile(data, w) })
openDirButton := widget.NewButton("打开目录", func() { openDir(data, w) })
card := widget.NewCard(data.Title, data.Text, container.NewVBox(cardButton, openDirButton))
return card
card := container.NewVBox(cardButton, openDirButton)
return card, nil
}
func runExecFile(data *models.BaseCard, w fyne.Window) {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"work_cation/repo"
)
func UserViews(w fyne.Window) fyne.CanvasObject {
func mainUserViews(w fyne.Window) fyne.CanvasObject {
image := canvas.NewImageFromResource(assets.LogoDataSR)
image.FillMode = canvas.ImageFillContain