tree_service.go 15 KB

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