tree_service.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /*
  2. * @description:层级文件夹数据操作相关
  3. * @Author: CP
  4. * @Date: 2020-09-11 14:43:58
  5. * @FilePath: \construction_management\services\tree_service.go
  6. */
  7. package services
  8. import (
  9. "encoding/json"
  10. "errors"
  11. "fmt"
  12. "log"
  13. "strconv"
  14. "time"
  15. "github.com/kataras/iris/v12"
  16. "go.mod/comm"
  17. "go.mod/conf"
  18. "go.mod/dao"
  19. "go.mod/datasource"
  20. "go.mod/models"
  21. "go.mod/web/viewmodels"
  22. )
  23. //定义项目Service接口
  24. type TreeService interface {
  25. //ValidManager(code string, account string, password string) error
  26. ValidRule(ctx iris.Context) (viewmodels.Tree, error)
  27. Create(data viewmodels.Tree) error
  28. GetAllProject(projectId int) *viewmodels.Tree
  29. GetAllContract(projectId int) *viewmodels.FolderContract
  30. Rename(treevm viewmodels.Tree, projectId int) error
  31. GetFolderAndBid(id int, projectId int) ([]models.CmTree, error)
  32. DeleteFolderAndBid(id int, projectId int) error
  33. Move(id int, moveId int, projectId int) error
  34. }
  35. //返回service操作类
  36. type treeService struct {
  37. dao *dao.TreeDao
  38. }
  39. //创建项目service
  40. func NewTreeService() TreeService {
  41. return &treeService{
  42. dao: dao.NewTreeDao(datasource.InstanceDbMaster()),
  43. }
  44. }
  45. // 文件夹规则验证
  46. func (s *treeService) ValidRule(ctx iris.Context) (viewmodels.Tree, error) {
  47. folderVaild := viewmodels.Tree{}
  48. err := ctx.ReadJSON(&folderVaild)
  49. if err != nil {
  50. log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
  51. return folderVaild, err
  52. }
  53. err = folderVaild.Validate()
  54. if err != nil {
  55. log.Println("文件夹验证, error=", err)
  56. return folderVaild, err
  57. }
  58. return folderVaild, nil
  59. }
  60. // 获得项目下 相关文件夹-整个树结构
  61. func (s *treeService) GetAllProject(projectId int) *viewmodels.Tree {
  62. datalist := s.dao.GetAllTree(projectId)
  63. folderlist := make([]*viewmodels.Tree, 0)
  64. // 生成根
  65. folder := &viewmodels.Tree{}
  66. id, _ := comm.AesEncrypt(strconv.Itoa(0), conf.SignSecret)
  67. parentId, _ := comm.AesEncrypt(strconv.Itoa(-1), conf.SignSecret)
  68. folder.Id = id
  69. folder.Name = "root"
  70. folder.Isfolder = 1
  71. folder.ParentId = parentId
  72. folderlist = append(folderlist, folder)
  73. // 加入数据
  74. for _, data := range datalist {
  75. folder := &viewmodels.Tree{}
  76. //folder.Id = comm.Encrypt([]byte(conf.SignSecret), []byte(strconv.Itoa(data.Id)))
  77. id, _ := comm.AesEncrypt(strconv.Itoa(data.Id), conf.SignSecret)
  78. parentId, _ := comm.AesEncrypt(strconv.Itoa(data.ParentId), conf.SignSecret)
  79. projectId, _ := comm.AesEncrypt(strconv.Itoa(data.ProjectId), conf.SignSecret)
  80. serial, _ := comm.AesEncrypt(strconv.Itoa(data.Serial), conf.SignSecret)
  81. bidsectionId, _ := comm.AesEncrypt(strconv.Itoa(data.BidsectionId), conf.SignSecret)
  82. folder.Id = id
  83. folder.Name = data.Name
  84. folder.ParentId = parentId
  85. folder.ProjectId = projectId
  86. folder.BidsectionId = bidsectionId
  87. folder.Depth = data.Depth + 1
  88. folder.Serial = serial
  89. folder.Ancounts = data.Ancounts
  90. folder.Isfolder = data.Isfolder
  91. folder.IsEnd = false
  92. //folder.Leaf = true
  93. folder.HasFolder = false
  94. folder.IsBid = false
  95. folder.CreateTime = data.CreateTime.Format(conf.SysTimeform)
  96. folderlist = append(folderlist, folder)
  97. }
  98. //fmt.Println(folderlist)
  99. //var data []*viewmodels.Tree
  100. // data := make([]*viewmodels.Tree, 0)
  101. // for i, _ := range folderlist {
  102. // var a *viewmodels.Tree
  103. // a = &folderlist[i]
  104. // data = append(data, a)
  105. // }
  106. node := folderlist[0] //父节点
  107. maketree(folderlist, node) //调用生成tree
  108. //transformjson(node) //转化为json
  109. return node
  110. }
  111. // 获得合同管理的目录
  112. func (s *treeService) GetAllContract(projectId int) *viewmodels.FolderContract {
  113. datalist := s.dao.GetAllTree(projectId)
  114. folderlist := make([]viewmodels.FolderContract, 0)
  115. // 生成根
  116. folder := viewmodels.FolderContract{}
  117. id, _ := comm.AesEncrypt(strconv.Itoa(0), conf.SignSecret)
  118. parentId, _ := comm.AesEncrypt(strconv.Itoa(-1), conf.SignSecret)
  119. folder.Id = id
  120. folder.Name = "root"
  121. folder.ParentId = parentId
  122. folder.Isfolder = 1
  123. folderlist = append(folderlist, folder)
  124. // 加入数据
  125. for _, data := range datalist {
  126. folder := viewmodels.FolderContract{}
  127. id, _ := comm.AesEncrypt(strconv.Itoa(data.Id), conf.SignSecret)
  128. parentId, _ := comm.AesEncrypt(strconv.Itoa(data.ParentId), conf.SignSecret)
  129. projectId, _ := comm.AesEncrypt(strconv.Itoa(data.ProjectId), conf.SignSecret)
  130. bidsectionId, _ := comm.AesEncrypt(strconv.Itoa(data.BidsectionId), conf.SignSecret)
  131. folder.Id = id
  132. folder.Name = data.Name
  133. folder.ParentId = parentId
  134. folder.ProjectId = projectId
  135. folder.BidsectionId = bidsectionId
  136. // 合同数据
  137. folder.Contracts = data.Contracts
  138. folder.ContractsIncome = data.ContractsIncome
  139. folder.ContractsReturned = data.ContractsReturned
  140. // 汇款进度
  141. ContractsIncome, err := strconv.ParseFloat(data.ContractsIncome, 64)
  142. if err != nil {
  143. ContractsIncome = 0
  144. }
  145. ContractsReturned, err := strconv.ParseFloat(data.ContractsReturned, 64)
  146. if err != nil || ContractsReturned == 0 {
  147. ContractsReturned = 0
  148. folder.ContractsIncomeProgress = "0%"
  149. } else {
  150. folder.ContractsIncomeProgress = fmt.Sprintf("%.0f", (ContractsReturned/ContractsIncome)*100) + "%"
  151. }
  152. folder.ContractsPay = data.ContractsPay
  153. folder.ContractsPaid = data.ContractsPaid
  154. // 支付进度
  155. ContractsPay, err := strconv.ParseFloat(data.ContractsPay, 64)
  156. if err != nil {
  157. ContractsPay = 0
  158. }
  159. ContractsPaid, err := strconv.ParseFloat(data.ContractsPaid, 64)
  160. if err != nil || ContractsPaid == 0 {
  161. ContractsPaid = 0
  162. folder.ContractsPayProgress = "0%"
  163. } else {
  164. folder.ContractsPayProgress = fmt.Sprintf("%.0f", (ContractsPaid/ContractsPay)*100) + "%"
  165. }
  166. folder.Isfolder = data.Isfolder
  167. folder.IsEnd = false
  168. folder.HasFolder = false
  169. folder.IsBid = false
  170. folderlist = append(folderlist, folder)
  171. }
  172. //fmt.Println(folderlist)
  173. var data []*viewmodels.FolderContract
  174. data = make([]*viewmodels.FolderContract, 0)
  175. for i, _ := range folderlist {
  176. var a *viewmodels.FolderContract
  177. a = &folderlist[i]
  178. data = append(data, a)
  179. }
  180. node := &folderlist[0] //父节点
  181. comm.MakeFolderContract(data, node)
  182. return node
  183. }
  184. // 新增一个文件夹
  185. func (s *treeService) Create(data viewmodels.Tree) error {
  186. // 类型校验
  187. folder := models.CmTree{}
  188. folder.Name = data.Name
  189. // 项目ID
  190. ProjectId, err := strconv.Atoi(data.ProjectId)
  191. if err != nil {
  192. return err
  193. }
  194. // 获得该目录ID
  195. Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
  196. if err != nil {
  197. return err
  198. }
  199. IdInt, err1 := strconv.Atoi(Id)
  200. if err1 != nil {
  201. return err1
  202. }
  203. // 该目录中是否有标段
  204. bidlist := s.dao.GetBidsection(IdInt)
  205. if len(bidlist) > 0 {
  206. return errors.New("该文件夹已存在标段,不能在新增目录")
  207. }
  208. // 获得该深度的文件夹最大序号
  209. serial := 0
  210. depth := data.Depth + 1
  211. if data.Depth == -1 {
  212. // 1-创建顶级目录--获得最大序号
  213. datalist := s.dao.GetAllDepth(depth, ProjectId)
  214. maxIndex := len(datalist)
  215. if maxIndex != 0 {
  216. serial = datalist[maxIndex-1].Serial + 1
  217. }
  218. } else {
  219. // 1-创建次目录-获得次级目录最大序号
  220. treeNode := s.dao.Get(IdInt, ProjectId)
  221. // 去除前端depth作用-在这里获得下级目录的深度
  222. depth = treeNode.Depth + 1
  223. if treeNode.Id == 0 {
  224. return errors.New("上级目录不正确")
  225. }
  226. attribution := fmt.Sprintf("%s%d-", treeNode.Attribution, treeNode.Serial)
  227. datalist := s.dao.GetALLDepthByAttribution(depth, ProjectId, attribution)
  228. maxIndex := len(datalist)
  229. if maxIndex != 0 {
  230. serial = datalist[maxIndex-1].Serial + 1
  231. }
  232. // 设置归属
  233. folder.Attribution = attribution //treeNode.Attribution + strconv.Itoa(treeNode.Serial) + "-"
  234. folder.ParentId = IdInt
  235. }
  236. folder.ProjectId = ProjectId
  237. folder.Serial = serial
  238. folder.Depth = depth
  239. folder.Isfolder = 1
  240. folder.CreateTime = time.Now()
  241. folder.UpdateTime = time.Now()
  242. folder.ContractsIncome = "0"
  243. folder.ContractsPaid = "0"
  244. folder.ContractsPay = "0"
  245. folder.ContractsReturned = "0"
  246. err = s.dao.Create(&folder)
  247. if err != nil {
  248. log.Println("添加目录出错, error=", err)
  249. return errors.New("添加目录出错")
  250. }
  251. return nil
  252. }
  253. // 重命名
  254. func (s *treeService) Rename(data viewmodels.Tree, projectId int) error {
  255. // 获得该目录ID
  256. Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
  257. if err != nil {
  258. return err
  259. }
  260. IdInt, err1 := strconv.Atoi(Id)
  261. if err1 != nil {
  262. return err1
  263. }
  264. // 获得树信息
  265. treeData := s.dao.Get(IdInt, projectId)
  266. if treeData.Id == 0 {
  267. return errors.New("修改的目录不合法")
  268. }
  269. treeNode := models.CmTree{}
  270. treeNode.Id = IdInt
  271. treeNode.Name = data.Name
  272. if treeData.Isfolder == 1 {
  273. // 目录
  274. err = s.dao.Update(&treeNode, []string{"Name"})
  275. } else {
  276. // 标段
  277. treeNode.BidsectionId = treeData.BidsectionId
  278. err = s.dao.Rename(&treeNode, []string{"Name"})
  279. }
  280. if err != nil {
  281. return err
  282. }
  283. return nil
  284. }
  285. // 获得该目录下所有的目录和标段
  286. func (s *treeService) GetFolderAndBid(id int, projectId int) ([]models.CmTree, error) {
  287. // 获得该目录ID
  288. // id, err := comm.AesDecrypt(id, conf.SignSecret)
  289. // if err != nil {
  290. // return nil, errors.New("目录解析错误")
  291. // }
  292. // IdInt, err := strconv.Atoi(id)
  293. // if err != nil {
  294. // return nil, errors.New("目录解析错误")
  295. // }
  296. // 获得该目录下所有数据
  297. folder := s.dao.Get(id, projectId)
  298. if folder.Id == 0 {
  299. return nil, errors.New("目录不合法")
  300. }
  301. attribution := fmt.Sprintf("%s%d-", folder.Attribution, folder.Serial)
  302. // 获得目录归属
  303. dataList := s.dao.GetFolderAndBid(folder.ProjectId, attribution)
  304. return dataList, nil
  305. }
  306. // 删除该目录和所属的目录和标段
  307. func (s *treeService) DeleteFolderAndBid(id int, projectId int) error {
  308. // 获得该目录ID
  309. // id, err := comm.AesDecrypt(id, conf.SignSecret)
  310. // if err != nil {
  311. // return errors.New("目录解析错误")
  312. // }
  313. // IdInt, err := strconv.Atoi(id)
  314. // if err != nil {
  315. // return errors.New("目录解析错误")
  316. // }
  317. // 获得该目录下 归属关系
  318. folder := s.dao.Get(id, projectId)
  319. if folder.Id == 0 {
  320. return errors.New("目录不合法")
  321. }
  322. attribution := fmt.Sprintf("%s%d-", folder.Attribution, folder.Serial)
  323. // --逻辑删除 目录和数据
  324. err := s.dao.DeleteFolderAndBid(folder.Id, folder.ProjectId, attribution)
  325. if err != nil {
  326. return err
  327. }
  328. // TODO -加入堆栈 物理删除数据
  329. return nil
  330. }
  331. // 移动目录
  332. func (s *treeService) Move(id int, moveId int, projectId int) error {
  333. // 获得项目目录
  334. treeNode := s.dao.Get(id, projectId)
  335. if treeNode.Id == 0 {
  336. return errors.New("目录或标段解析错误")
  337. }
  338. targetFolder := &models.CmTree{}
  339. // id为0是跟目录
  340. if moveId == 0 {
  341. // id
  342. targetFolder.Id = 0
  343. // 1.获得最大序号
  344. // seriallist := s.dao.GetALLDepthByAttribution(0, projectId, "")
  345. // maxIndex := len(seriallist)
  346. // serial := 0
  347. // if maxIndex != 0 {
  348. // serial = seriallist[maxIndex-1].Serial + 1
  349. // }
  350. // targetFolder.Serial = serial
  351. targetFolder.Serial = 0
  352. // 2.归属
  353. targetFolder.Attribution = ""
  354. // 3.深度depth-根目录为-1
  355. targetFolder.Depth = -1
  356. // 4.为目录
  357. targetFolder.Isfolder = 1
  358. // 5.项目ID
  359. targetFolder.ProjectId = projectId
  360. // fmt.Println(targetFolder)
  361. // if targetFolder.Id == 0 {
  362. // return errors.New("目录解析错误-测试")
  363. // }
  364. } else {
  365. targetFolder = s.dao.Get(moveId, projectId)
  366. if targetFolder.Id == 0 {
  367. return errors.New("目录解析错误")
  368. }
  369. }
  370. // 目录必须是目录
  371. if targetFolder.Isfolder == 0 {
  372. return errors.New("目标不是文件夹")
  373. }
  374. // 目录的目标不能是自己
  375. if id == moveId {
  376. return errors.New("目标目录是原目录-不能移动")
  377. }
  378. // 移动的是目录
  379. if treeNode.Isfolder == 1 {
  380. // 1.目录下不能有标段
  381. // 被移动的目录存在标段
  382. moveBidList := s.dao.GetBidsection(moveId)
  383. if len(moveBidList) > 0 {
  384. return errors.New("该目录中存在标段,不能移动")
  385. }
  386. } else {
  387. // 标段
  388. // 1.移动的目录是否为叶子节点
  389. moveBidList := s.dao.GetChildFolder(moveId)
  390. if len(moveBidList) > 0 {
  391. return errors.New("该目录中存在其他目录,不能移动")
  392. }
  393. }
  394. err := s.dao.Move(treeNode, targetFolder)
  395. if err != nil {
  396. return err
  397. }
  398. return nil
  399. }
  400. // 创建一颗树...interface{}
  401. func maketree(Data []*viewmodels.Tree, node *viewmodels.Tree) { //参数为父节点,添加父节点的子节点指针切片
  402. childs, _ := havechild(Data, node) //判断节点是否有子节点并返回
  403. if childs != nil {
  404. // fmt.Printf("\n")
  405. // fmt.Println(*node)
  406. // fmt.Println("子节点:")
  407. // for _, v := range childs {
  408. // fmt.Println(*v)
  409. // } //打印
  410. // 子节点总数
  411. Total := len(childs)
  412. node.ChildsTotal = Total
  413. // 标记最后一个元素
  414. end := Total - 1
  415. childs[end].IsEnd = true
  416. // 往父节点添加子节点
  417. node.Children = append(node.Children, childs[0:]...) //添加子节点
  418. for _, v := range childs { //查询子节点的子节点,并添加到子节点
  419. _, has := havechild(Data, v)
  420. if has {
  421. // 递归添加节点
  422. maketree(Data, v)
  423. }
  424. // else {
  425. // // 叶子节点
  426. // node.Leaf = false
  427. // }
  428. // 目录下是否包含标段
  429. if v.Isfolder == 0 {
  430. node.IsBid = true
  431. } else {
  432. node.HasFolder = true
  433. }
  434. }
  435. }
  436. }
  437. // 是否有子树
  438. func havechild(Data []*viewmodels.Tree, node *viewmodels.Tree) (child []*viewmodels.Tree, yes bool) {
  439. for _, v := range Data {
  440. if v.ParentId == node.Id {
  441. child = append(child, v)
  442. }
  443. }
  444. if child != nil {
  445. yes = true
  446. }
  447. return
  448. }
  449. func transformjson(Data *viewmodels.Tree) { //转为json
  450. Jsondata, _ := json.Marshal(Data)
  451. fmt.Println(string(Jsondata))
  452. }
  453. //now := comm.NowUnix()
  454. //comm.FormatFromUnixTime(now)
  455. // ParentIdInt := 0
  456. // if data.ParentId != "" {
  457. // ParentId, err := comm.AesDecrypt(data.ParentId, conf.SignSecret)
  458. // if err != nil {
  459. // return err
  460. // }
  461. // ParentIdInt, err = strconv.Atoi(ParentId)
  462. // if err != nil {
  463. // ParentIdInt = 0
  464. // }
  465. // }