def.go 6.9 KB
Newer Older
aaronchen2k2k's avatar
aaronchen2k2k 已提交
1 2 3
package serverService

import (
aaronchen2k2k's avatar
aaronchen2k2k 已提交
4
	"github.com/easysoft/zendata/src/gen"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
5 6
	"github.com/easysoft/zendata/src/model"
	"github.com/easysoft/zendata/src/server/repo"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
7
	serverUtils "github.com/easysoft/zendata/src/server/utils"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
8
	"github.com/easysoft/zendata/src/service"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
9 10
	constant "github.com/easysoft/zendata/src/utils/const"
	fileUtils "github.com/easysoft/zendata/src/utils/file"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
11
	stringUtils "github.com/easysoft/zendata/src/utils/string"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
12
	"github.com/easysoft/zendata/src/utils/vari"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
13 14
	"github.com/jinzhu/gorm"
	"gopkg.in/yaml.v3"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
15
	"io/ioutil"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
16
	"path"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
17
	"strconv"
18
	"strings"
aaronchen2k2k's avatar
aaronchen2k2k 已提交
19 20 21 22 23 24
)

type DefService struct {
	defRepo *serverRepo.DefRepo
	fieldRepo *serverRepo.FieldRepo
	referRepo *serverRepo.ReferRepo
aaronchen2k2k's avatar
aaronchen2k2k 已提交
25
	resService *ResService
aaronchen2k2k's avatar
aaronchen2k2k 已提交
26 27
}

