tree_service.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  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, projectAccountId 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.Accounts = data.Accounts
  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, projectAccountId 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. // 求和
  183. // dataLenght := len(data) + 4
  184. return node
  185. }
  186. // 新增一个文件夹
  187. func (s *treeService) Create(data viewmodels.Tree) error {
  188. // 类型校验
  189. folder := models.CmTree{}
  190. folder.Name = data.Name
  191. // 项目ID
  192. ProjectId, err := strconv.Atoi(data.ProjectId)
  193. if err != nil {
  194. return err
  195. }
  196. // 获得该目录ID
  197. Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
  198. if err != nil {
  199. return err
  200. }
  201. IdInt, err1 := strconv.Atoi(Id)
  202. if err1 != nil {
  203. return err1
  204. }
  205. // 该目录中是否有标段
  206. bidlist := s.dao.GetBidsection(IdInt)
  207. if len(bidlist) > 0 {
  208. return errors.New("该文件夹已存在标段,不能在新增目录")
  209. }
  210. // 获得该深度的文件夹最大序号
  211. serial := 0
  212. depth := data.Depth + 1
  213. if data.Depth == -1 {
  214. // 1-创建顶级目录--获得最大序号
  215. datalist := s.dao.GetAllDepth(depth, ProjectId)
  216. maxIndex := len(datalist)
  217. if maxIndex != 0 {
  218. serial = datalist[maxIndex-1].Serial + 1
  219. }
  220. } else {
  221. // 1-创建次目录-获得次级目录最大序号
  222. treeNode := s.dao.Get(IdInt, ProjectId)
  223. // 去除前端depth作用-在这里获得下级目录的深度
  224. depth = treeNode.Depth + 1
  225. if treeNode.Id == 0 {
  226. return errors.New("上级目录不正确")
  227. }
  228. attribution := fmt.Sprintf("%s%d-", treeNode.Attribution, treeNode.Serial)
  229. datalist := s.dao.GetALLDepthByAttribution(depth, ProjectId, attribution)
  230. maxIndex := len(datalist)
  231. if maxIndex != 0 {
  232. serial = datalist[maxIndex-1].Serial + 1
  233. }
  234. // 设置归属
  235. folder.Attribution = attribution //treeNode.Attribution + strconv.Itoa(treeNode.Serial) + "-"
  236. folder.ParentId = IdInt
  237. }
  238. folder.ProjectId = ProjectId
  239. folder.Serial = serial
  240. folder.Depth = depth
  241. folder.Isfolder = 1
  242. folder.CreateTime = time.Now()
  243. folder.UpdateTime = time.Now()
  244. folder.ContractsIncome = "0"
  245. folder.ContractsPaid = "0"
  246. folder.ContractsPay = "0"
  247. folder.ContractsReturned = "0"
  248. err = s.dao.Create(&folder)
  249. if err != nil {
  250. log.Println("添加目录出错, error=", err)
  251. return errors.New("添加目录出错")
  252. }
  253. return nil
  254. }
  255. // 重命名
  256. func (s *treeService) Rename(data viewmodels.Tree, projectId int) error {
  257. // 获得该目录ID
  258. Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
  259. if err != nil {
  260. return err
  261. }
  262. IdInt, err1 := strconv.Atoi(Id)
  263. if err1 != nil {
  264. return err1
  265. }
  266. // 获得树信息
  267. treeData := s.dao.Get(IdInt, projectId)
  268. if treeData.Id == 0 {
  269. return errors.New("修改的目录不合法")
  270. }
  271. treeNode := models.CmTree{}
  272. treeNode.Id = IdInt
  273. treeNode.Name = data.Name
  274. if treeData.Isfolder == 1 {
  275. // 目录
  276. err = s.dao.Update(&treeNode, []string{"Name"})
  277. } else {
  278. // 标段
  279. treeNode.BidsectionId = treeData.BidsectionId
  280. err = s.dao.Rename(&treeNode, []string{"Name"})
  281. }
  282. if err != nil {
  283. return err
  284. }
  285. return nil
  286. }
  287. // 获得该目录下所有的目录和标段
  288. func (s *treeService) GetFolderAndBid(id int, projectId int) ([]models.CmTree, error) {
  289. // 获得该目录ID
  290. // id, err := comm.AesDecrypt(id, conf.SignSecret)
  291. // if err != nil {
  292. // return nil, errors.New("目录解析错误")
  293. // }
  294. // IdInt, err := strconv.Atoi(id)
  295. // if err != nil {
  296. // return nil, errors.New("目录解析错误")
  297. // }
  298. // 获得该目录下所有数据
  299. folder := s.dao.Get(id, projectId)
  300. if folder.Id == 0 {
  301. return nil, errors.New("目录不合法")
  302. }
  303. attribution := fmt.Sprintf("%s%d-", folder.Attribution, folder.Serial)
  304. // 获得目录归属
  305. dataList := s.dao.GetFolderAndBid(folder.ProjectId, attribution)
  306. return dataList, nil
  307. }
  308. // 删除该目录和所属的目录和标段
  309. func (s *treeService) DeleteFolderAndBid(id int, projectId int) error {
  310. // 获得该目录ID
  311. // id, err := comm.AesDecrypt(id, conf.SignSecret)
  312. // if err != nil {
  313. // return errors.New("目录解析错误")
  314. // }
  315. // IdInt, err := strconv.Atoi(id)
  316. // if err != nil {
  317. // return errors.New("目录解析错误")
  318. // }
  319. // 获得该目录下 归属关系
  320. folder := s.dao.Get(id, projectId)
  321. if folder.Id == 0 {
  322. return errors.New("目录不合法")
  323. }
  324. attribution := fmt.Sprintf("%s%d-", folder.Attribution, folder.Serial)
  325. // --逻辑删除 目录和数据
  326. err := s.dao.DeleteFolderAndBid(folder.Id, folder.ProjectId, attribution)
  327. if err != nil {
  328. return err
  329. }
  330. // TODO -加入堆栈 物理删除数据
  331. return nil
  332. }
  333. // 移动目录
  334. func (s *treeService) Move(id int, moveId int, projectId int) error {
  335. // 获得项目目录
  336. treeNode := s.dao.Get(id, projectId)
  337. if treeNode.Id == 0 {
  338. return errors.New("目录或标段解析错误")
  339. }
  340. targetFolder := &models.CmTree{}
  341. // id为0是跟目录
  342. if moveId == 0 {
  343. // id
  344. targetFolder.Id = 0
  345. // 1.获得最大序号
  346. // seriallist := s.dao.GetALLDepthByAttribution(0, projectId, "")
  347. // maxIndex := len(seriallist)
  348. // serial := 0
  349. // if maxIndex != 0 {
  350. // serial = seriallist[maxIndex-1].Serial + 1
  351. // }
  352. // targetFolder.Serial = serial
  353. targetFolder.Serial = 0
  354. // 2.归属
  355. targetFolder.Attribution = ""
  356. // 3.深度depth-根目录为-1
  357. targetFolder.Depth = -1
  358. // 4.为目录
  359. targetFolder.Isfolder = 1
  360. // 5.项目ID
  361. targetFolder.ProjectId = projectId
  362. // fmt.Println(targetFolder)
  363. // if targetFolder.Id == 0 {
  364. // return errors.New("目录解析错误-测试")
  365. // }
  366. } else {
  367. targetFolder = s.dao.Get(moveId, projectId)
  368. if targetFolder.Id == 0 {
  369. return errors.New("目录解析错误")
  370. }
  371. }
  372. // 目录必须是目录
  373. if targetFolder.Isfolder == 0 {
  374. return errors.New("目标不是文件夹")
  375. }
  376. // 目录的目标不能是自己
  377. if id == moveId {
  378. return errors.New("目标目录是原目录-不能移动")
  379. }
  380. // 移动的是目录
  381. if treeNode.Isfolder == 1 {
  382. // 1.目录下不能有标段
  383. // 被移动的目录存在标段
  384. moveBidList := s.dao.GetBidsection(moveId)
  385. if len(moveBidList) > 0 {
  386. return errors.New("该目录中存在标段,不能移动")
  387. }
  388. } else {
  389. // 标段
  390. // 1.移动的目录是否为叶子节点
  391. moveBidList := s.dao.GetChildFolder(moveId)
  392. if len(moveBidList) > 0 {
  393. return errors.New("该目录中存在其他目录,不能移动")
  394. }
  395. }
  396. err := s.dao.Move(treeNode, targetFolder)
  397. if err != nil {
  398. return err
  399. }
  400. return nil
  401. }
  402. // 创建一颗树...interface{}
  403. func maketree(Data []*viewmodels.Tree, node *viewmodels.Tree) { //参数为父节点,添加父节点的子节点指针切片
  404. childs, _ := havechild(Data, node) //判断节点是否有子节点并返回
  405. if childs != nil {
  406. // fmt.Printf("\n")
  407. // fmt.Println(*node)
  408. // fmt.Println("子节点:")
  409. // for _, v := range childs {
  410. // fmt.Println(*v)
  411. // } //打印
  412. // 子节点总数
  413. Total := len(childs)
  414. node.ChildsTotal = Total
  415. // 标记最后一个元素
  416. end := Total - 1
  417. childs[end].IsEnd = true
  418. // 往父节点添加子节点
  419. node.Children = append(node.Children, childs[0:]...) //添加子节点
  420. for _, v := range childs { //查询子节点的子节点,并添加到子节点
  421. _, has := havechild(Data, v)
  422. if has {
  423. // 递归添加节点
  424. maketree(Data, v)
  425. }
  426. // else {
  427. // // 叶子节点
  428. // node.Leaf = false
  429. // }
  430. // 目录下是否包含标段
  431. if v.Isfolder == 0 {
  432. node.IsBid = true
  433. } else {
  434. node.HasFolder = true
  435. }
  436. }
  437. }
  438. }
  439. // 是否有子树
  440. func havechild(Data []*viewmodels.Tree, node *viewmodels.Tree) (child []*viewmodels.Tree, yes bool) {
  441. for _, v := range Data {
  442. if v.ParentId == node.Id {
  443. child = append(child, v)
  444. }
  445. }
  446. if child != nil {
  447. yes = true
  448. }
  449. return
  450. }
  451. func transformjson(Data *viewmodels.Tree) { //转为json
  452. Jsondata, _ := json.Marshal(Data)
  453. fmt.Println(string(Jsondata))
  454. }
  455. //now := comm.NowUnix()
  456. //comm.FormatFromUnixTime(now)
  457. // ParentIdInt := 0
  458. // if data.ParentId != "" {
  459. // ParentId, err := comm.AesDecrypt(data.ParentId, conf.SignSecret)
  460. // if err != nil {
  461. // return err
  462. // }
  463. // ParentIdInt, err = strconv.Atoi(ParentId)
  464. // if err != nil {
  465. // ParentIdInt = 0
  466. // }
  467. // }