Parcourir la source

项目相关接口

caipin il y a 4 ans
Parent
commit
ecc8653e15

+ 39 - 6
bootstrap/bootstrap.go

@@ -9,7 +9,6 @@ package bootstrap
 import (
 	"time"
 
-	"github.com/iris-contrib/middleware/csrf"
 	"github.com/kataras/iris/v12"
 	"github.com/kataras/iris/v12/middleware/logger"
 	"github.com/kataras/iris/v12/middleware/recover"
@@ -64,10 +63,41 @@ func (b *Bootstrapper) SetupViews(viewsDir string) {
 	b.RegisterView(htmlEngine)
 }
 
-func (b *Bootstrapper) SetupCsrfHandlers(csrfKey string) {
-	protect := csrf.Protect([]byte(csrfKey), csrf.FieldName("csrf"))
-	csrf.Secure(false)
-	b.Party("/", protect)
+// 配置csrf
+// func (b *Bootstrapper) SetupCsrfHandlers(csrfKey string) {
+// 	protect := csrf.Protect([]byte(csrfKey), csrf.FieldName("csrf"), csrf.Secure(false))
+// 	//csrf.Domain("")
+
+// 	b.Party("/", protect)
+// }
+
+// 配置jwt
+func (b *Bootstrapper) SetupJwtHandlers(jwtKey string) {
+
+	// j2 := jwt.New(jwt.Config{
+	// 	// 注意,新增了一个错误处理函数
+	// 	ErrorHandler: func(ctx iris.Context, err error) {
+	// 		if err == nil {
+	// 			return
+	// 		}
+
+	// 		ctx.StopExecution()
+	// 		ctx.StatusCode(iris.StatusUnauthorized)
+	// 		ctx.JSON(ResModel{
+	// 			Code: "501",
+	// 			Msg:  err.Error(),
+	// 		})
+	// 	},
+	// 	// 设置一个函数返回秘钥,关键在于return []byte("这里设置秘钥")
+	// 	ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
+	// 		return []byte(jwtKey), nil
+	// 	},
+
+	// 	// 设置一个加密方法
+	// 	SigningMethod: jwt.SigningMethodHS256,
+	// })
+
+	//b.Party("/", j2.Serve)
 }
 
 //处理异常--设置错误信息展示
@@ -108,6 +138,7 @@ const (
 	//20200902GCJSXM7C084477AEA06096F5
 	//9AB0F421E53A477C084477AEA06096F5
 	CsrfKey = "9AB0F421E53A477C084477AEA06096F5"
+	JwtKey  = "9AB0F421E53A477C084477AEA06096F5"
 )
 
 // 初始化Bootstrap
@@ -120,7 +151,9 @@ func (b *Bootstrapper) Bootstrap() *Bootstrapper {
 	// 	[]byte("lot-secret-of-characters-big-too"),
 	// )
 	// 设置csrf
-	b.SetupCsrfHandlers(CsrfKey)
+	//b.SetupCsrfHandlers(CsrfKey)
+	// 设置jwt
+	b.SetupJwtHandlers(JwtKey)
 	//设置异常信息
 	b.SetupErrorHandlers()
 

+ 0 - 3
conf/project.go

@@ -25,9 +25,6 @@ const UserPrizeMax = 3000 // 用户每天最多抽奖次数
 
 // 定义24小时的奖品分配权重
 var PrizeDataRandomDayTime = [100]int{
-	// 24 * 3 = 72   平均3%的机会
-	// 100 - 72 = 28 剩余28%的机会
-	// 7 * 4 = 28    剩下的分别给7个时段增加4%的机会
 	0, 0, 0,
 	1, 1, 1,
 	2, 2, 2,

+ 21 - 4
dao/project_dao.go

@@ -7,6 +7,8 @@
 package dao
 
 import (
+	"fmt"
+
 	"github.com/go-xorm/xorm"
 	"go.mod/models"
 )
@@ -24,14 +26,29 @@ func NewProjectDao(engine *xorm.Engine) *ProjectDao {
 }
 
 //CmProjectAccount 设置的值获得数据
-func (d *ProjectDao) GetOne(data *models.CmProject) *models.CmProject {
+func (d *ProjectDao) Get(data *models.CmProject) {
 	//data := data
-	//Get取到值后,会自动赋值到data中
 	ok, err := d.engine.Get(data)
 	if ok && err == nil {
-		return data
+		//return nil
 	} else {
 		data.Id = 0
-		return data
+		//return err
+	}
+}
+
+// 获得一组项目数据
+func (d *ProjectDao) GetListByCode(code string) []models.CmProject {
+	datalist := make([]models.CmProject, 0)
+
+	err := d.engine.
+		Where("code like ?", code+"%").
+		Desc("id").
+		Find(&datalist)
+	fmt.Println(datalist)
+	if err != nil {
+		return datalist
+	} else {
+		return datalist
 	}
 }

+ 93 - 0
dao/tree_dao.go

@@ -0,0 +1,93 @@
+/*
+ * @description: 树结构数据库操作相关
+ * @Author: CP
+ * @Date: 2020-09-11 14:49:27
+ * @FilePath: \construction_management\dao\tree_dao.go
+ */
+package dao
+
+import (
+	"github.com/go-xorm/xorm"
+	"go.mod/models"
+)
+
+//数据库操作引擎
+type TreeDao struct {
+	engine *xorm.Engine
+}
+
+//获得一个DAO对象
+func NewTreeDao(engine *xorm.Engine) *TreeDao {
+	return &TreeDao{
+		engine: engine,
+	}
+}
+
+//id获得数据
+func (d *TreeDao) Get(id int) *models.CmTree {
+	data := &models.CmTree{Id: id}
+	//Get取到值后,会自动赋值到data中
+	ok, err := d.engine.Get(data)
+	if ok && err == nil {
+		return data
+	} else {
+		data.Id = 0
+		return data
+	}
+}
+
+func (d *TreeDao) GetBidsection(id int) []models.CmTree {
+	datalist := make([]models.CmTree, 0)
+	err := d.engine.
+		Asc("serial").
+		Where("parent_id=? and isfolder=0", id).
+		Find(&datalist)
+
+	if err != nil {
+		return datalist
+	} else {
+		return datalist
+	}
+}
+
+// 获得某一深度的 结构数据(不包含子集) 正序
+func (d *TreeDao) GetAllDepth(depth int, projectId int) []models.CmTree {
+	datalist := make([]models.CmTree, 0)
+	err := d.engine.
+		Asc("serial").
+		Where("depth=? and project_id=?", depth, projectId).
+		Find(&datalist)
+
+	if err != nil {
+		return datalist
+	} else {
+		return datalist
+	}
+}
+
+// 获得项目文件夹
+func (d *TreeDao) GetAllTree(projectId int) []models.CmTree {
+	datalist := make([]models.CmTree, 0)
+	err := d.engine.
+		Asc("id").
+		Where("project_id=?", projectId).
+		Find(&datalist)
+
+	if err != nil {
+		return datalist
+	} else {
+		return datalist
+	}
+}
+
+//创建
+func (d *TreeDao) Create(data *models.CmTree) error {
+	_, err := d.engine.Insert(data)
+	return err
+}
+
+// 更新
+func (d *TreeDao) Update(data *models.CmTree, columns []string) error {
+	_, err := d.engine.Id(data.Id).MustCols(columns...).Update(data)
+	return err
+}

+ 7 - 0
models/PDMAN_DB_VERSION.go

@@ -0,0 +1,7 @@
+package models
+
+type PdmanDbVersion struct {
+	DbVersion   string `xorm:"VARCHAR(256)"`
+	VersionDesc string `xorm:"VARCHAR(1024)"`
+	CreatedTime string `xorm:"VARCHAR(32)"`
+}

+ 12 - 0
models/cm_log.go

@@ -0,0 +1,12 @@
+package models
+
+type CmLog struct {
+	Id         int    `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
+	Operator   string `xorm:"comment('操作者') VARCHAR(32)"`
+	CreateTime int    `xorm:"comment('操作时间') INT(11)"`
+	Controller string `xorm:"comment('操作的控制器名称') VARCHAR(32)"`
+	Action     string `xorm:"comment('操作的action名称') VARCHAR(32)"`
+	Operation  string `xorm:"comment('操作内容') VARCHAR(32)"`
+	Type       int    `xorm:"comment('日志类型 1为操作日志') TINYINT(1)"`
+	TargetId   int    `xorm:"comment('操作的id') INT(11)"`
+}

+ 19 - 0
models/cm_message.go

@@ -0,0 +1,19 @@
+package models
+
+import (
+	"time"
+)
+
+type CmMessage struct {
+	Id          int       `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
+	Title       string    `xorm:"comment('消息标题') VARCHAR(255)"`
+	Content     string    `xorm:"comment('消息内容') TEXT"`
+	CreateTime  string    `xorm:"comment('创建时间') VARCHAR(32)"`
+	CreateUid   int       `xorm:"comment('创建者id') INT(11)"`
+	ProjectId   int       `xorm:"comment('项目id,针对项目通知') INT(11)"`
+	Creator     int       `xorm:"comment('创建者') INT(11)"`
+	Type        int       `xorm:"comment('消息类型 1为项目 2为系统') TINYINT(1)"`
+	Status      int       `xorm:"comment('消息状态,1:已发布,2:未发布') TINYINT(1)"`
+	ReleaseTime int       `xorm:"comment('发布时间') INT(11)"`
+	Istop       time.Time `xorm:"not null default 'CURRENT_TIMESTAMP' comment('是否置顶,0为非置顶,时间戳为置顶时间') TIMESTAMP"`
+}

+ 1 - 1
models/cm_permission.go

@@ -1,7 +1,7 @@
 package models
 
 type CmPermission struct {
-	Id         int    `xorm:"not null pk INT(11)"`
+	Id         int    `xorm:"not null pk autoincr INT(11)"`
 	Name       string `xorm:"not null comment('权限名称') VARCHAR(32)"`
 	Controller string `xorm:"comment('控制器名称') VARCHAR(32)"`
 	Action     string `xorm:"comment('action名称') VARCHAR(32)"`

+ 19 - 0
models/cm_tree.go

@@ -0,0 +1,19 @@
+package models
+
+import (
+	"time"
+)
+
+type CmTree struct {
+	Id          int       `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
+	Name        string    `xorm:"not null comment('名称') VARCHAR(64)"`
+	ProjectId   int       `xorm:"not null default 0 comment('项目ID') INT(11)"`
+	Depth       int       `xorm:"not null default 0 comment('深度') TINYINT(4)"`
+	Serial      int       `xorm:"not null default 0 comment('序号') TINYINT(4)"`
+	Attribution string    `xorm:"comment('归属') VARCHAR(32)"`
+	Isfolder    int       `xorm:"not null default 1 comment('是否文件夹 1文件夹 0其他') TINYINT(1)"`
+	TenderId    int       `xorm:"comment('标段ID') INT(11)"`
+	ParentId    int       `xorm:"not null default 0 comment('父级ID') INT(11)"`
+	CreateTime  time.Time `xorm:"comment('创建时间') DATETIME"`
+	UpdateTime  time.Time `xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"`
+}

+ 12 - 0
models/cm_version.go

@@ -0,0 +1,12 @@
+package models
+
+import (
+	"time"
+)
+
+type CmVersion struct {
+	Id         int       `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
+	Name       string    `xorm:"comment('版本号') VARCHAR(255)"`
+	CreateTime time.Time `xorm:"comment('创建时间') DATETIME"`
+	Content    string    `xorm:"TEXT"`
+}

+ 11 - 0
models/cm_white_list.go

@@ -0,0 +1,11 @@
+package models
+
+type CmWhiteList struct {
+	Id         int    `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
+	Ip         string `xorm:"comment('ip地址') VARCHAR(32)"`
+	Type       int    `xorm:"comment('白名单类型 1为后台访问限制 2为接口访问限制') TINYINT(1)"`
+	Enable     int    `xorm:"comment('是否启用 0为禁用') TINYINT(1)"`
+	Token      string `xorm:"comment('接口访问token') VARCHAR(32)"`
+	CreateTime int    `xorm:"comment('创建时间') INT(11)"`
+	Remark     string `xorm:"comment('备注') VARCHAR(32)"`
+}

+ 0 - 115
services/folder_service.go

@@ -1,115 +0,0 @@
-/*
- * @description:层级文件夹数据操作相关
- * @Author: CP
- * @Date: 2020-09-11 14:43:58
- * @FilePath: \construction_management\services\folder_service.go
- */
-package services
-
-import (
-	"log"
-	"strconv"
-	"time"
-
-	"github.com/kataras/iris/v12"
-	"go.mod/comm"
-	"go.mod/conf"
-	"go.mod/dao"
-	"go.mod/datasource"
-	"go.mod/models"
-	"go.mod/web/viewmodels"
-)
-
-//定义项目Service接口
-type FoldertService interface {
-	//ValidManager(code string, account string, password string) error
-	ValidRule(ctx iris.Context) (viewmodels.Folder, error)
-	Create(data viewmodels.Folder) error
-	GetAllProject(int) []viewmodels.Folder
-}
-
-//返回service操作类
-type foldertService struct {
-	dao *dao.FolderDao
-}
-
-//创建项目service
-func NewFoldertService() FoldertService {
-	return &foldertService{
-		dao: dao.NewFolderDao(datasource.InstanceDbMaster()),
-	}
-}
-
-// 文件夹规则验证
-func (s *foldertService) ValidRule(ctx iris.Context) (viewmodels.Folder, error) {
-	folderVaild := viewmodels.Folder{}
-	err := ctx.ReadForm(&folderVaild)
-	if err != nil {
-		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
-		return folderVaild, err
-	}
-
-	err = folderVaild.Validate()
-	if err != nil {
-		log.Println("文件夹验证, error=", err)
-		return folderVaild, err
-	}
-
-	return folderVaild, nil
-}
-
-// 获得项目文件夹相关
-func (s *foldertService) GetAllProject(projectId int) []viewmodels.Folder {
-
-	datalist := s.dao.GetAllProject(projectId)
-	folderlist := make([]viewmodels.Folder, 0)
-
-	for _, data := range datalist {
-		folder := viewmodels.Folder{}
-		//folder.Id = comm.Encrypt([]byte(conf.SignSecret), []byte(strconv.Itoa(data.Id)))
-		id, _ := comm.AesEncrypt(strconv.Itoa(data.Id), conf.SignSecret)
-		parentId, _ := comm.AesEncrypt(strconv.Itoa(data.ParentId), conf.SignSecret)
-		projectId, _ := comm.AesEncrypt(strconv.Itoa(data.ProjectId), conf.SignSecret)
-		folder.Id = id
-		folder.Name = data.Name
-		folder.ParentId = parentId
-		folder.ProjectId = projectId
-		folderlist = append(folderlist, folder)
-	}
-
-	return folderlist
-}
-
-// 新增一个文件夹
-func (s *foldertService) Create(data viewmodels.Folder) error {
-	//now := comm.NowUnix()
-	//comm.FormatFromUnixTime(now)
-	folder := models.CmFolder{}
-	folder.Name = data.Name
-	ProjectId, err := strconv.Atoi(data.ProjectId)
-	if err != nil {
-		return err
-	}
-
-	ParentIdInt := 0
-	if data.ParentId != "" {
-		ParentId, err := comm.AesDecrypt(data.ParentId, conf.SignSecret)
-		if err != nil {
-			return err
-		}
-		ParentIdInt, err = strconv.Atoi(ParentId)
-		if err != nil {
-			ParentIdInt = 0
-		}
-	}
-
-	folder.ProjectId = ProjectId
-	folder.ParentId = ParentIdInt
-	folder.CreateTime = time.Now()
-	folder.UpdateTime = time.Now()
-	err = s.dao.Create(&folder)
-	if err != nil {
-		return err
-	}
-	return nil
-}

+ 51 - 10
services/login_service.go

@@ -8,11 +8,13 @@ package services
 
 import (
 	"errors"
+	"fmt"
 	"log"
 	"net/http"
-	"net/url"
 	"strconv"
+	"time"
 
+	"github.com/iris-contrib/middleware/jwt"
 	"github.com/kataras/iris/v12"
 	"go.mod/comm"
 	"go.mod/conf"
@@ -46,7 +48,8 @@ func NewLoginService() LoginService {
 // 登陆验证
 func (s *loginService) ValidRule(ctx iris.Context) (viewmodels.Login, error) {
 	loginVaild := viewmodels.Login{}
-	err := ctx.ReadForm(&loginVaild)
+	err := ctx.ReadJSON(&loginVaild)
+	fmt.Println(loginVaild)
 	if err != nil {
 		log.Println("ReadForm转换异常, error=", err)
 		return loginVaild, err
@@ -65,7 +68,7 @@ func (s *loginService) ValidProjectAccount(loginData viewmodels.Login, writer ht
 	projectInfo := models.CmProject{}
 	// 工程项目是否存在
 	projectInfo.Code = loginData.Code
-	s.projectDao.GetOne(&projectInfo)
+	s.projectDao.Get(&projectInfo)
 	if projectInfo.Id == 0 {
 		return errors.New("工程建设管理员还未创建拉取项目,禁止登录")
 	}
@@ -80,25 +83,63 @@ func (s *loginService) ValidProjectAccount(loginData viewmodels.Login, writer ht
 	if err != nil {
 		return err
 	}
-	// 加密用户标识 生成数字证书
+
+	// 加密用户标识
 	identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
 	if err != nil {
 		return err
 	}
-	digitalToken := comm.CreateSign(conf.CookieSecret + strconv.Itoa(projectAccountInfo.Id))
+	// 加密项目标识
+	projectId, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.ProjectId), conf.CookieSecret)
+	if err != nil {
+		return err
+	}
+	// jwt token
+	token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
+		// 根据需求,可以存一些必要的数据
+		"identity": identity,
+		"project":  projectId,
+		// 签发人
+		"iss": "cm",
+		// 签发时间
+		"iat": time.Now().Unix(),
+		// 设定过期时间,便于测试,设置1分钟过期
+		"exp": time.Now().Add(72 * time.Hour * time.Duration(1)).Unix(),
+	})
 
-	// 设置cookie
+	// 使用设置的秘钥,签名生成jwt字符串
+	tokenString, _ := token.SignedString([]byte(conf.SignSecret))
+	fmt.Println(tokenString)
 	maxAge := 60 * 60 * 24 * 7
-	params := url.Values{}
-	params.Add("identity", identity)
-	params.Add("digitalToken", digitalToken)
+	// params := url.Values{}
+	// params.Add("token", tokenString)
 	c := &http.Cookie{
 		Name:   "cm",
-		Value:  params.Encode(),
+		Value:  tokenString, //params.Encode(),
 		Path:   "/",
 		MaxAge: maxAge,
 	}
 	http.SetCookie(writer, c)
+
+	// // 加密用户标识 生成数字证书
+	// identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
+	// if err != nil {
+	// 	return err
+	// }
+	// digitalToken := comm.CreateSign(conf.CookieSecret + strconv.Itoa(projectAccountInfo.Id))
+
+	// // 设置cookie
+	// maxAge := 60 * 60 * 24 * 7
+	// params := url.Values{}
+	// params.Add("identity", identity)
+	// params.Add("digitalToken", digitalToken)
+	// c := &http.Cookie{
+	// 	Name:   "cm",
+	// 	Value:  params.Encode(),
+	// 	Path:   "/",
+	// 	MaxAge: maxAge,
+	// }
+	// http.SetCookie(writer, c)
 	// TODO--分布式会话--后续需要在加入
 
 	return nil

+ 1 - 1
services/project_account_service.go

@@ -23,7 +23,7 @@ import (
 //定义项目用户Service接口
 type ProjectAccountService interface {
 	ValidRule(ctx iris.Context) (viewmodels.ProjectAccount, error)
-	Save(viewAccount viewmodels.ProjectAccount, in int) error
+	Save(viewAccount viewmodels.ProjectAccount, id int) error
 	Get(id int) *viewmodels.ProjectAccount
 }
 

+ 98 - 0
services/project_service.go

@@ -7,13 +7,24 @@
 package services
 
 import (
+	"log"
+	"strconv"
+
+	"github.com/kataras/iris/v12"
+	"go.mod/comm"
+	"go.mod/conf"
 	"go.mod/dao"
 	"go.mod/datasource"
+	"go.mod/models"
+	"go.mod/web/viewmodels"
 )
 
 //定义项目Service接口
 type ProjectService interface {
 	//ValidManager(code string, account string, password string) error
+	ValidRule(iris.Context) (viewmodels.Project, error)
+	Get(*viewmodels.Project)
+	GetList(viewmodels.Project) []viewmodels.Project
 }
 
 //返回service操作类
@@ -27,3 +38,90 @@ func NewProjectService() ProjectService {
 		dao: dao.NewProjectDao(datasource.InstanceDbMaster()),
 	}
 }
+
+// 验证项目项的内容
+func (s *projectService) ValidRule(ctx iris.Context) (viewmodels.Project, error) {
+	projectVaild := viewmodels.Project{}
+	err := ctx.ReadForm(&projectVaild)
+	if err != nil {
+		log.Println("project-ValidRule-ReadForm转换异常, error=", err)
+		return projectVaild, err
+	}
+
+	err = projectVaild.Validate()
+	if err != nil {
+		log.Println("项目信息验证, error=", err)
+		return projectVaild, err
+	}
+
+	return projectVaild, nil
+}
+
+// 获得单个项目信息-ID 编号
+func (s *projectService) Get(projectVM *viewmodels.Project) {
+	projectCM := models.CmProject{}
+
+	// 项目ID或编号
+	if projectVM.Id == "" && projectVM.Code == "" {
+		projectVM.Id = "0"
+		return
+		//return errors.New("项目ID或者项目编号不存在")
+	}
+
+	if projectVM.Id != "" {
+		projectId, err := comm.AesDecrypt(projectVM.Id, conf.SignSecret)
+		if err != nil {
+			projectVM.Id = "0"
+			return
+		}
+		projectIdInt, err := strconv.Atoi(projectId)
+		if err != nil {
+			projectVM.Id = "0"
+			return
+		}
+		if projectIdInt != 0 {
+			projectCM.Id = projectIdInt
+		}
+	} else if projectVM.Code != "" {
+		projectCM.Code = projectVM.Code
+	} else {
+		projectVM.Id = "0"
+		return
+	}
+
+	s.dao.Get(&projectCM)
+	if projectCM.Id != 0 {
+		// 项目信息补充完整
+		projectB := makeProjectVM(projectCM)
+		projectVM = &projectB
+	} else {
+		projectVM.Id = "0"
+		return
+	}
+}
+
+// 获得一组项目信息 -项目编号
+func (s *projectService) GetList(projectVM viewmodels.Project) []viewmodels.Project {
+	datalist := make([]viewmodels.Project, 0)
+	// 项目编号
+	if projectVM.Code != "" {
+
+		projectData := s.dao.GetListByCode(projectVM.Code)
+		for _, data := range projectData {
+			projectVM = makeProjectVM(data)
+			datalist = append(datalist, projectVM)
+		}
+		return datalist
+	}
+	return datalist
+}
+
+// 构造视图层models
+func makeProjectVM(projectCM models.CmProject) viewmodels.Project {
+	projectVM := viewmodels.Project{}
+	id, _ := comm.AesEncrypt(strconv.Itoa(projectCM.Id), conf.SignSecret)
+	projectVM.Id = id
+	projectVM.Code = projectCM.Code
+	projectVM.Name = projectCM.Name
+	return projectVM
+}

+ 250 - 0
services/tree_service.go

@@ -0,0 +1,250 @@
+/*
+ * @description:层级文件夹数据操作相关
+ * @Author: CP
+ * @Date: 2020-09-11 14:43:58
+ * @FilePath: \construction_management\services\tree_service.go
+ */
+package services
+
+import (
+	"encoding/json"
+	"errors"
+	"fmt"
+	"log"
+	"strconv"
+	"time"
+
+	"github.com/kataras/iris/v12"
+	"go.mod/comm"
+	"go.mod/conf"
+	"go.mod/dao"
+	"go.mod/datasource"
+	"go.mod/models"
+	"go.mod/web/viewmodels"
+)
+
+//定义项目Service接口
+type TreeService interface {
+	//ValidManager(code string, account string, password string) error
+	ValidRule(ctx iris.Context) (viewmodels.Tree, error)
+	Create(data viewmodels.Tree) error
+	GetAllProject(int) *viewmodels.Tree
+	Rename(data viewmodels.Tree) error
+}
+
+//返回service操作类
+type foldertService struct {
+	dao *dao.TreeDao
+}
+
+//创建项目service
+func NewTreeService() TreeService {
+	return &foldertService{
+		dao: dao.NewTreeDao(datasource.InstanceDbMaster()),
+	}
+}
+
+// 文件夹规则验证
+func (s *foldertService) ValidRule(ctx iris.Context) (viewmodels.Tree, error) {
+	folderVaild := viewmodels.Tree{}
+	err := ctx.ReadForm(&folderVaild)
+	if err != nil {
+		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
+		return folderVaild, err
+	}
+
+	err = folderVaild.Validate()
+	if err != nil {
+		log.Println("文件夹验证, error=", err)
+		return folderVaild, err
+	}
+
+	return folderVaild, nil
+}
+
+// 获得项目文件夹相关
+func (s *foldertService) GetAllProject(projectId int) *viewmodels.Tree {
+
+	datalist := s.dao.GetAllTree(projectId)
+	folderlist := make([]viewmodels.Tree, 0)
+	// 生成根
+	folder := viewmodels.Tree{}
+	id, _ := comm.AesEncrypt(strconv.Itoa(0), conf.SignSecret)
+	parentId, _ := comm.AesEncrypt(strconv.Itoa(-1), conf.SignSecret)
+	folder.Id = id
+	folder.Name = "root"
+	folder.ParentId = parentId
+	folderlist = append(folderlist, folder)
+	// 加入数据
+	for _, data := range datalist {
+		folder := viewmodels.Tree{}
+		//folder.Id = comm.Encrypt([]byte(conf.SignSecret), []byte(strconv.Itoa(data.Id)))
+		id, _ := comm.AesEncrypt(strconv.Itoa(data.Id), conf.SignSecret)
+		parentId, _ := comm.AesEncrypt(strconv.Itoa(data.ParentId), conf.SignSecret)
+		projectId, _ := comm.AesEncrypt(strconv.Itoa(data.ProjectId), conf.SignSecret)
+		serial, _ := comm.AesEncrypt(strconv.Itoa(data.Serial), conf.SignSecret)
+		folder.Id = id
+		folder.Name = data.Name
+		folder.ParentId = parentId
+		folder.ProjectId = projectId
+		folder.Depth = data.Depth + 1
+		folder.Serial = serial
+		folder.Leaf = true
+		folder.CreateTime = data.CreateTime.Format(conf.SysTimeform)
+		folderlist = append(folderlist, folder)
+	}
+
+	var data []*viewmodels.Tree
+	data = make([]*viewmodels.Tree, 0)
+	for i, _ := range folderlist {
+		var a *viewmodels.Tree
+		a = &folderlist[i]
+		data = append(data, a)
+	}
+
+	node := &folderlist[0] //父节点
+	maketree(data, node)   //调用生成tree
+	//transformjson(node)    //转化为json
+	return node
+}
+
+// 新增一个文件夹
+func (s *foldertService) Create(data viewmodels.Tree) error {
+	// 类型校验
+	folder := models.CmTree{}
+	folder.Name = data.Name
+	ProjectId, err := strconv.Atoi(data.ProjectId)
+	if err != nil {
+		return err
+	}
+
+	// 获得该目录ID
+	Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
+	if err != nil {
+		return err
+	}
+	IdInt, err1 := strconv.Atoi(Id)
+	if err1 != nil {
+		return err1
+	}
+
+	// 该目录中是否有标段
+	bidlist := s.dao.GetBidsection(IdInt)
+	if len(bidlist) > 0 {
+		return errors.New("该文件夹已存在标段,不能在新增目录")
+
+	}
+
+	// 获得该深度的文件夹最大序号
+	datalist := s.dao.GetAllDepth(data.Depth, ProjectId)
+	maxIndex := len(datalist)
+	serial := 0
+	if maxIndex != 0 {
+		serial = datalist[maxIndex-1].Serial + 1
+	}
+
+	// 设置归属
+	if data.Depth != 0 {
+		treeNode := s.dao.Get(IdInt)
+		if treeNode.Id == 0 {
+			return errors.New("上级目录不正确")
+		}
+
+		folder.Attribution = treeNode.Attribution + strconv.Itoa(treeNode.Serial) + "-"
+		folder.ParentId = IdInt
+	}
+
+	folder.ProjectId = ProjectId
+	folder.Serial = serial
+	folder.Depth = data.Depth
+	folder.Isfolder = 1
+	folder.CreateTime = time.Now()
+	folder.UpdateTime = time.Now()
+	err = s.dao.Create(&folder)
+	if err != nil {
+		return errors.New("添加目录出错")
+	}
+	return nil
+}
+
+// 重命名
+func (s *foldertService) Rename(data viewmodels.Tree) error {
+	// 获得该目录ID
+	Id, err := comm.AesDecrypt(data.Id, conf.SignSecret)
+	if err != nil {
+		return err
+	}
+	IdInt, err1 := strconv.Atoi(Id)
+	if err1 != nil {
+		return err1
+	}
+	// 装配需要更新的数据
+	folder := models.CmTree{}
+	folder.Id = IdInt
+	folder.Name = data.Name
+	err = s.dao.Update(&folder, []string{"Name"})
+	if err != nil {
+		return errors.New("目录重命名出错")
+	}
+	return nil
+}
+
+// 创建一颗树
+func maketree(Data []*viewmodels.Tree, node *viewmodels.Tree) { //参数为父节点,添加父节点的子节点指针切片
+	childs, _ := havechild(Data, node) //判断节点是否有子节点并返回
+	if childs != nil {
+		// fmt.Printf("\n")
+		// fmt.Println(*node)
+		// fmt.Println("子节点:")
+		// for _, v := range childs {
+		// 	fmt.Println(*v)
+		// } //打印
+
+		// 往父节点添加子节点
+		node.Children = append(node.Children, childs[0:]...) //添加子节点
+		for _, v := range childs {                           //查询子节点的子节点,并添加到子节点
+			_, has := havechild(Data, v)
+			if has {
+				// 递归添加节点
+				maketree(Data, v)
+			} else {
+				// 叶子节点
+				node.Leaf = false
+			}
+		}
+	}
+}
+
+// 是否有子树
+func havechild(Data []*viewmodels.Tree, node *viewmodels.Tree) (child []*viewmodels.Tree, yes bool) {
+	for _, v := range Data {
+		if v.ParentId == node.Id {
+			child = append(child, v)
+		}
+	}
+	if child != nil {
+		yes = true
+	}
+	return
+}
+
+func transformjson(Data *viewmodels.Tree) { //转为json
+
+	Jsondata, _ := json.Marshal(Data)
+
+	fmt.Println(string(Jsondata))
+}
+
+//now := comm.NowUnix()
+//comm.FormatFromUnixTime(now)
+// ParentIdInt := 0
+// if data.ParentId != "" {
+// 	ParentId, err := comm.AesDecrypt(data.ParentId, conf.SignSecret)
+// 	if err != nil {
+// 		return err
+// 	}
+// 	ParentIdInt, err = strconv.Atoi(ParentId)
+// 	if err != nil {
+// 		ParentIdInt = 0
+// 	}
+// }

+ 87 - 0
web/api/login_api.go

@@ -0,0 +1,87 @@
+/*
+ * @description: api 登陆接口相关
+ * @Author: CP
+ * @Date: 2020-09-17 16:23:02
+ * @FilePath: \construction_management\web\api\login_api.go
+ */
+package api
+
+import (
+	"fmt"
+
+	"github.com/kataras/iris/v12"
+	"go.mod/services"
+	"go.mod/web/utils"
+)
+
+type LoginApi struct {
+	//框架-web应用上下文环境
+	Ctx iris.Context
+	// 需要用的service
+	ServiceProjectAccount services.ProjectAccountService
+	ServiceLogin          services.LoginService
+}
+
+// func (c *LoginApi) Get() {
+// 	token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
+// 		// 根据需求,可以存一些必要的数据
+// 		"userName": "JabinGP",
+// 		"userId":   "1",
+// 		"admin":    true,
+
+// 		// 签发人
+// 		"iss": "iris",
+// 		// 签发时间
+// 		"iat": time.Now().Unix(),
+// 		// 设定过期时间,便于测试,设置1分钟过期
+// 		"exp": time.Now().Add(1 * time.Minute * time.Duration(1)).Unix(),
+// 	})
+
+// 	// 使用设置的秘钥,签名生成jwt字符串
+// 	tokenString, _ := token.SignedString([]byte(conf.SignSecret))
+
+// 	// 返回
+// 	c.Ctx.JSON(tokenString)
+// }
+
+//登陆
+func (c *LoginApi) Post() {
+	ErrMsg := ""
+	Code := -1
+	//验证规则
+	LoginData, err := c.ServiceLogin.ValidRule(c.Ctx)
+	if err != nil {
+		ErrMsg = utils.FormValidError(err)
+	} else {
+		//验证登陆用户
+		err = c.ServiceLogin.ValidProjectAccount(LoginData, c.Ctx.ResponseWriter())
+		if err != nil {
+			ErrMsg = fmt.Sprintf("%s", err)
+		} else {
+			//验证通关
+			Code = 0
+			// c.Ctx.JSON(iris.Map{
+			// 	"code": 200,
+			// 	"msg":  ErrMsg,
+			// })
+
+		}
+	}
+
+	c.Ctx.JSON(iris.Map{
+		"code": Code,
+		"msg":  ErrMsg,
+	})
+
+	// return mvc.View{
+	// 	Name: "login/login.html",
+	// 	Data: iris.Map{
+	// 		"Title":     "用户登录",
+	// 		"Channel":   "login",
+	// 		"Action":    "login",
+	// 		"LoginData": LoginData,
+	// 		"ErrMsg":    ErrMsg,
+	// 	},
+	// 	Layout: "login/layout.html",
+	// }
+}

+ 72 - 0
web/api/project_api.go

@@ -0,0 +1,72 @@
+/*
+ * @description: 项目相关 api
+ * @Author: CP
+ * @Date: 2020-09-23 09:46:21
+ * @FilePath: \construction_management\web\api\project_api.go
+ */
+package api
+
+import (
+	"github.com/kataras/iris/v12"
+	"go.mod/services"
+	"go.mod/web/viewmodels"
+)
+
+type ProjectApi struct {
+	//框架-web应用上下文环境
+	Ctx iris.Context
+	// 需要用的service
+	ServiceProject services.ProjectService
+}
+
+// 获得单个项目信息
+func (c *ProjectApi) Get() {
+	// 验证内容
+	ProjectData := viewmodels.Project{}
+	err := c.Ctx.ReadForm(&ProjectData)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{
+			"code": -1,
+			"msg":  "ReadForm转换异常",
+		})
+		return
+	} else {
+		// 获得项目信息
+		c.ServiceProject.Get(&ProjectData)
+		if ProjectData.Id == "0" {
+			c.Ctx.JSON(iris.Map{
+				"code": 0,
+				"msg":  "",
+				"data": nil,
+			})
+			return
+		}
+		c.Ctx.JSON(iris.Map{
+			"code": 0,
+			"msg":  "",
+			"data": ProjectData,
+		})
+	}
+}
+
+// 获得多个项目信息
+func (c *ProjectApi) GetList() {
+	// 验证内容
+	ProjectData := viewmodels.Project{}
+	err := c.Ctx.ReadForm(&ProjectData)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{
+			"code": -1,
+			"msg":  "ReadForm转换异常",
+		})
+		return
+	} else {
+		// 获得项目信息
+		dataList := c.ServiceProject.GetList(ProjectData)
+		c.Ctx.JSON(iris.Map{
+			"code": 0,
+			"msg":  "",
+			"data": dataList,
+		})
+	}
+}

+ 126 - 0
web/api/tree_api.go

@@ -0,0 +1,126 @@
+/*
+ * @description:
+ * @Author: CP
+ * @Date: 2020-09-17 17:50:50
+ * @FilePath: \construction_management\web\api\tree_api.go
+ */
+package api
+
+import (
+	"fmt"
+	"strconv"
+
+	"github.com/kataras/iris/v12"
+	"go.mod/services"
+	"go.mod/web/utils"
+)
+
+type TreeApi struct {
+	//框架-web应用上下文环境
+	Ctx iris.Context
+	// 需要用的service
+	ServiceProject services.ProjectService
+	ServiceTree    services.TreeService
+}
+
+// 获得项目目录结构
+func (c *TreeApi) Get() {
+
+	// 获得项目ID
+	projectIdInt, err := utils.GetProjectId(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{
+			"code": -1,
+			"msg":  err,
+		})
+		return
+	}
+
+	// 获得层级文件夹
+	FolderData := c.ServiceTree.GetAllProject(projectIdInt)
+
+	c.Ctx.JSON(iris.Map{
+		"code": 0,
+		"msg":  "",
+		"data": FolderData,
+	})
+}
+
+// 添加树结构
+func (c *TreeApi) PostCreate() {
+	ErrMsg := ""
+	// 验证内容
+	FolderData, err := c.ServiceTree.ValidRule(c.Ctx)
+	if err != nil {
+		ErrMsg = utils.FormValidError(err)
+		c.Ctx.JSON(iris.Map{
+			"code": -1,
+			"msg":  ErrMsg,
+		})
+		return
+	} else {
+
+		// 获得项目ID
+		projectIdInt, err := utils.GetProjectId(c.Ctx)
+		if err != nil {
+			c.Ctx.JSON(iris.Map{
+				"code": -1,
+				"msg":  fmt.Sprintf("%s", err),
+			})
+			return
+		}
+
+		FolderData.ProjectId = strconv.Itoa(projectIdInt)
+		// 新增文件夹
+		err = c.ServiceTree.Create(FolderData)
+		if err != nil {
+			c.Ctx.JSON(iris.Map{
+				"code": 3,
+				"msg":  fmt.Sprintf("%s", err),
+			})
+			return
+		}
+		c.Ctx.JSON(iris.Map{
+			"code": 0,
+			"msg":  "新增成功",
+		})
+	}
+}
+
+// 文件夹重命名
+func (c *TreeApi) PostRename() {
+	ErrMsg := ""
+	// 验证内容
+	FolderData, err := c.ServiceTree.ValidRule(c.Ctx)
+	if err != nil {
+		ErrMsg = utils.FormValidError(err)
+		c.Ctx.JSON(iris.Map{
+			"code": -1,
+			"msg":  ErrMsg,
+		})
+		return
+	} else {
+		// 新增文件夹
+		err = c.ServiceTree.Rename(FolderData)
+		if err != nil {
+			c.Ctx.JSON(iris.Map{
+				"code": 3,
+				"msg":  fmt.Sprintf("%s", err),
+			})
+			return
+		}
+		c.Ctx.JSON(iris.Map{
+			"code": 0,
+			"msg":  "重命名成功",
+		})
+	}
+}
+
+// 删除目录,需要删除树结构下的目录以及叶子
+func (c *TreeApi) DeleteDelete() {
+	// 获得需要删除数据
+
+	// 逻辑删除
+
+	// 加入删除任务堆栈,定时任务删除
+}

+ 20 - 0
web/controllers/api.go

@@ -0,0 +1,20 @@
+/*
+ * @description: API接口相关
+ * @Author: CP
+ * @Date: 2020-09-17 11:48:40
+ * @FilePath: \construction_management\web\controllers\api.go
+ */
+package controllers
+
+import (
+	"github.com/kataras/iris/v12"
+	"go.mod/services"
+)
+
+type ApiController struct {
+	//框架-web应用上下文环境
+	Ctx iris.Context
+	// 需要用的service
+	ServiceProject services.ProjectService
+	ServiceTree    services.TreeService
+}

+ 22 - 0
web/controllers/api_tree.go

@@ -0,0 +1,22 @@
+/*
+ * @description: 树接口相关
+ * @Author: CP
+ * @Date: 2020-09-17 15:00:25
+ * @FilePath: \construction_management\web\controllers\api_tree.go
+ */
+package controllers
+
+// 文件夹目录 树结构
+func (c *ApiController) GetTreeJson() {
+
+	// 获得层级文件夹
+	// projectId, err := c.Ctx.Values().GetInt("projectId")
+	// if err != nil {
+	// 	projectId = 0
+	// }
+
+	TreeData := c.ServiceTree.GetAllProject(23)
+	// Jsondata, _ := json.Marshal(TreeData)
+	// fmt.Println(string(Jsondata))
+	c.Ctx.JSON(TreeData) // or myjsonStruct{hello:"json}
+}

+ 3 - 0
web/controllers/login.go

@@ -33,6 +33,9 @@ func (c *LoginController) Get() mvc.Result {
 
 //登录页面
 func (c *LoginController) GetLogin() mvc.Result {
+
+	// r := c.Ctx.GetReferrer()
+	// fmt.Println(r)
 	errMsg := c.Ctx.URLParam("err")
 	return mvc.View{
 		Name: "login/login.html",

+ 1 - 1
web/controllers/project.go

@@ -17,7 +17,7 @@ type ProjectController struct {
 	Ctx iris.Context
 	// 需要用的service
 	ServiceProject services.ProjectService
-	ServiceFolder  services.FoldertService
+	ServiceTree    services.TreeService
 }
 
 // 项目信息设置

+ 2 - 2
web/controllers/project_bidsection.go

@@ -20,10 +20,10 @@ func (c *ProjectController) GetBidsectionManage() mvc.Result {
 		projectId = 0
 	}
 
-	FolderData := c.ServiceFolder.GetAllProject(projectId)
+	FolderData := c.ServiceTree.GetAllProject(projectId)
 	// 获得标段
 
-	// 层级文件夹
+	// 层级文件 
 
 	return mvc.View{
 		Name: "project/bidsection/manage.html",

+ 3 - 3
web/controllers/project_folder.go

@@ -2,7 +2,7 @@
  * @description:标段-文件夹相关
  * @Author: CP
  * @Date: 2020-09-09 17:34:56
- * @FilePath: \construction_management\web\controllers\project_folder.go
+ * @FilePath: \construction_management\web\controllers\project_tree.go
  */
 package controllers
 
@@ -17,7 +17,7 @@ import (
 func (c *ProjectController) PostBidsectionFolderAdd() {
 	ErrMsg := ""
 	// 验证内容
-	FolderData, err := c.ServiceFolder.ValidRule(c.Ctx)
+	FolderData, err := c.ServiceTree.ValidRule(c.Ctx)
 	if err != nil {
 		ErrMsg = utils.FormValidError(err)
 		comm.Redirect(c.Ctx.ResponseWriter(), "/project/bidsection/manage?errMsg="+ErrMsg)
@@ -29,7 +29,7 @@ func (c *ProjectController) PostBidsectionFolderAdd() {
 		}
 		FolderData.ProjectId = strconv.Itoa(projectId)
 		// 新增文件夹
-		err = c.ServiceFolder.Create(FolderData)
+		err = c.ServiceTree.Create(FolderData)
 		if err != nil {
 			comm.Redirect(c.Ctx.ResponseWriter(), "/project/bidsection/manage?errMsg="+ErrMsg)
 		}

+ 3 - 4
web/main.go

@@ -10,7 +10,6 @@ import (
 	"fmt"
 
 	"go.mod/bootstrap"
-	"go.mod/conf"
 	"go.mod/web/middleware/identity"
 	"go.mod/web/routes"
 )
@@ -30,9 +29,9 @@ func newApp() *bootstrap.Bootstrapper {
 func main() {
 	// 服务器集群的时候才需要区分这项设置
 	// 比如:根据服务器的IP、名称、端口号等,或者运行的参数
-	if port == 6060 {
-		conf.RunningCrontabService = true
-	}
+	// if port == 6060 {
+	// 	conf.RunningCrontabService = true
+	// }
 
 	app := newApp()
 	app.Listen(fmt.Sprintf(":%d", port))

+ 46 - 0
web/middleware/jwt.go

@@ -0,0 +1,46 @@
+/*
+ * @description:
+ * @Author: CP
+ * @Date: 2020-09-17 17:15:00
+ * @FilePath: \construction_management\web\middleware\jwt.go
+ */
+package middleware
+
+import (
+	"github.com/iris-contrib/middleware/jwt"
+	"github.com/kataras/iris/v12"
+	"go.mod/conf"
+)
+
+// ResModel 返回数据模板
+type ResModel struct {
+	Code string      `json:"code"`
+	Msg  string      `json:"msg"`
+	Data interface{} `json:"data"`
+}
+
+func JwtAuth() *jwt.Middleware {
+	j2 := jwt.New(jwt.Config{
+		// 注意,新增了一个错误处理函数
+		ErrorHandler: func(ctx iris.Context, err error) {
+			if err == nil {
+				return
+			}
+
+			ctx.StopExecution()
+			ctx.StatusCode(iris.StatusUnauthorized)
+			ctx.JSON(ResModel{
+				Code: "501",
+				Msg:  err.Error(),
+			})
+		},
+		// 设置一个函数返回秘钥,关键在于return []byte("这里设置秘钥")
+		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
+			return []byte(conf.SignSecret), nil
+		},
+
+		// 设置一个加密方法
+		SigningMethod: jwt.SigningMethodHS256,
+	})
+	return j2
+}

+ 24 - 2
web/routes/routes.go

@@ -10,6 +10,7 @@ import (
 	"github.com/kataras/iris/v12/mvc"
 	"go.mod/bootstrap"
 	"go.mod/services"
+	"go.mod/web/api"
 	"go.mod/web/controllers"
 	"go.mod/web/middleware"
 )
@@ -19,7 +20,7 @@ func Configure(b *bootstrap.Bootstrapper) {
 	ProjectAccountService := services.NewProjectAccountService()
 	LoginService := services.NewLoginService()
 	ProjectService := services.NewProjectService()
-	FolderService := services.NewFoldertService()
+	TreeService := services.NewTreeService()
 	//CSRF相关
 	b.Use(middleware.SetCsrf)
 
@@ -53,7 +54,7 @@ func Configure(b *bootstrap.Bootstrapper) {
 	// 项目相关
 	project := mvc.New(b.Party("/project"))
 	project.Router.Use(middleware.SessionsAuth)
-	project.Register(FolderService)
+	project.Register(TreeService)
 	project.Register(ProjectService)
 	project.Handle(new(controllers.ProjectController))
 
@@ -62,4 +63,25 @@ func Configure(b *bootstrap.Bootstrapper) {
 	bidsection.Register(ProjectService)
 	bidsection.Router.Use(middleware.SessionsAuth)
 	bidsection.Handle(new(controllers.BidsectionController))
+
+	// 接口相关
+	// 登陆接口
+	apiLogin := mvc.New(b.Party("/api/login"))
+	apiLogin.Register(ProjectAccountService)
+	apiLogin.Register(LoginService)
+	//apiLogin.Router.Use(middleware.JwtAuth().Serve)
+	apiLogin.Handle(new(api.LoginApi))
+
+	// TreeNode相关接口
+	apiTree := mvc.New(b.Party("/api/tree"))
+	apiTree.Register(TreeService)
+	apiTree.Register(ProjectService)
+	apiTree.Router.Use(middleware.JwtAuth().Serve)
+	apiTree.Handle(new(api.TreeApi))
+
+	// 项目相关接口
+	apiProject := mvc.New(b.Party("/api/project"))
+	apiProject.Register(ProjectService)
+	apiProject.Router.Use(middleware.JwtAuth().Serve)
+	apiProject.Handle(new(api.ProjectApi))
 }

+ 25 - 1
web/utils/utils.go

@@ -6,7 +6,16 @@
  */
 package utils
 
-import "strings"
+import (
+	"errors"
+	"strconv"
+	"strings"
+
+	"github.com/dgrijalva/jwt-go"
+	"github.com/kataras/iris/v12"
+	"go.mod/comm"
+	"go.mod/conf"
+)
 
 // 字符串转换MAP
 func StringToMap(str string, split string) map[string]string {
@@ -18,3 +27,18 @@ func StringToMap(str string, split string) map[string]string {
 	}
 	return strMap
 }
+
+// 获得项目ID
+func GetProjectId(ctx iris.Context) (int, error) {
+	jwtInfo := ctx.Values().Get("jwt").(*jwt.Token)
+	project := jwtInfo.Claims.(jwt.MapClaims)["project"].(string)
+	projectId, err := comm.AesDecrypt(project, conf.CookieSecret)
+	if err != nil {
+		return 0, errors.New("项目不存在")
+	}
+	projectIdInt, err := strconv.Atoi(projectId)
+	if err != nil {
+		return 0, errors.New("项目不存在")
+	}
+	return projectIdInt, nil
+}

+ 0 - 26
web/viewmodels/folder.go

@@ -1,26 +0,0 @@
-/*
- * @description: 视图层 文件夹 models
- * @Author: CP
- * @Date: 2020-09-11 15:12:43
- * @FilePath: \construction_management\web\viewmodels\folder.go
- */
-package viewmodels
-
-import validation "github.com/go-ozzo/ozzo-validation/v3"
-
-type Folder struct {
-	Id         string `form:"id"`
-	Name       string `form:"name"`
-	ProjectId  string `form:"projectId"`
-	TenderId   int    `form:"tenderId"`
-	ParentId   string `form:"parentId"`
-	CreateTime string `form:"createTime"`
-	UpdateTime string `form:"updateTime"`
-	Csrf       string `form:"csrf"`
-}
-
-func (l Folder) Validate() error {
-	return validation.ValidateStruct(&l,
-		validation.Field(&l.Name, validation.Required.Error("文件夹名称不能为空"), validation.Length(1, 15).Error("最多 15 个字符")),
-	)
-}

+ 47 - 0
web/viewmodels/project.go

@@ -0,0 +1,47 @@
+/*
+ * @description: 项目展示项
+ * @Author: CP
+ * @Date: 2020-09-23 11:01:47
+ * @FilePath: \construction_management\web\viewmodels\project.go
+ */
+package viewmodels
+
+import validation "github.com/go-ozzo/ozzo-validation/v3"
+
+type Project struct {
+	Id   string `form:"id" json:"id"`
+	Code string `form:"code" json:"code"`
+	Name string `form:"name" json:"name"`
+
+	// EnterpriseId  int    `xorm:"comment('企业id') INT(11)"`
+	// UserId        int    `xorm:"comment('管理员id(sso用户)') INT(11)"`
+	// UserAccount   string `xorm:"comment('管理员名字(sso用户名)') VARCHAR(32)"`
+	// CreateTime    int    `xorm:"comment('创建时间') INT(11)"`
+	// MaxUser       int    `xorm:"comment('最大创建用户数(删除)') TINYINT(4)"`
+	// Creator       int64  `xorm:"comment('创建者') BIGINT(20)"`
+	// Status        int    `xorm:"comment('项目状态') TINYINT(1)"`
+	// Remark        string `xorm:"comment('备注') VARCHAR(128)"`
+	// ManagerId     int    `xorm:"comment('销售负责人') INT(11)"`
+	// ManagerOffice int    `xorm:"comment('负责人办事处') TINYINT(4)"`
+	// Office        int    `xorm:"comment('办事处id(项目所属)') TINYINT(4)"`
+	// OfficeShare   string `xorm:"comment('办事处共享(office id列表') VARCHAR(1024)"`
+	// BillId        string `xorm:"comment('工程量清单id列表') VARCHAR(128)"`
+	// ChapterId     string `xorm:"comment('项目节清单id列表') VARCHAR(128)"`
+	// StandardId    int    `xorm:"comment('标准清单id') TINYINT(4)"`
+	// Valuation     string `xorm:"comment('清单规范id列表(删除)') VARCHAR(128)"`
+	// QrcodeJson    string `xorm:"comment('项目二维码信息') TEXT"`
+	// DealpayJson   string `xorm:"TEXT"`
+	// Custom        int    `xorm:"comment('是否是定制项目') TINYINT(1)"`
+	// CanApi        int    `xorm:"comment('定制项目接口是否可用') TINYINT(1)"`
+	// Secret        string `xorm:"comment('定制项目私钥') VARCHAR(255)"`
+	// PageShow      string `xorm:"comment('前台页面或功能展示与隐藏') VARCHAR(3072)"`
+	// PagePath      string `xorm:"VARCHAR(11)"`
+}
+
+func (l Project) Validate() error {
+	return validation.ValidateStruct(&l,
+		// 字符的4倍
+		validation.Field(&l.Name, validation.Required.Error("项目名称不能为空"), validation.Length(1, 512).Error("最多 128 个字")),
+		validation.Field(&l.Code, validation.Required.Error("项目编号不能为空"), validation.Length(12, 128).Error("不得少于 3 个字")),
+	)
+}

+ 74 - 0
web/viewmodels/tree.go

@@ -0,0 +1,74 @@
+/*
+ * @description: 视图层 文件夹 models
+ * @Author: CP
+ * @Date: 2020-09-11 15:12:43
+ * @FilePath: \construction_management\web\viewmodels\tree.go
+ */
+package viewmodels
+
+import (
+	validation "github.com/go-ozzo/ozzo-validation/v3"
+)
+
+type Tree struct {
+	Id          string `form:"id" json:"id"`
+	Name        string `form:"name" json:"name"`
+	ProjectId   string `form:"projectId"`
+	TenderId    int    `form:"tenderId"`
+	ParentId    string `form:"parentId" json:"parentId"`
+	Depth       int    `form:"depth"`
+	Serial      string `form:"serial"`
+	Attribution string `form:"attribution"`
+	Isfolder    int    `form:"isfolder"`
+	CreateTime  string `form:"createTime"`
+	UpdateTime  string `form:"updateTime"`
+
+	Csrf     string  `form:"csrf"`
+	Leaf     bool    `json:"leaf"`
+	Children []*Tree `json:"children"`
+}
+
+func (l Tree) Validate() error {
+	return validation.ValidateStruct(&l,
+		validation.Field(&l.Name, validation.Required.Error("文件夹名称不能为空"), validation.Length(1, 60).Error("最多 15 个字符")),
+	)
+}
+
+// func (l Tree) Maketree(Data []*Tree, node *Tree) { //参数为父节点,添加父节点的子节点指针切片
+// 	childs, _ := this.Havechild(Data, node) //判断节点是否有子节点并返回
+// 	if childs != nil {
+// 		// fmt.Printf("\n")
+// 		// fmt.Println(*node)
+// 		// fmt.Println("子节点:")
+// 		for _, v := range childs {
+// 			fmt.Println(*v)
+// 		} //打印
+
+// 		node.Child = append(node.Child, childs[0:]...) //添加子节点
+// 		for _, v := range childs {                     //查询子节点的子节点,并添加到子节点
+// 			_, has := Havechild(Data, v)
+// 			if has {
+// 				Maketree(Data, v) //递归添加节点
+// 			}
+// 		}
+// 	}
+// }
+
+// func (l Tree) Havechild(Data []*Tree, node *Tree) (child []*Tree, yes bool) {
+// 	for _, v := range Data {
+// 		if v.ParentId == node.Id {
+// 			child = append(child, v)
+// 		}
+// 	}
+// 	if child != nil {
+// 		yes = true
+// 	}
+// 	return
+// }
+
+// func transformjson(Data *Tree) { //转为json
+
+// 	Jsondata, _ := json.Marshal(Data)
+
+// 	fmt.Println(string(Jsondata))
+// }

+ 1 - 1
web/views/login/login.html

@@ -15,7 +15,7 @@
                     <input id="inputEmail" name="code" value="{{.LoginData.Code}}" class="form-control " placeholder="项目编号" required="" autofocus="">
                 </div>
                 <div class="form-group mb-3">
-                    <input id="inputEmail" name="account" value="{{.LoginData.Account}}" class="form-control " placeholder="登录账号" required="" autofocus="">
+                    <input  name="account" value="{{.LoginData.Account}}" class="form-control " placeholder="登录账号" required="" autofocus="">
                 </div>
                 <div class="form-group mb-3">
                     <input id="inputPassword" name="password" class="form-control " placeholder="密码" required="" type="password">

+ 7 - 1
web/views/project/bidsection/manage.html

@@ -42,7 +42,7 @@
                     class="fal fa-folder"></i>&nbsp;{{$data.Name}}</td>
                 <td></td>
                 <td>
-                  <a href="#add-folder" data-ParentId="{{$data.Id}}" data-toggle="modal" data-target="#add-folder"
+                  <a href="#add-folder" data-ParentId="{{$data.Id}}" data-Depth="{{$data.Depth}}" data-Id="{{$data.Id}}" data-toggle="modal" data-target="#add-folder"
                     class="btn btn-sm btn-primary pull-right">
                     新建文件夹</a>
                   <a href="#add-bd" data-toggle="modal" data-target="#add-bd"
@@ -137,6 +137,8 @@
   <form action="{{.Action}}folder/add" id="formValid" method="post">
     {{.csrfField}}
     <input name="parentId" value="0" type="hidden">
+    <input name="depth" value="" type="hidden">
+    <input name="id" value="" type="hidden">
     <div class="modal-dialog" role="document">
       <div class="modal-content">
         <div class="modal-header">
@@ -313,6 +315,10 @@
     $('a[data-target="#add-folder"]').click(function () {
       var parentId=$(this).attr("data-ParentId");
       $('input[name="parentId"]').val(parentId);
+      var depth=$(this).attr("data-Depth");
+      $('input[name="depth"]').val(depth);
+      var id=$(this).attr("data-Id");
+      $('input[name="id"]').val(id);
     });
 
   })

+ 286 - 0
工程项目管理.postman_collection.json

@@ -0,0 +1,286 @@
+{
+	"info": {
+		"_postman_id": "c565c5a4-20a3-4d88-9a3e-62981014dc4a",
+		"name": "工程项目管理",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
+	},
+	"item": [
+		{
+			"name": "目录相关",
+			"item": [
+				{
+					"name": "目录重命名",
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"body": {
+							"mode": "formdata",
+							"formdata": [
+								{
+									"key": "id",
+									"value": "055xjkeP0g05KaKSttgv4w",
+									"description": "目录ID",
+									"type": "text"
+								},
+								{
+									"key": "name",
+									"value": "2级子目录重命名",
+									"description": "目录名称",
+									"type": "text"
+								}
+							]
+						},
+						"url": {
+							"raw": "http://cm.com/api/tree/rename",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"tree",
+								"rename"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "添加目录",
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"body": {
+							"mode": "formdata",
+							"formdata": [
+								{
+									"key": "id",
+									"value": "055xjkeP0g05KaKSttgv4w",
+									"description": "目录ID",
+									"type": "text"
+								},
+								{
+									"key": "depth",
+									"value": "2",
+									"description": "目录深度",
+									"type": "text"
+								},
+								{
+									"key": "name",
+									"value": "2级工程目录的子目录",
+									"description": "目录名称",
+									"type": "text"
+								}
+							]
+						},
+						"url": {
+							"raw": "http://cm.com/api/tree/create",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"tree",
+								"create"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "获得树目录",
+					"request": {
+						"method": "GET",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"url": {
+							"raw": "http://cm.com/api/tree",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"tree"
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "目录删除",
+					"request": {
+						"method": "DELETE",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"body": {
+							"mode": "formdata",
+							"formdata": [
+								{
+									"key": "id",
+									"value": "055xjkeP0g05KaKSttgv4w",
+									"description": "目录ID",
+									"type": "text"
+								}
+							]
+						},
+						"url": {
+							"raw": "http://cm.com/api/tree/delete",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"tree",
+								"delete"
+							]
+						}
+					},
+					"response": []
+				}
+			],
+			"protocolProfileBehavior": {}
+		},
+		{
+			"name": "项目相关",
+			"item": [
+				{
+					"name": "获得项目相关信息",
+					"protocolProfileBehavior": {
+						"disableBodyPruning": true
+					},
+					"request": {
+						"method": "GET",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\r\n    \r\n    \"code\": \"234\"\r\n}",
+							"options": {
+								"raw": {
+									"language": "json"
+								}
+							}
+						},
+						"url": {
+							"raw": "http://cm.com/api/project?code=234",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"project"
+							],
+							"query": [
+								{
+									"key": "code",
+									"value": "234"
+								}
+							]
+						}
+					},
+					"response": []
+				},
+				{
+					"name": "获得一组项目信息",
+					"request": {
+						"method": "GET",
+						"header": [
+							{
+								"key": "Authorization",
+								"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDA5Mjg2ODQsImlhdCI6MTYwMDY2OTQ4NCwiaWRlbnRpdHkiOiI1R0lWLVdIZm15aDNnUXhEU0VCVk5BIiwiaXNzIjoiY20iLCJwcm9qZWN0IjoiZG5sUE5sWjN6SFFVSHBQOVBUTXNldyJ9.emddRhE_urzFWi6I90Au919Ev30NQFKXLpdw6glyRSY",
+								"type": "text"
+							}
+						],
+						"url": {
+							"raw": "http://cm.com/api/project/list?code=2",
+							"protocol": "http",
+							"host": [
+								"cm",
+								"com"
+							],
+							"path": [
+								"api",
+								"project",
+								"list"
+							],
+							"query": [
+								{
+									"key": "code",
+									"value": "2"
+								}
+							]
+						}
+					},
+					"response": []
+				}
+			],
+			"protocolProfileBehavior": {}
+		},
+		{
+			"name": "项目用户登陆",
+			"request": {
+				"method": "POST",
+				"header": [],
+				"body": {
+					"mode": "raw",
+					"raw": "{\n\"code\":\"234\",\n\"account\":\"caipin\",\n\"password\":\"123456\"\n}",
+					"options": {
+						"raw": {
+							"language": "json"
+						}
+					}
+				},
+				"url": {
+					"raw": "http://cm.com/api/login",
+					"protocol": "http",
+					"host": [
+						"cm",
+						"com"
+					],
+					"path": [
+						"api",
+						"login"
+					]
+				}
+			},
+			"response": []
+		}
+	],
+	"protocolProfileBehavior": {}
+}