28 29
func (s *DefService) List(keywords string, page int) (list []*model.ZdDef, total int) {
	list, total, _ = s.defRepo.List(strings.TrimSpace(keywords), page)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
30 31 32
	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
33
func (s *DefService) Get(id int) (def model.ZdDef, dirs []model.Dir) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
34
	def, _ = s.defRepo.Get(uint(id))
aaronchen2k2k's avatar
aaronchen2k2k 已提交
35

aaronchen2k2k's avatar
aaronchen2k2k 已提交
36
	serverUtils.GetDirs(constant.ResDirUsers, &dirs)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
37 38 39 40

	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
41 42
func (s *DefService) Save(def *model.ZdDef) (err error) {
	def.Folder = serverUtils.DealWithPathSepRight(def.Folder)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
43
	def.Path = vari.WorkDir + def.Folder + serverUtils.AddExt(def.FileName, ".yaml")
aaronchen2k2k's avatar
aaronchen2k2k 已提交
44 45 46 47 48 49

	if def.ID == 0 {
		err = s.Create(def)
	} else {
		err = s.Update(def)
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
50 51
	s.updateYaml(def.ID)

aaronchen2k2k's avatar
aaronchen2k2k 已提交
52 53
	return
}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
54

aaronchen2k2k's avatar
aaronchen2k2k 已提交
55
func (s *DefService) Create(def *model.ZdDef) (err error) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
56 57
	err = s.defRepo.Create(def)

aaronchen2k2k's avatar
aaronchen2k2k 已提交
58
	// add root field node
aaronchen2k2k's avatar
aaronchen2k2k 已提交
59
	rootField, err := s.fieldRepo.CreateTreeNode(def.ID, 0, "字段", "root")
aaronchen2k2k's avatar
aaronchen2k2k 已提交
60
	s.referRepo.CreateDefault(rootField.ID, constant.ResTypeDef)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
61
	err = s.defRepo.Update(def)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
62

aaronchen2k2k's avatar
aaronchen2k2k 已提交
63 64 65
	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
66
func (s *DefService) Update(def *model.ZdDef) (err error) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
67 68
	var old model.ZdDef
	old, err = s.defRepo.Get(def.ID)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
69 70 71
	if err == gorm.ErrRecordNotFound {
		return
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
72 73
	if def.Path != old.Path {
		fileUtils.RemoveExist(old.Path)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
74 75 76 77 78 79 80 81
	}

	err = s.defRepo.Update(def)

	return
}

func (s *DefService) Remove(id int) (err error) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
82 83
	var old model.ZdDef
	old, err = s.defRepo.Get(uint(id))
aaronchen2k2k's avatar
aaronchen2k2k 已提交
84 85 86
	if err == gorm.ErrRecordNotFound {
		return
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
87
	fileUtils.RemoveExist(old.Path)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
88 89 90 91 92

	err = s.defRepo.Remove(uint(id))
	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
93 94 95
func (s *DefService) updateYaml(id uint) (err error) {
	var po model.ZdDef
	po, _ = s.defRepo.Get(id)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
96

aaronchen2k2k's avatar
aaronchen2k2k 已提交
97 98 99
	s.genYaml(&po)
	err = s.defRepo.UpdateYaml(po)
	fileUtils.WriteFile(po.Path, po.Yaml)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
100 101 102 103

	return
}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
104
func (s *DefService) genYaml(def *model.ZdDef) (str string) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
105 106 107 108 109
	root, err := s.fieldRepo.GetDefFieldTree(def.ID)
	if err != nil {
		return
	}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
110 111
	yamlObj := model.DefData{}
	s.defRepo.GenDef(*def, &yamlObj)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
112

aaronchen2k2k's avatar
aaronchen2k2k 已提交
113
	for _, child := range root.Fields { // ignore the root
aaronchen2k2k's avatar
aaronchen2k2k 已提交
114
		defField := model.DefField{}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
115
		zdFieldToFieldForExport(*child, &defField)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
116

aaronchen2k2k's avatar
aaronchen2k2k 已提交
117
		yamlObj.Fields = append(yamlObj.Fields, defField)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
118 119
	}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
120
	bytes, err := yaml.Marshal(yamlObj)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
121
	def.Yaml = stringUtils.ConvertYamlStringToMapFormat(bytes)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
122 123 124 125

	return
}

126
func (s *DefService) Sync(files []model.ResFile) (err error) {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
127
	list := s.defRepo.ListAll()
128

aaronchen2k2k's avatar
aaronchen2k2k 已提交
129 130 131
	mp := map[string]*model.ZdDef{}
	for _, item := range list {
		mp[item.Path] = item
aaronchen2k2k's avatar
aaronchen2k2k 已提交
132 133
	}

134
	for _, fi := range files {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
135 136 137 138 139
		// for yaml "res", "data" type should be default value text
		if fi.ResType == "" || fi.ResType == constant.ResTypeYaml {
			fi.ResType = constant.ResTypeText
		}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
140
		_, found := mp[fi.Path]
aaronchen2k2k's avatar
aaronchen2k2k 已提交
141 142
		if !found { // no record
			s.SyncToDB(fi)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
143 144
		} else if fi.UpdatedAt.Unix() > mp[fi.Path].UpdatedAt.Unix() { // db is old
			s.defRepo.Remove(mp[fi.Path].ID)
145
			s.SyncToDB(fi)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
146 147 148 149 150
		}
	}

	return
}
151 152 153
func (s *DefService) SyncToDB(fi model.ResFile) (err error) {
	content, _ := ioutil.ReadFile(fi.Path)
	yamlContent := stringUtils.ReplaceSpecialChars(content)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
154 155 156 157 158 159 160
	po := model.ZdDef{}
	err = yaml.Unmarshal(yamlContent, &po)
	po.Title = fi.Title
	po.Type = fi.ResType
	po.Desc = fi.Desc
	po.Path = fi.Path
	po.Folder = serverUtils.GetRelativePath(po.Path)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
161

162
	po.ReferName = service.PathToName(po.Path, constant.ResDirUsers, po.Type)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
163 164
	po.FileName = fileUtils.GetFileName(po.Path)

aaronchen2k2k's avatar
aaronchen2k2k 已提交
165 166 167 168 169
	po.Yaml = string(content)

	s.defRepo.Create(&po)

	rootField, _ := s.fieldRepo.CreateTreeNode(po.ID, 0, "字段", "root")
170
	s.referRepo.CreateDefault(rootField.ID, constant.ResTypeDef)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
171
	for i, field := range po.Fields {
172
		field.Ord = i + 1
aaronchen2k2k's avatar
aaronchen2k2k 已提交
173
		s.saveFieldToDB(&field, fi.Path, rootField.ID, po.ID)
174 175 176 177
	}

	return
}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
178 179 180
func (s *DefService) saveFieldToDB(item *model.ZdField, currPath string, parentID, defID uint) {
	refer := model.ZdRefer{OwnerType: "def", OwnerID: item.ID}

181
	if item.Select != "" { // refer to excel
aaronchen2k2k's avatar
aaronchen2k2k 已提交
182 183 184 185 186 187
		refer.Type = constant.ResTypeExcel

		refer.ColName = item.Select
		refer.Condition = item.Where
		refer.Rand = item.Rand

aaronchen2k2k's avatar
aaronchen2k2k 已提交
188 189
		_, sheet := fileUtils.ConvertResExcelPath(item.From)
		refer.File = item.From
aaronchen2k2k's avatar
aaronchen2k2k 已提交
190 191
		refer.Sheet = sheet

aaronchen2k2k's avatar
aaronchen2k2k 已提交
192 193 194 195 196 197 198 199
	} else if item.Use != "" { // refer to ranges or instances, need to read yaml to get the type
		rangeSections := gen.ParseRangeProperty(item.Use)
		if len(rangeSections) > 0 { // only get the first one
			rangeSection := rangeSections[0]
			desc, _, count := gen.ParseRangeSection(rangeSection) // medium{2}
			refer.ColName = desc
			refer.Count = count
		}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
200

aaronchen2k2k's avatar
aaronchen2k2k 已提交
201
		path := ConvertReferRangeToPath(item.From, currPath)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
202
		_, _, refer.Type = service.ReadYamlInfo(path)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
203
		refer.File = item.From
aaronchen2k2k's avatar
aaronchen2k2k 已提交
204

205 206 207
	} else if item.Config != "" { // refer to config
		refer.Type = constant.ResTypeConfig

aaronchen2k2k's avatar
aaronchen2k2k 已提交
208 209
		rangeSections := gen.ParseRangeProperty(item.Config) // dir/config.yaml
		if len(rangeSections) > 0 { // only get the first one
210 211 212 213
			rangeSection := rangeSections[0]
			desc, _, count := gen.ParseRangeSection(rangeSection)
			refer.Count = count

aaronchen2k2k's avatar
aaronchen2k2k 已提交
214 215
			path := ConvertReferRangeToPath(desc, currPath)
			refer.File = GetRelatedPathWithResDir(path)
216 217
		}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
218 219 220
	} else if item.Range != "" { // deal with yaml and text refer using range prop
		item.Range = strings.TrimSpace(item.Range)
		rangeSections := gen.ParseRangeProperty(item.Range)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
221
		if len(rangeSections) > 0 { // only get the first one
aaronchen2k2k's avatar
aaronchen2k2k 已提交
222
			rangeSection := rangeSections[0]
aaronchen2k2k's avatar
aaronchen2k2k 已提交
223
			desc, step, count := gen.ParseRangeSection(rangeSection) // dir/users.txt:R{3}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
224

aaronchen2k2k's avatar
aaronchen2k2k 已提交
225
			if path.Ext(desc) == ".txt" { // dir/users.txt:2
aaronchen2k2k's avatar
aaronchen2k2k 已提交
226
				refer.Type = constant.ResTypeText
aaronchen2k2k's avatar
aaronchen2k2k 已提交
227 228 229 230 231 232 233 234

				if strings.ToLower(step) == "r" {
					refer.Rand = true
				} else {
					refer.Step, _ = strconv.Atoi(step)
				}

			} else if path.Ext(desc) == ".yaml" { // dir/content.yaml{3}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
235
				refer.Type = constant.ResTypeYaml
aaronchen2k2k's avatar
aaronchen2k2k 已提交
236 237

				refer.Count = count
aaronchen2k2k's avatar
aaronchen2k2k 已提交
238
			}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
239
			if path.Ext(desc) == ".txt" || path.Ext(desc) == ".yaml" {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
240 241
				path := ConvertReferRangeToPath(desc, currPath)
				refer.File = GetRelatedPathWithResDir(path)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
242 243 244 245
			}
		}
	}

aaronchen2k2k's avatar
aaronchen2k2k 已提交
246 247
	item.DefID = defID
	item.ParentID = parentID
aaronchen2k2k's avatar
aaronchen2k2k 已提交
248 249 250 251 252 253
	if item.Type == "" {
		item.Type = constant.FieldTypeList
	}
	if item.Mode == "" {
		item.Mode = constant.ModeParallel
	}
aaronchen2k2k's avatar
aaronchen2k2k 已提交
254
	s.fieldRepo.Save(item)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
255 256
	refer.OwnerID = item.ID
	s.referRepo.Save(&refer)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
257 258

	for _, child := range item.Fields {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
259
		s.saveFieldToDB(child, currPath, item.ID, defID)
aaronchen2k2k's avatar
aaronchen2k2k 已提交
260 261
	}
}
262

aaronchen2k2k's avatar
aaronchen2k2k 已提交
263 264
func NewDefService(defRepo *serverRepo.DefRepo, fieldRepo *serverRepo.FieldRepo,
	referRepo *serverRepo.ReferRepo) *DefService {
aaronchen2k2k's avatar
aaronchen2k2k 已提交
265 266
	return &DefService{defRepo: defRepo, fieldRepo: fieldRepo, referRepo: referRepo}
}