wangxingcheng 3 years ago
parent
commit
1141e6b033
43 changed files with 4801 additions and 0 deletions
  1. 455 0
      opms_parent/app/dao/plat/internal/plat_followup.go
  2. 428 0
      opms_parent/app/dao/plat/internal/plat_followup_comment.go
  3. 431 0
      opms_parent/app/dao/plat/internal/plat_followup_file.go
  4. 464 0
      opms_parent/app/dao/plat/internal/plat_task.go
  5. 428 0
      opms_parent/app/dao/plat/internal/plat_task_comment.go
  6. 434 0
      opms_parent/app/dao/plat/internal/plat_task_log.go
  7. 431 0
      opms_parent/app/dao/plat/internal/plat_task_progress.go
  8. 36 0
      opms_parent/app/dao/plat/plat_followup.go
  9. 36 0
      opms_parent/app/dao/plat/plat_followup_comment.go
  10. 36 0
      opms_parent/app/dao/plat/plat_followup_file.go
  11. 36 0
      opms_parent/app/dao/plat/plat_task.go
  12. 36 0
      opms_parent/app/dao/plat/plat_task_comment.go
  13. 36 0
      opms_parent/app/dao/plat/plat_task_log.go
  14. 36 0
      opms_parent/app/dao/plat/plat_task_progress.go
  15. 75 0
      opms_parent/app/handler/plat/followup.go
  16. 51 0
      opms_parent/app/handler/plat/followup_comment.go
  17. 30 0
      opms_parent/app/handler/plat/followup_file.go
  18. 74 0
      opms_parent/app/handler/plat/task.go
  19. 51 0
      opms_parent/app/handler/plat/task_comment.go
  20. 30 0
      opms_parent/app/handler/plat/task_log.go
  21. 51 0
      opms_parent/app/handler/plat/task_progress.go
  22. 34 0
      opms_parent/app/model/plat/internal/plat_followup.go
  23. 25 0
      opms_parent/app/model/plat/internal/plat_followup_comment.go
  24. 26 0
      opms_parent/app/model/plat/internal/plat_followup_file.go
  25. 37 0
      opms_parent/app/model/plat/internal/plat_task.go
  26. 25 0
      opms_parent/app/model/plat/internal/plat_task_comment.go
  27. 27 0
      opms_parent/app/model/plat/internal/plat_task_log.go
  28. 26 0
      opms_parent/app/model/plat/internal/plat_task_progress.go
  29. 57 0
      opms_parent/app/model/plat/plat_followup.go
  30. 30 0
      opms_parent/app/model/plat/plat_followup_comment.go
  31. 30 0
      opms_parent/app/model/plat/plat_followup_file.go
  32. 56 0
      opms_parent/app/model/plat/plat_task.go
  33. 30 0
      opms_parent/app/model/plat/plat_task_comment.go
  34. 21 0
      opms_parent/app/model/plat/plat_task_log.go
  35. 30 0
      opms_parent/app/model/plat/plat_task_progress.go
  36. 185 0
      opms_parent/app/service/plat/plat_followup.go
  37. 66 0
      opms_parent/app/service/plat/plat_followup_comment.go
  38. 43 0
      opms_parent/app/service/plat/plat_followup_file.go
  39. 182 0
      opms_parent/app/service/plat/plat_task.go
  40. 66 0
      opms_parent/app/service/plat/plat_task_comment.go
  41. 43 0
      opms_parent/app/service/plat/plat_task_log.go
  42. 66 0
      opms_parent/app/service/plat/plat_task_progress.go
  43. 11 0
      opms_parent/main.go

+ 455 - 0
opms_parent/app/dao/plat/internal/plat_followup.go

@@ -0,0 +1,455 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatFollowupDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatFollowupDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platFollowupColumns
+}
+
+// PlatFollowupColumns defines and stores column names for table plat_followup.
+type platFollowupColumns struct {
+	Id            string // 主键
+	FollowType    string // 跟进类型(10电话20邮件30拜访)
+	FollowDate    string // 跟进时间
+	FollowContent string // 跟进内容
+	TargetId      string // 跟进对象ID
+	TargetType    string // 跟进对象类型(10客户,20项目,30合同,40回款)
+	TargetName    string // 跟进对象
+	CustId        string // 关联客户
+	CustName      string // 客户名称
+	ContactsId    string // 关联联系人
+	ContactsName  string // 联系人姓名
+	Reminders     string // 提醒对象
+	NextTime      string // 下次联系时间
+	Remark        string // 备注
+	CreatedBy     string // 创建者
+	CreatedName   string // 创建人
+	CreatedTime   string // 创建时间
+	UpdatedBy     string // 更新者
+	UpdatedName   string // 更新人
+	UpdatedTime   string // 更新时间
+	DeletedTime   string // 删除时间
+}
+
+var (
+	// PlatFollowup is globally public accessible object for table plat_followup operations.
+	PlatFollowup = PlatFollowupDao{
+		M:     g.DB("default").Model("plat_followup").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_followup",
+		Columns: platFollowupColumns{
+			Id:            "id",
+			FollowType:    "follow_type",
+			FollowDate:    "follow_date",
+			FollowContent: "follow_content",
+			TargetId:      "target_id",
+			TargetType:    "target_type",
+			TargetName:    "target_name",
+			CustId:        "cust_id",
+			CustName:      "cust_name",
+			ContactsId:    "contacts_id",
+			ContactsName:  "contacts_name",
+			Reminders:     "reminders",
+			NextTime:      "next_time",
+			Remark:        "remark",
+			CreatedBy:     "created_by",
+			CreatedName:   "created_name",
+			CreatedTime:   "created_time",
+			UpdatedBy:     "updated_by",
+			UpdatedName:   "updated_name",
+			UpdatedTime:   "updated_time",
+			DeletedTime:   "deleted_time",
+		},
+	}
+)
+
+func NewPlatFollowupDao(tenant string) PlatFollowupDao {
+	var dao PlatFollowupDao
+	dao = PlatFollowupDao{
+		M:     g.DB(tenant).Model("plat_followup").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_followup",
+		Columns: platFollowupColumns{
+			Id:            "id",
+			FollowType:    "follow_type",
+			FollowDate:    "follow_date",
+			FollowContent: "follow_content",
+			TargetId:      "target_id",
+			TargetType:    "target_type",
+			TargetName:    "target_name",
+			CustId:        "cust_id",
+			CustName:      "cust_name",
+			ContactsId:    "contacts_id",
+			ContactsName:  "contacts_name",
+			Reminders:     "reminders",
+			NextTime:      "next_time",
+			Remark:        "remark",
+			CreatedBy:     "created_by",
+			CreatedName:   "created_name",
+			CreatedTime:   "created_time",
+			UpdatedBy:     "updated_by",
+			UpdatedName:   "updated_name",
+			UpdatedTime:   "updated_time",
+			DeletedTime:   "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatFollowupDao) Ctx(ctx context.Context) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatFollowupDao) As(as string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatFollowupDao) TX(tx *gdb.TX) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatFollowupDao) Master() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatFollowupDao) Slave() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatFollowupDao) Args(args ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupDao) LeftJoin(table ...string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupDao) RightJoin(table ...string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupDao) InnerJoin(table ...string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatFollowupDao) Option(option int) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatFollowupDao) OmitEmpty() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatFollowupDao) Filter() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatFollowupDao) Where(where interface{}, args ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatFollowupDao) WherePri(where interface{}, args ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatFollowupDao) And(where interface{}, args ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatFollowupDao) Or(where interface{}, args ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatFollowupDao) Group(groupBy string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatFollowupDao) Order(orderBy ...string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatFollowupDao) Limit(limit ...int) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatFollowupDao) Offset(offset int) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatFollowupDao) Page(page, limit int) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatFollowupDao) Batch(batch int) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatFollowupDao) Cache(duration time.Duration, name ...string) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatFollowupDao) Data(data ...interface{}) *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatFollowup.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupDao) All(where ...interface{}) ([]*plat.PlatFollowup, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowup
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatFollowup.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupDao) One(where ...interface{}) (*plat.PlatFollowup, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowup
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatFollowupDao) FindOne(where ...interface{}) (*plat.PlatFollowup, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowup
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatFollowupDao) FindAll(where ...interface{}) ([]*plat.PlatFollowup, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowup
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatFollowupDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatFollowupDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatFollowupDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatFollowupDao) Chunk(limit int, callback func(entities []*plat.PlatFollowup, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatFollowup
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatFollowupDao) LockUpdate() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatFollowupDao) LockShared() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatFollowupDao) Unscoped() *PlatFollowupDao {
+	return &PlatFollowupDao{M: d.M.Unscoped()}
+}

+ 428 - 0
opms_parent/app/dao/plat/internal/plat_followup_comment.go

@@ -0,0 +1,428 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatFollowupCommentDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatFollowupCommentDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platFollowupCommentColumns
+}
+
+// PlatFollowupCommentColumns defines and stores column names for table plat_followup_comment.
+type platFollowupCommentColumns struct {
+	Id          string // 主键
+	FollowId    string // 关联跟进
+	Content     string // 评论内容
+	Pid         string // 回复对象ID
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// PlatFollowupComment is globally public accessible object for table plat_followup_comment operations.
+	PlatFollowupComment = PlatFollowupCommentDao{
+		M:     g.DB("default").Model("plat_followup_comment").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_followup_comment",
+		Columns: platFollowupCommentColumns{
+			Id:          "id",
+			FollowId:    "follow_id",
+			Content:     "content",
+			Pid:         "pid",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewPlatFollowupCommentDao(tenant string) PlatFollowupCommentDao {
+	var dao PlatFollowupCommentDao
+	dao = PlatFollowupCommentDao{
+		M:     g.DB(tenant).Model("plat_followup_comment").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_followup_comment",
+		Columns: platFollowupCommentColumns{
+			Id:          "id",
+			FollowId:    "follow_id",
+			Content:     "content",
+			Pid:         "pid",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatFollowupCommentDao) Ctx(ctx context.Context) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatFollowupCommentDao) As(as string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatFollowupCommentDao) TX(tx *gdb.TX) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatFollowupCommentDao) Master() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatFollowupCommentDao) Slave() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatFollowupCommentDao) Args(args ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupCommentDao) LeftJoin(table ...string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupCommentDao) RightJoin(table ...string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupCommentDao) InnerJoin(table ...string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupCommentDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupCommentDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatFollowupCommentDao) Option(option int) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatFollowupCommentDao) OmitEmpty() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatFollowupCommentDao) Filter() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatFollowupCommentDao) Where(where interface{}, args ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatFollowupCommentDao) WherePri(where interface{}, args ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatFollowupCommentDao) And(where interface{}, args ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatFollowupCommentDao) Or(where interface{}, args ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatFollowupCommentDao) Group(groupBy string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatFollowupCommentDao) Order(orderBy ...string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatFollowupCommentDao) Limit(limit ...int) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatFollowupCommentDao) Offset(offset int) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatFollowupCommentDao) Page(page, limit int) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatFollowupCommentDao) Batch(batch int) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatFollowupCommentDao) Cache(duration time.Duration, name ...string) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatFollowupCommentDao) Data(data ...interface{}) *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatFollowupComment.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupCommentDao) All(where ...interface{}) ([]*plat.PlatFollowupComment, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowupComment
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatFollowupComment.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupCommentDao) One(where ...interface{}) (*plat.PlatFollowupComment, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowupComment
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatFollowupCommentDao) FindOne(where ...interface{}) (*plat.PlatFollowupComment, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowupComment
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatFollowupCommentDao) FindAll(where ...interface{}) ([]*plat.PlatFollowupComment, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowupComment
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatFollowupCommentDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatFollowupCommentDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatFollowupCommentDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatFollowupCommentDao) Chunk(limit int, callback func(entities []*plat.PlatFollowupComment, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatFollowupComment
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatFollowupCommentDao) LockUpdate() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatFollowupCommentDao) LockShared() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatFollowupCommentDao) Unscoped() *PlatFollowupCommentDao {
+	return &PlatFollowupCommentDao{M: d.M.Unscoped()}
+}

+ 431 - 0
opms_parent/app/dao/plat/internal/plat_followup_file.go

@@ -0,0 +1,431 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatFollowupFileDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatFollowupFileDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platFollowupFileColumns
+}
+
+// PlatFollowupFileColumns defines and stores column names for table plat_followup_file.
+type platFollowupFileColumns struct {
+	Id          string // 主键
+	FollowId    string // 关联跟进
+	FileName    string // 文件名
+	FileType    string // 文件类型
+	FileUrl     string // 文件地址
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// PlatFollowupFile is globally public accessible object for table plat_followup_file operations.
+	PlatFollowupFile = PlatFollowupFileDao{
+		M:     g.DB("default").Model("plat_followup_file").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_followup_file",
+		Columns: platFollowupFileColumns{
+			Id:          "id",
+			FollowId:    "follow_id",
+			FileName:    "file_name",
+			FileType:    "file_type",
+			FileUrl:     "file_url",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewPlatFollowupFileDao(tenant string) PlatFollowupFileDao {
+	var dao PlatFollowupFileDao
+	dao = PlatFollowupFileDao{
+		M:     g.DB(tenant).Model("plat_followup_file").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_followup_file",
+		Columns: platFollowupFileColumns{
+			Id:          "id",
+			FollowId:    "follow_id",
+			FileName:    "file_name",
+			FileType:    "file_type",
+			FileUrl:     "file_url",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatFollowupFileDao) Ctx(ctx context.Context) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatFollowupFileDao) As(as string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatFollowupFileDao) TX(tx *gdb.TX) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatFollowupFileDao) Master() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatFollowupFileDao) Slave() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatFollowupFileDao) Args(args ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupFileDao) LeftJoin(table ...string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupFileDao) RightJoin(table ...string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatFollowupFileDao) InnerJoin(table ...string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupFileDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatFollowupFileDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatFollowupFileDao) Option(option int) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatFollowupFileDao) OmitEmpty() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatFollowupFileDao) Filter() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatFollowupFileDao) Where(where interface{}, args ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatFollowupFileDao) WherePri(where interface{}, args ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatFollowupFileDao) And(where interface{}, args ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatFollowupFileDao) Or(where interface{}, args ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatFollowupFileDao) Group(groupBy string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatFollowupFileDao) Order(orderBy ...string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatFollowupFileDao) Limit(limit ...int) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatFollowupFileDao) Offset(offset int) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatFollowupFileDao) Page(page, limit int) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatFollowupFileDao) Batch(batch int) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatFollowupFileDao) Cache(duration time.Duration, name ...string) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatFollowupFileDao) Data(data ...interface{}) *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatFollowupFile.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupFileDao) All(where ...interface{}) ([]*plat.PlatFollowupFile, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowupFile
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatFollowupFile.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatFollowupFileDao) One(where ...interface{}) (*plat.PlatFollowupFile, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowupFile
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatFollowupFileDao) FindOne(where ...interface{}) (*plat.PlatFollowupFile, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatFollowupFile
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatFollowupFileDao) FindAll(where ...interface{}) ([]*plat.PlatFollowupFile, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatFollowupFile
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatFollowupFileDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatFollowupFileDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatFollowupFileDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatFollowupFileDao) Chunk(limit int, callback func(entities []*plat.PlatFollowupFile, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatFollowupFile
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatFollowupFileDao) LockUpdate() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatFollowupFileDao) LockShared() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatFollowupFileDao) Unscoped() *PlatFollowupFileDao {
+	return &PlatFollowupFileDao{M: d.M.Unscoped()}
+}

+ 464 - 0
opms_parent/app/dao/plat/internal/plat_task.go

@@ -0,0 +1,464 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatTaskDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatTaskDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platTaskColumns
+}
+
+// PlatTaskColumns defines and stores column names for table plat_task.
+type platTaskColumns struct {
+	Id               string // 主键
+	TaskTitle        string // 任务标题
+	TaskType         string // 任务类型
+	TaskStatus       string // 任务状态(10进行中20关闭)
+	IsOverdue        string // 是否超期(10否20是)
+	TaskStartDate    string // 任务开始时间
+	TaskEndDate      string // 任务结束时间
+	TaskDesc         string // 任务说明
+	SupervisorUserId string // 督办人
+	WatchUserId      string // 监办人
+	MainUserId       string // 负责人ID
+	OwnerUserId      string // 团队成员ID
+	TaskLabel        string // 任务标签,号拼接
+	TargetId         string // 关联对象ID
+	TargetType       string // 关联对象类型(10客户,20项目,30合同,40回款)
+	TargetName       string // 关联对象
+	Remark           string // 备注
+	CreatedBy        string // 创建者
+	CreatedName      string // 创建人
+	CreatedTime      string // 创建时间
+	UpdatedBy        string // 更新者
+	UpdatedName      string // 更新人
+	UpdatedTime      string // 更新时间
+	DeletedTime      string // 删除时间
+}
+
+var (
+	// PlatTask is globally public accessible object for table plat_task operations.
+	PlatTask = PlatTaskDao{
+		M:     g.DB("default").Model("plat_task").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_task",
+		Columns: platTaskColumns{
+			Id:               "id",
+			TaskTitle:        "task_title",
+			TaskType:         "task_type",
+			TaskStatus:       "task_status",
+			IsOverdue:        "is_overdue",
+			TaskStartDate:    "task_start_date",
+			TaskEndDate:      "task_end_date",
+			TaskDesc:         "task_desc",
+			SupervisorUserId: "supervisor_user_id",
+			WatchUserId:      "watch_user_id",
+			MainUserId:       "main_user_id",
+			OwnerUserId:      "owner_user_id",
+			TaskLabel:        "task_label",
+			TargetId:         "target_id",
+			TargetType:       "target_type",
+			TargetName:       "target_name",
+			Remark:           "remark",
+			CreatedBy:        "created_by",
+			CreatedName:      "created_name",
+			CreatedTime:      "created_time",
+			UpdatedBy:        "updated_by",
+			UpdatedName:      "updated_name",
+			UpdatedTime:      "updated_time",
+			DeletedTime:      "deleted_time",
+		},
+	}
+)
+
+func NewPlatTaskDao(tenant string) PlatTaskDao {
+	var dao PlatTaskDao
+	dao = PlatTaskDao{
+		M:     g.DB(tenant).Model("plat_task").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_task",
+		Columns: platTaskColumns{
+			Id:               "id",
+			TaskTitle:        "task_title",
+			TaskType:         "task_type",
+			TaskStatus:       "task_status",
+			IsOverdue:        "is_overdue",
+			TaskStartDate:    "task_start_date",
+			TaskEndDate:      "task_end_date",
+			TaskDesc:         "task_desc",
+			SupervisorUserId: "supervisor_user_id",
+			WatchUserId:      "watch_user_id",
+			MainUserId:       "main_user_id",
+			OwnerUserId:      "owner_user_id",
+			TaskLabel:        "task_label",
+			TargetId:         "target_id",
+			TargetType:       "target_type",
+			TargetName:       "target_name",
+			Remark:           "remark",
+			CreatedBy:        "created_by",
+			CreatedName:      "created_name",
+			CreatedTime:      "created_time",
+			UpdatedBy:        "updated_by",
+			UpdatedName:      "updated_name",
+			UpdatedTime:      "updated_time",
+			DeletedTime:      "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatTaskDao) Ctx(ctx context.Context) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatTaskDao) As(as string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatTaskDao) TX(tx *gdb.TX) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatTaskDao) Master() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatTaskDao) Slave() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatTaskDao) Args(args ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskDao) LeftJoin(table ...string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskDao) RightJoin(table ...string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskDao) InnerJoin(table ...string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatTaskDao) Option(option int) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatTaskDao) OmitEmpty() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatTaskDao) Filter() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatTaskDao) Where(where interface{}, args ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatTaskDao) WherePri(where interface{}, args ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatTaskDao) And(where interface{}, args ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatTaskDao) Or(where interface{}, args ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatTaskDao) Group(groupBy string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatTaskDao) Order(orderBy ...string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatTaskDao) Limit(limit ...int) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatTaskDao) Offset(offset int) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatTaskDao) Page(page, limit int) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatTaskDao) Batch(batch int) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatTaskDao) Cache(duration time.Duration, name ...string) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatTaskDao) Data(data ...interface{}) *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatTask.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskDao) All(where ...interface{}) ([]*plat.PlatTask, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTask
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatTask.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskDao) One(where ...interface{}) (*plat.PlatTask, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTask
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatTaskDao) FindOne(where ...interface{}) (*plat.PlatTask, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTask
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatTaskDao) FindAll(where ...interface{}) ([]*plat.PlatTask, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTask
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatTaskDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatTaskDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatTaskDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatTaskDao) Chunk(limit int, callback func(entities []*plat.PlatTask, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatTask
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatTaskDao) LockUpdate() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatTaskDao) LockShared() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatTaskDao) Unscoped() *PlatTaskDao {
+	return &PlatTaskDao{M: d.M.Unscoped()}
+}

+ 428 - 0
opms_parent/app/dao/plat/internal/plat_task_comment.go

@@ -0,0 +1,428 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatTaskCommentDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatTaskCommentDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platTaskCommentColumns
+}
+
+// PlatTaskCommentColumns defines and stores column names for table plat_task_comment.
+type platTaskCommentColumns struct {
+	Id          string // 主键
+	TaskId      string // 关联跟进
+	Content     string // 评论内容
+	Pid         string // 回复对象ID
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// PlatTaskComment is globally public accessible object for table plat_task_comment operations.
+	PlatTaskComment = PlatTaskCommentDao{
+		M:     g.DB("default").Model("plat_task_comment").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_task_comment",
+		Columns: platTaskCommentColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			Content:     "content",
+			Pid:         "pid",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewPlatTaskCommentDao(tenant string) PlatTaskCommentDao {
+	var dao PlatTaskCommentDao
+	dao = PlatTaskCommentDao{
+		M:     g.DB(tenant).Model("plat_task_comment").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_task_comment",
+		Columns: platTaskCommentColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			Content:     "content",
+			Pid:         "pid",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatTaskCommentDao) Ctx(ctx context.Context) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatTaskCommentDao) As(as string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatTaskCommentDao) TX(tx *gdb.TX) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatTaskCommentDao) Master() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatTaskCommentDao) Slave() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatTaskCommentDao) Args(args ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskCommentDao) LeftJoin(table ...string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskCommentDao) RightJoin(table ...string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskCommentDao) InnerJoin(table ...string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskCommentDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskCommentDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatTaskCommentDao) Option(option int) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatTaskCommentDao) OmitEmpty() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatTaskCommentDao) Filter() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatTaskCommentDao) Where(where interface{}, args ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatTaskCommentDao) WherePri(where interface{}, args ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatTaskCommentDao) And(where interface{}, args ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatTaskCommentDao) Or(where interface{}, args ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatTaskCommentDao) Group(groupBy string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatTaskCommentDao) Order(orderBy ...string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatTaskCommentDao) Limit(limit ...int) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatTaskCommentDao) Offset(offset int) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatTaskCommentDao) Page(page, limit int) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatTaskCommentDao) Batch(batch int) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatTaskCommentDao) Cache(duration time.Duration, name ...string) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatTaskCommentDao) Data(data ...interface{}) *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatTaskComment.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskCommentDao) All(where ...interface{}) ([]*plat.PlatTaskComment, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskComment
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatTaskComment.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskCommentDao) One(where ...interface{}) (*plat.PlatTaskComment, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskComment
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatTaskCommentDao) FindOne(where ...interface{}) (*plat.PlatTaskComment, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskComment
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatTaskCommentDao) FindAll(where ...interface{}) ([]*plat.PlatTaskComment, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskComment
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatTaskCommentDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatTaskCommentDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatTaskCommentDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatTaskCommentDao) Chunk(limit int, callback func(entities []*plat.PlatTaskComment, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatTaskComment
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatTaskCommentDao) LockUpdate() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatTaskCommentDao) LockShared() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatTaskCommentDao) Unscoped() *PlatTaskCommentDao {
+	return &PlatTaskCommentDao{M: d.M.Unscoped()}
+}

+ 434 - 0
opms_parent/app/dao/plat/internal/plat_task_log.go

@@ -0,0 +1,434 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatTaskLogDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatTaskLogDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platTaskLogColumns
+}
+
+// PlatTaskLogColumns defines and stores column names for table plat_task_log.
+type platTaskLogColumns struct {
+	Id          string // 主键
+	TaskId      string // 关联任务
+	NodeName    string // 流程节点名称
+	Desc        string // 说明
+	StartTime   string // 开始处理时间
+	EndTime     string // 处理结束时间
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// PlatTaskLog is globally public accessible object for table plat_task_log operations.
+	PlatTaskLog = PlatTaskLogDao{
+		M:     g.DB("default").Model("plat_task_log").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_task_log",
+		Columns: platTaskLogColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			NodeName:    "node_name",
+			Desc:        "desc",
+			StartTime:   "start_time",
+			EndTime:     "end_time",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewPlatTaskLogDao(tenant string) PlatTaskLogDao {
+	var dao PlatTaskLogDao
+	dao = PlatTaskLogDao{
+		M:     g.DB(tenant).Model("plat_task_log").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_task_log",
+		Columns: platTaskLogColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			NodeName:    "node_name",
+			Desc:        "desc",
+			StartTime:   "start_time",
+			EndTime:     "end_time",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatTaskLogDao) Ctx(ctx context.Context) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatTaskLogDao) As(as string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatTaskLogDao) TX(tx *gdb.TX) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatTaskLogDao) Master() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatTaskLogDao) Slave() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatTaskLogDao) Args(args ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskLogDao) LeftJoin(table ...string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskLogDao) RightJoin(table ...string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskLogDao) InnerJoin(table ...string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskLogDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskLogDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatTaskLogDao) Option(option int) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatTaskLogDao) OmitEmpty() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatTaskLogDao) Filter() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatTaskLogDao) Where(where interface{}, args ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatTaskLogDao) WherePri(where interface{}, args ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatTaskLogDao) And(where interface{}, args ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatTaskLogDao) Or(where interface{}, args ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatTaskLogDao) Group(groupBy string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatTaskLogDao) Order(orderBy ...string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatTaskLogDao) Limit(limit ...int) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatTaskLogDao) Offset(offset int) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatTaskLogDao) Page(page, limit int) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatTaskLogDao) Batch(batch int) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatTaskLogDao) Cache(duration time.Duration, name ...string) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatTaskLogDao) Data(data ...interface{}) *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatTaskLog.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskLogDao) All(where ...interface{}) ([]*plat.PlatTaskLog, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskLog
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatTaskLog.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskLogDao) One(where ...interface{}) (*plat.PlatTaskLog, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskLog
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatTaskLogDao) FindOne(where ...interface{}) (*plat.PlatTaskLog, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskLog
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatTaskLogDao) FindAll(where ...interface{}) ([]*plat.PlatTaskLog, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskLog
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatTaskLogDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatTaskLogDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatTaskLogDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatTaskLogDao) Chunk(limit int, callback func(entities []*plat.PlatTaskLog, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatTaskLog
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatTaskLogDao) LockUpdate() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatTaskLogDao) LockShared() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatTaskLogDao) Unscoped() *PlatTaskLogDao {
+	return &PlatTaskLogDao{M: d.M.Unscoped()}
+}

+ 431 - 0
opms_parent/app/dao/plat/internal/plat_task_progress.go

@@ -0,0 +1,431 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"dashoo.cn/micro/app/model/plat"
+	"database/sql"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+	"time"
+)
+
+// PlatTaskProgressDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type PlatTaskProgressDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns platTaskProgressColumns
+}
+
+// PlatTaskProgressColumns defines and stores column names for table plat_task_progress.
+type platTaskProgressColumns struct {
+	Id          string // 主键
+	TaskId      string // 关联任务
+	ProgDate    string // 进展时间
+	ProgDesc    string // 进展说明
+	ProgFile    string // 相关附件
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// PlatTaskProgress is globally public accessible object for table plat_task_progress operations.
+	PlatTaskProgress = PlatTaskProgressDao{
+		M:     g.DB("default").Model("plat_task_progress").Safe(),
+		DB:    g.DB("default"),
+		Table: "plat_task_progress",
+		Columns: platTaskProgressColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			ProgDate:    "prog_date",
+			ProgDesc:    "prog_desc",
+			ProgFile:    "prog_file",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+)
+
+func NewPlatTaskProgressDao(tenant string) PlatTaskProgressDao {
+	var dao PlatTaskProgressDao
+	dao = PlatTaskProgressDao{
+		M:     g.DB(tenant).Model("plat_task_progress").Safe(),
+		DB:    g.DB(tenant),
+		Table: "plat_task_progress",
+		Columns: platTaskProgressColumns{
+			Id:          "id",
+			TaskId:      "task_id",
+			ProgDate:    "prog_date",
+			ProgDesc:    "prog_desc",
+			ProgFile:    "prog_file",
+			Remark:      "remark",
+			CreatedBy:   "created_by",
+			CreatedName: "created_name",
+			CreatedTime: "created_time",
+			UpdatedBy:   "updated_by",
+			UpdatedName: "updated_name",
+			UpdatedTime: "updated_time",
+			DeletedTime: "deleted_time",
+		},
+	}
+	return dao
+}
+
+// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy
+// of current DB object and with given context in it.
+// Note that this returned DB object can be used only once, so do not assign it to
+// a global or package variable for long using.
+func (d *PlatTaskProgressDao) Ctx(ctx context.Context) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *PlatTaskProgressDao) As(as string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *PlatTaskProgressDao) TX(tx *gdb.TX) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *PlatTaskProgressDao) Master() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Master()}
+}
+
+// Slave marks the following operation on slave node.
+// Note that it makes sense only if there's any slave node configured.
+func (d *PlatTaskProgressDao) Slave() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *PlatTaskProgressDao) Args(args ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Args(args...)}
+}
+
+// LeftJoin does "LEFT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskProgressDao) LeftJoin(table ...string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.LeftJoin(table...)}
+}
+
+// RightJoin does "RIGHT JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskProgressDao) RightJoin(table ...string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.RightJoin(table...)}
+}
+
+// InnerJoin does "INNER JOIN ... ON ..." statement on the model.
+// The parameter <table> can be joined table and its joined condition,
+// and also with its alias name, like:
+// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid")
+// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid")
+func (d *PlatTaskProgressDao) InnerJoin(table ...string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.InnerJoin(table...)}
+}
+
+// Fields sets the operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskProgressDao) Fields(fieldNamesOrMapStruct ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Fields(fieldNamesOrMapStruct...)}
+}
+
+// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','.
+// The parameter <fieldNamesOrMapStruct> can be type of string/map/*map/struct/*struct.
+func (d *PlatTaskProgressDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *PlatTaskProgressDao) Option(option int) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Option(option)}
+}
+
+// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers
+// the data and where attributes for empty values.
+func (d *PlatTaskProgressDao) OmitEmpty() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *PlatTaskProgressDao) Filter() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Filter()}
+}
+
+// Where sets the condition statement for the model. The parameter <where> can be type of
+// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times,
+// multiple conditions will be joined into where statement using "AND".
+// Eg:
+// Where("uid=10000")
+// Where("uid", 10000)
+// Where("money>? AND name like ?", 99999, "vip_%")
+// Where("uid", 1).Where("name", "john")
+// Where("status IN (?)", g.Slice{1,2,3})
+// Where("age IN(?,?)", 18, 50)
+// Where(User{ Id : 1, UserName : "john"})
+func (d *PlatTaskProgressDao) Where(where interface{}, args ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Where(where, args...)}
+}
+
+// WherePri does the same logic as M.Where except that if the parameter <where>
+// is a single condition like int/string/float/slice, it treats the condition as the primary
+// key value. That is, if primary key is "id" and given <where> parameter as "123", the
+// WherePri function treats the condition as "id=123", but M.Where treats the condition
+// as string "123".
+func (d *PlatTaskProgressDao) WherePri(where interface{}, args ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *PlatTaskProgressDao) And(where interface{}, args ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *PlatTaskProgressDao) Or(where interface{}, args ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *PlatTaskProgressDao) Group(groupBy string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *PlatTaskProgressDao) Order(orderBy ...string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Order(orderBy...)}
+}
+
+// Limit sets the "LIMIT" statement for the model.
+// The parameter <limit> can be either one or two number, if passed two number is passed,
+// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]"
+// statement.
+func (d *PlatTaskProgressDao) Limit(limit ...int) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Limit(limit...)}
+}
+
+// Offset sets the "OFFSET" statement for the model.
+// It only makes sense for some databases like SQLServer, PostgreSQL, etc.
+func (d *PlatTaskProgressDao) Offset(offset int) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Offset(offset)}
+}
+
+// Page sets the paging number for the model.
+// The parameter <page> is started from 1 for paging.
+// Note that, it differs that the Limit function start from 0 for "LIMIT" statement.
+func (d *PlatTaskProgressDao) Page(page, limit int) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *PlatTaskProgressDao) Batch(batch int) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Batch(batch)}
+}
+
+// Cache sets the cache feature for the model. It caches the result of the sql, which means
+// if there's another same sql request, it just reads and returns the result from cache, it
+// but not committed and executed into the database.
+//
+// If the parameter <duration> < 0, which means it clear the cache with given <name>.
+// If the parameter <duration> = 0, which means it never expires.
+// If the parameter <duration> > 0, which means it expires after <duration>.
+//
+// The optional parameter <name> is used to bind a name to the cache, which means you can later
+// control the cache like changing the <duration> or clearing the cache with specified <name>.
+//
+// Note that, the cache feature is disabled if the model is operating on a transaction.
+func (d *PlatTaskProgressDao) Cache(duration time.Duration, name ...string) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Cache(duration, name...)}
+}
+
+// Data sets the operation data for the model.
+// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
+// Eg:
+// Data("uid=10000")
+// Data("uid", 10000)
+// Data(g.Map{"uid": 10000, "name":"john"})
+// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
+func (d *PlatTaskProgressDao) Data(data ...interface{}) *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Data(data...)}
+}
+
+// All does "SELECT FROM ..." statement for the model.
+// It retrieves the records from table and returns the result as []*model.PlatTaskProgress.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskProgressDao) All(where ...interface{}) ([]*plat.PlatTaskProgress, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskProgress
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// One retrieves one record from table and returns the result as *model.PlatTaskProgress.
+// It returns nil if there's no record retrieved with the given conditions from table.
+//
+// The optional parameter <where> is the same as the parameter of M.Where function,
+// see M.Where.
+func (d *PlatTaskProgressDao) One(where ...interface{}) (*plat.PlatTaskProgress, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskProgress
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindOne retrieves and returns a single Record by M.WherePri and M.One.
+// Also see M.WherePri and M.One.
+func (d *PlatTaskProgressDao) FindOne(where ...interface{}) (*plat.PlatTaskProgress, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *plat.PlatTaskProgress
+	if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entity, nil
+}
+
+// FindAll retrieves and returns Result by by M.WherePri and M.All.
+// Also see M.WherePri and M.All.
+func (d *PlatTaskProgressDao) FindAll(where ...interface{}) ([]*plat.PlatTaskProgress, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*plat.PlatTaskProgress
+	if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return entities, nil
+}
+
+// Struct retrieves one record from table and converts it into given struct.
+// The parameter <pointer> should be type of *struct/**struct. If type **struct is given,
+// it can create the struct internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not nil.
+//
+// Eg:
+// user := new(User)
+// err  := dao.User.Where("id", 1).Struct(user)
+//
+// user := (*User)(nil)
+// err  := dao.User.Where("id", 1).Struct(&user)
+func (d *PlatTaskProgressDao) Struct(pointer interface{}, where ...interface{}) error {
+	return d.M.Struct(pointer, where...)
+}
+
+// Structs retrieves records from table and converts them into given struct slice.
+// The parameter <pointer> should be type of *[]struct/*[]*struct. It can create and fill the struct
+// slice internally during converting.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions
+// from table and <pointer> is not empty.
+//
+// Eg:
+// users := ([]User)(nil)
+// err   := dao.User.Structs(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Structs(&users)
+func (d *PlatTaskProgressDao) Structs(pointer interface{}, where ...interface{}) error {
+	return d.M.Structs(pointer, where...)
+}
+
+// Scan automatically calls Struct or Structs function according to the type of parameter <pointer>.
+// It calls function Struct if <pointer> is type of *struct/**struct.
+// It calls function Structs if <pointer> is type of *[]struct/*[]*struct.
+//
+// The optional parameter <where> is the same as the parameter of Model.Where function,
+// see Model.Where.
+//
+// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil.
+//
+// Eg:
+// user  := new(User)
+// err   := dao.User.Where("id", 1).Scan(user)
+//
+// user  := (*User)(nil)
+// err   := dao.User.Where("id", 1).Scan(&user)
+//
+// users := ([]User)(nil)
+// err   := dao.User.Scan(&users)
+//
+// users := ([]*User)(nil)
+// err   := dao.User.Scan(&users)
+func (d *PlatTaskProgressDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *PlatTaskProgressDao) Chunk(limit int, callback func(entities []*plat.PlatTaskProgress, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*plat.PlatTaskProgress
+		err = result.Structs(&entities)
+		if err == sql.ErrNoRows {
+			return false
+		}
+		return callback(entities, err)
+	})
+}
+
+// LockUpdate sets the lock for update for current operation.
+func (d *PlatTaskProgressDao) LockUpdate() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *PlatTaskProgressDao) LockShared() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *PlatTaskProgressDao) Unscoped() *PlatTaskProgressDao {
+	return &PlatTaskProgressDao{M: d.M.Unscoped()}
+}

+ 36 - 0
opms_parent/app/dao/plat/plat_followup.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platFollowupDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platFollowupDao struct {
+	internal.PlatFollowupDao
+}
+
+var (
+	// PlatFollowup is globally public accessible object for table plat_followup operations.
+	PlatFollowup = platFollowupDao{
+		internal.PlatFollowup,
+	}
+)
+
+type PlatFollowupDao struct {
+	internal.PlatFollowupDao
+}
+
+func NewPlatFollowupDao(tenant string) *PlatFollowupDao {
+	dao := internal.NewPlatFollowupDao(tenant)
+	return &PlatFollowupDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_followup_comment.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platFollowupCommentDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platFollowupCommentDao struct {
+	internal.PlatFollowupCommentDao
+}
+
+var (
+	// PlatFollowupComment is globally public accessible object for table plat_followup_comment operations.
+	PlatFollowupComment = platFollowupCommentDao{
+		internal.PlatFollowupComment,
+	}
+)
+
+type PlatFollowupCommentDao struct {
+	internal.PlatFollowupCommentDao
+}
+
+func NewPlatFollowupCommentDao(tenant string) *PlatFollowupCommentDao {
+	dao := internal.NewPlatFollowupCommentDao(tenant)
+	return &PlatFollowupCommentDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_followup_file.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platFollowupFileDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platFollowupFileDao struct {
+	internal.PlatFollowupFileDao
+}
+
+var (
+	// PlatFollowupFile is globally public accessible object for table plat_followup_file operations.
+	PlatFollowupFile = platFollowupFileDao{
+		internal.PlatFollowupFile,
+	}
+)
+
+type PlatFollowupFileDao struct {
+	internal.PlatFollowupFileDao
+}
+
+func NewPlatFollowupFileDao(tenant string) *PlatFollowupFileDao {
+	dao := internal.NewPlatFollowupFileDao(tenant)
+	return &PlatFollowupFileDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_task.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platTaskDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platTaskDao struct {
+	internal2.PlatTaskDao
+}
+
+var (
+	// PlatTask is globally public accessible object for table plat_task operations.
+	PlatTask = platTaskDao{
+		internal2.PlatTask,
+	}
+)
+
+type PlatTaskDao struct {
+	internal2.PlatTaskDao
+}
+
+func NewPlatTaskDao(tenant string) *PlatTaskDao {
+	dao := internal2.NewPlatTaskDao(tenant)
+	return &PlatTaskDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_task_comment.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platTaskCommentDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platTaskCommentDao struct {
+	internal2.PlatTaskCommentDao
+}
+
+var (
+	// PlatTaskComment is globally public accessible object for table plat_task_comment operations.
+	PlatTaskComment = platTaskCommentDao{
+		internal2.PlatTaskComment,
+	}
+)
+
+type PlatTaskCommentDao struct {
+	internal2.PlatTaskCommentDao
+}
+
+func NewPlatTaskCommentDao(tenant string) *PlatTaskCommentDao {
+	dao := internal2.NewPlatTaskCommentDao(tenant)
+	return &PlatTaskCommentDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_task_log.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platTaskLogDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platTaskLogDao struct {
+	internal2.PlatTaskLogDao
+}
+
+var (
+	// PlatTaskLog is globally public accessible object for table plat_task_log operations.
+	PlatTaskLog = platTaskLogDao{
+		internal2.PlatTaskLog,
+	}
+)
+
+type PlatTaskLogDao struct {
+	internal2.PlatTaskLogDao
+}
+
+func NewPlatTaskLogDao(tenant string) *PlatTaskLogDao {
+	dao := internal2.NewPlatTaskLogDao(tenant)
+	return &PlatTaskLogDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 36 - 0
opms_parent/app/dao/plat/plat_task_progress.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/dao/plat/internal"
+)
+
+// platTaskProgressDao is the manager for logic model data accessing
+// and custom defined data operations functions management. You can define
+// methods on it to extend its functionality as you wish.
+type platTaskProgressDao struct {
+	internal2.PlatTaskProgressDao
+}
+
+var (
+	// PlatTaskProgress is globally public accessible object for table plat_task_progress operations.
+	PlatTaskProgress = platTaskProgressDao{
+		internal2.PlatTaskProgress,
+	}
+)
+
+type PlatTaskProgressDao struct {
+	internal2.PlatTaskProgressDao
+}
+
+func NewPlatTaskProgressDao(tenant string) *PlatTaskProgressDao {
+	dao := internal2.NewPlatTaskProgressDao(tenant)
+	return &PlatTaskProgressDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 75 - 0
opms_parent/app/handler/plat/followup.go

@@ -0,0 +1,75 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type FollowUpHandler struct{}
+
+// GetList 获取列表
+func (h *FollowUpHandler) GetList(ctx context.Context, req *model.SearchPlatFollowupReq, rsp *comm_def.CommonMsg) error {
+	followupService, err := server.NewFollowupService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := followupService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// GetListByDay 获取列表
+func (h *FollowUpHandler) GetListByDay(ctx context.Context, req *model.SearchPlatFollowupReq, rsp *comm_def.CommonMsg) error {
+	followupService, err := server.NewFollowupService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := followupService.GetListByDay(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// Create 添加跟进记录
+func (h *FollowUpHandler) Create(ctx context.Context, req *model.AddPlatFollowupReq, rsp *comm_def.CommonMsg) error {
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	// 校验附件参数
+	for _, file := range req.Files {
+		if err := gvalid.CheckStruct(ctx, file, nil); err != nil {
+			return err
+		}
+	}
+	followupService, err := server.NewFollowupService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = followupService.Create(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}

+ 51 - 0
opms_parent/app/handler/plat/followup_comment.go

@@ -0,0 +1,51 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type FollowUpCommentHandler struct{}
+
+// GetList 获取列表
+func (h *FollowUpCommentHandler) GetList(ctx context.Context, req *model.SearchPlatFollowupCommentReq, rsp *comm_def.CommonMsg) error {
+	followupCommentService, err := server.NewFollowupCommentService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := followupCommentService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// Create 添加跟进评论
+func (h *FollowUpCommentHandler) Create(ctx context.Context, req *model.AddPlatFollowupCommentReq, rsp *comm_def.CommonMsg) error {
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	followupCommentService, err := server.NewFollowupCommentService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = followupCommentService.Create(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}

+ 30 - 0
opms_parent/app/handler/plat/followup_file.go

@@ -0,0 +1,30 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+)
+
+type FollowUpFileHandler struct{}
+
+// GetList 获取列表
+func (h *FollowUpFileHandler) GetList(ctx context.Context, req *model.SearchPlatFollowupFileReq, rsp *comm_def.CommonMsg) error {
+	followupFileService, err := server.NewFollowupFileService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := followupFileService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}

+ 74 - 0
opms_parent/app/handler/plat/task.go

@@ -0,0 +1,74 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type TaskHandler struct{}
+
+// GetList 获取列表
+func (h *TaskHandler) GetList(ctx context.Context, req *model.SearchPlatTaskReq, rsp *comm_def.CommonMsg) error {
+	taskService, err := server.NewTaskService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := taskService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// Create 添加任务
+func (h *TaskHandler) Create(ctx context.Context, req *model.AddPlatTaskReq, rsp *comm_def.CommonMsg) error {
+	if req.TaskStatus == "" {
+		req.TaskStatus = "10" // 任务状态(10进行中20关闭)
+	}
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	taskService, err := server.NewTaskService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = taskService.Create(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}
+
+// ChangeStatus 修改任务状态
+func (h *TaskHandler) ChangeStatus(ctx context.Context, req *model.ChangeStatusReq, rsp *comm_def.CommonMsg) error {
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	taskService, err := server.NewTaskService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = taskService.ChangeStatus(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}

+ 51 - 0
opms_parent/app/handler/plat/task_comment.go

@@ -0,0 +1,51 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type TaskCommentHandler struct{}
+
+// GetList 获取列表
+func (h *TaskCommentHandler) GetList(ctx context.Context, req *model.SearchPlatTaskCommentReq, rsp *comm_def.CommonMsg) error {
+	taskCommentService, err := server.NewTaskCommentService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := taskCommentService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// Create 添加任务评论
+func (h *TaskCommentHandler) Create(ctx context.Context, req *model.AddPlatTaskCommentReq, rsp *comm_def.CommonMsg) error {
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	taskCommentService, err := server.NewTaskCommentService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = taskCommentService.Create(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}

+ 30 - 0
opms_parent/app/handler/plat/task_log.go

@@ -0,0 +1,30 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+)
+
+type TaskLogHandler struct{}
+
+// GetList 获取列表
+func (h *TaskLogHandler) GetList(ctx context.Context, req *model.SearchPlatTaskLogReq, rsp *comm_def.CommonMsg) error {
+	taskLogService, err := server.NewTaskLogService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := taskLogService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}

+ 51 - 0
opms_parent/app/handler/plat/task_progress.go

@@ -0,0 +1,51 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/common_definition/comm_def"
+	model "dashoo.cn/micro/app/model/plat"
+	server "dashoo.cn/micro/app/service/plat"
+	"dashoo.cn/opms_libary/myerrors"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gvalid"
+)
+
+type TaskProgressHandler struct{}
+
+// GetList 获取列表
+func (h *TaskProgressHandler) GetList(ctx context.Context, req *model.SearchPlatTaskProgressReq, rsp *comm_def.CommonMsg) error {
+	taskProgressService, err := server.NewTaskProgressService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	g.Log().Info("搜索值", req)
+	total, list, err := taskProgressService.GetList(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}
+
+// Create 添加任务进展
+func (h *TaskProgressHandler) Create(ctx context.Context, req *model.AddPlatTaskProgressReq, rsp *comm_def.CommonMsg) error {
+	// 参数校验
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	taskProgressService, err := server.NewTaskProgressService(ctx)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	err = taskProgressService.Create(req)
+	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
+	if err != nil {
+		g.Log().Error(err)
+		return err
+	}
+	return nil
+}

+ 34 - 0
opms_parent/app/model/plat/internal/plat_followup.go

@@ -0,0 +1,34 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatFollowup is the golang structure for table plat_followup.
+type PlatFollowup struct {
+	Id            int         `orm:"id,primary"     json:"id"`            // 主键
+	FollowType    string      `orm:"follow_type"    json:"followType"`    // 跟进类型(10电话20邮件30拜访)
+	FollowDate    *gtime.Time `orm:"follow_date"    json:"followDate"`    // 跟进时间
+	FollowContent string      `orm:"follow_content" json:"followContent"` // 跟进内容
+	TargetId      int         `orm:"target_id"      json:"targetId"`      // 跟进对象ID
+	TargetType    string      `orm:"target_type"    json:"targetType"`    // 跟进对象类型(10客户,20项目,30合同,40回款)
+	TargetName    string      `orm:"target_name"    json:"targetName"`    // 跟进对象
+	CustId        int         `orm:"cust_id"        json:"custId"`        // 关联客户
+	CustName      string      `orm:"cust_name"      json:"custName"`      // 客户名称
+	ContactsId    int         `orm:"contacts_id"    json:"contactsId"`    // 关联联系人
+	ContactsName  string      `orm:"contacts_name"  json:"contactsName"`  // 联系人姓名
+	Reminders     string      `orm:"reminders"      json:"reminders"`     // 提醒对象
+	NextTime      *gtime.Time `orm:"next_time"      json:"nextTime"`      // 下次联系时间
+	Remark        string      `orm:"remark"         json:"remark"`        // 备注
+	CreatedBy     int         `orm:"created_by"     json:"createdBy"`     // 创建者
+	CreatedName   string      `orm:"created_name"   json:"createdName"`   // 创建人
+	CreatedTime   *gtime.Time `orm:"created_time"   json:"createdTime"`   // 创建时间
+	UpdatedBy     int         `orm:"updated_by"     json:"updatedBy"`     // 更新者
+	UpdatedName   string      `orm:"updated_name"   json:"updatedName"`   // 更新人
+	UpdatedTime   *gtime.Time `orm:"updated_time"   json:"updatedTime"`   // 更新时间
+	DeletedTime   *gtime.Time `orm:"deleted_time"   json:"deletedTime"`   // 删除时间
+}

+ 25 - 0
opms_parent/app/model/plat/internal/plat_followup_comment.go

@@ -0,0 +1,25 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatFollowupComment is the golang structure for table plat_followup_comment.
+type PlatFollowupComment struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	FollowId    int         `orm:"follow_id"    json:"followId"`    // 关联跟进
+	Content     string      `orm:"content"      json:"content"`     // 评论内容
+	Pid         int         `orm:"pid"          json:"pid"`         // 回复对象ID
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
+	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
+	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
+	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
+	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
+	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
+	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
+}

+ 26 - 0
opms_parent/app/model/plat/internal/plat_followup_file.go

@@ -0,0 +1,26 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatFollowupFile is the golang structure for table plat_followup_file.
+type PlatFollowupFile struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	FollowId    string      `orm:"follow_id"    json:"followId"`    // 关联跟进
+	FileName    string      `orm:"file_name"    json:"fileName"`    // 文件名
+	FileType    string      `orm:"file_type"    json:"fileType"`    // 文件类型
+	FileUrl     string      `orm:"file_url"     json:"fileUrl"`     // 文件地址
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
+	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
+	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
+	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
+	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
+	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
+	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
+}

+ 37 - 0
opms_parent/app/model/plat/internal/plat_task.go

@@ -0,0 +1,37 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatTask is the golang structure for table plat_task.
+type PlatTask struct {
+	Id               int         `orm:"id,primary"         json:"id"`               // 主键
+	TaskTitle        string      `orm:"task_title"         json:"taskTitle"`        // 任务标题
+	TaskType         string      `orm:"task_type"          json:"taskType"`         // 任务类型
+	TaskStatus       string      `orm:"task_status"        json:"taskStatus"`       // 任务状态(10进行中20关闭)
+	IsOverdue        string      `orm:"is_overdue"         json:"isOverdue"`        // 是否超期(10否20是)
+	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"`    // 任务开始时间
+	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"`      // 任务结束时间
+	TaskDesc         string      `orm:"task_desc"          json:"taskDesc"`         // 任务说明
+	SupervisorUserId int         `orm:"supervisor_user_id" json:"supervisorUserId"` // 督办人
+	WatchUserId      int         `orm:"watch_user_id"      json:"watchUserId"`      // 监办人
+	MainUserId       int         `orm:"main_user_id"       json:"mainUserId"`       // 负责人ID
+	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`      // 团队成员ID
+	TaskLabel        string      `orm:"task_label"         json:"taskLabel"`        // 任务标签,号拼接
+	TargetId         int         `orm:"target_id"          json:"targetId"`         // 关联对象ID
+	TargetType       string      `orm:"target_type"        json:"targetType"`       // 关联对象类型(10客户,20项目,30合同,40回款)
+	TargetName       string      `orm:"target_name"        json:"targetName"`       // 关联对象
+	Remark           string      `orm:"remark"             json:"remark"`           // 备注
+	CreatedBy        int         `orm:"created_by"         json:"createdBy"`        // 创建者
+	CreatedName      string      `orm:"created_name"       json:"createdName"`      // 创建人
+	CreatedTime      *gtime.Time `orm:"created_time"       json:"createdTime"`      // 创建时间
+	UpdatedBy        int         `orm:"updated_by"         json:"updatedBy"`        // 更新者
+	UpdatedName      string      `orm:"updated_name"       json:"updatedName"`      // 更新人
+	UpdatedTime      *gtime.Time `orm:"updated_time"       json:"updatedTime"`      // 更新时间
+	DeletedTime      *gtime.Time `orm:"deleted_time"       json:"deletedTime"`      // 删除时间
+}

+ 25 - 0
opms_parent/app/model/plat/internal/plat_task_comment.go

@@ -0,0 +1,25 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatTaskComment is the golang structure for table plat_task_comment.
+type PlatTaskComment struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	TaskId      int         `orm:"task_id"      json:"taskId"`      // 关联任务
+	Content     string      `orm:"content"      json:"content"`     // 评论内容
+	Pid         int         `orm:"pid"          json:"pid"`         // 回复对象ID
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
+	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
+	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
+	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
+	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
+	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
+	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
+}

+ 27 - 0
opms_parent/app/model/plat/internal/plat_task_log.go

@@ -0,0 +1,27 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatTaskLog is the golang structure for table plat_task_log.
+type PlatTaskLog struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	TaskId      int         `orm:"task_id"      json:"taskId"`      // 关联任务
+	NodeName    string      `orm:"node_name"    json:"nodeName"`    // 流程节点名称
+	Desc        string      `orm:"desc"         json:"desc"`        // 说明
+	StartTime   *gtime.Time `orm:"start_time"   json:"startTime"`   // 开始处理时间
+	EndTime     *gtime.Time `orm:"end_time"     json:"endTime"`     // 处理结束时间
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
+	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
+	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
+	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
+	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
+	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
+	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
+}

+ 26 - 0
opms_parent/app/model/plat/internal/plat_task_progress.go

@@ -0,0 +1,26 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatTaskProgress is the golang structure for table plat_task_progress.
+type PlatTaskProgress struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	TaskId      int         `orm:"task_id"      json:"taskId"`      // 关联任务
+	ProgDate    string      `orm:"prog_date"    json:"progDate"`    // 进展时间
+	ProgDesc    string      `orm:"prog_desc"    json:"progDesc"`    // 进展说明
+	ProgFile    string      `orm:"prog_file"    json:"progFile"`    // 相关附件
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+	CreatedBy   int         `orm:"created_by"   json:"createdBy"`   // 创建者
+	CreatedName string      `orm:"created_name" json:"createdName"` // 创建人
+	CreatedTime *gtime.Time `orm:"created_time" json:"createdTime"` // 创建时间
+	UpdatedBy   int         `orm:"updated_by"   json:"updatedBy"`   // 更新者
+	UpdatedName string      `orm:"updated_name" json:"updatedName"` // 更新人
+	UpdatedTime *gtime.Time `orm:"updated_time" json:"updatedTime"` // 更新时间
+	DeletedTime *gtime.Time `orm:"deleted_time" json:"deletedTime"` // 删除时间
+}

+ 57 - 0
opms_parent/app/model/plat/plat_followup.go

@@ -0,0 +1,57 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatFollowup is the golang structure for table plat_followup.
+type PlatFollowup internal.PlatFollowup
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatFollowupReq struct {
+	CustId string `json:"custId"`
+	TargetType string `son:"targetType"`
+	TargetId   string `json:"targetId"`
+	ManagerId   string `json:"managerId"`
+	DaysBeforeToday  int `json:"daysBeforeToday"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatFollowupReq struct {
+	FollowType    string      `orm:"follow_type"    json:"followType"    v:"required#跟进类型不能为空"`     // 跟进类型(10电话20邮件30拜访)
+	FollowDate    *gtime.Time `orm:"follow_date"    json:"followDate"    v:"required#跟进时间不能为空"`     // 跟进时间
+	FollowContent string      `orm:"follow_content" json:"followContent" v:"required#跟进内容不能为空"`     // 跟进内容
+	TargetId      int         `orm:"target_id"      json:"targetId"      v:"required|min:1#跟进对象ID不能为空|跟进对象ID不能为空"`   // 跟进对象ID
+	TargetType    string      `orm:"target_type"    json:"targetType"    v:"required#跟进对象类型不能为空"` // 跟进对象类型(10客户,20项目,30合同,40回款)
+	TargetName    string      `orm:"target_name"    json:"targetName"    v:"required#跟进对象不能为空"`     // 跟进对象
+	CustId        int         `orm:"cust_id"        json:"custId"        v:"required|min:1#关联客户不能为空|关联客户不能为空"`     // 关联客户
+	CustName      string      `orm:"cust_name"      json:"custName"      v:"required#客户名称不能为空"`     // 客户名称
+	ContactsId    int         `orm:"contacts_id"    json:"contactsId"    v:"required|min:1#关联联系人不能为空|关联联系人不能为空"`   // 关联联系人
+	ContactsName  string      `orm:"contacts_name"  json:"contactsName"  v:"required#联系人姓名不能为空"`   // 联系人姓名
+	Reminders     string      `orm:"reminders"      json:"reminders"`                                       // 提醒对象
+	NextTime      *gtime.Time `orm:"next_time"      json:"nextTime"`                                        // 下次联系时间
+	Remark        string      `orm:"remark"         json:"remark"`                                          // 备注
+	Files         []*AddPlatFollowupFileReq        `json:"files"`                                           // 附件
+}
+
+// 跟进记录详情展示,且展示第一级评论数据
+type FollowupInfo struct {
+	PlatFollowup
+	Comments      []*PlatFollowupComment        `json:"comments"`                                     // 评论
+	CommentNumber int                           `json:"commentNumber"`                                // 评论数量
+}
+
+// 跟进记录详情展示,按日期返回前端结果
+type FollowupInfoResp struct {
+	FollowDay     string   `json:"followDay"`     // 跟进记录的当天日期
+	FollowupList      []*FollowupInfo        `json:"followupList"`                                     // 跟进记录
+}

+ 30 - 0
opms_parent/app/model/plat/plat_followup_comment.go

@@ -0,0 +1,30 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// PlatFollowupComment is the golang structure for table plat_followup_comment.
+type PlatFollowupComment internal.PlatFollowupComment
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatFollowupCommentReq struct {
+	FollowId string `json:"followId"`
+	Pid  string     `json:"pid"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatFollowupCommentReq struct {
+	FollowId    string      `orm:"follow_id"    json:"followId"     v:"required#关联跟进不能为空"`  // 关联跟进
+	Content     string      `orm:"content"      json:"content"`                                     // 评论内容
+	Pid         int         `orm:"pid"          json:"pid"`                                         // 回复对象ID
+	Remark      string      `orm:"remark"       json:"remark"`                                      // 备注
+}

+ 30 - 0
opms_parent/app/model/plat/plat_followup_file.go

@@ -0,0 +1,30 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	"dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// PlatFollowupFile is the golang structure for table plat_followup_file.
+type PlatFollowupFile internal.PlatFollowupFile
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatFollowupFileReq struct {
+	FollowId string `json:"followId"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatFollowupFileReq struct {
+	//FollowId    string      `orm:"follow_id"    json:"followId"     v:"required#关联跟进不能为空"`  // 关联跟进
+	FileName    string      `orm:"file_name"    json:"fileName"     v:"required#文件名不能为空"`    // 文件名
+	FileType    string      `orm:"file_type"    json:"fileType"`                                    // 文件类型
+	FileUrl     string      `orm:"file_url"     json:"fileUrl"      v:"required#文件地址不能为空"`  // 文件地址
+	Remark      string      `orm:"remark"       json:"remark"`                                      // 备注
+}

+ 56 - 0
opms_parent/app/model/plat/plat_task.go

@@ -0,0 +1,56 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+	"github.com/gogf/gf/os/gtime"
+)
+
+// PlatTask is the golang structure for table plat_task.
+type PlatTask internal2.PlatTask
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatTaskReq struct {
+	TaskTitle string `json:"taskTitle"`
+	TaskType string `son:"taskType"`
+	TaskStatus   string `json:"taskStatus"`
+	IsOverdue   string `json:"isOverdue"`
+	MainUserId  string `json:"mainUserId"`
+	TargetId  string `json:"targetId"`
+	TargetType  string `json:"targetType"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatTaskReq struct {
+	TaskTitle        string      `orm:"task_title"         json:"taskTitle"    v:"required#任务标题不能为空"`        // 任务标题
+	TaskType         string      `orm:"task_type"          json:"taskType"    v:"required#任务类型不能为空"`         // 任务类型
+	TaskStatus       string      `orm:"task_status"        json:"taskStatus"    v:"required#任务状态不能为空"`       // 任务状态(10进行中20关闭)
+	IsOverdue        string      `orm:"is_overdue"         json:"isOverdue"`        // 是否超期(10否20是)
+	TaskStartDate    *gtime.Time `orm:"task_start_date"    json:"taskStartDate"    v:"required#任务开始时间不能为空"`    // 任务开始时间
+	TaskEndDate      *gtime.Time `orm:"task_end_date"      json:"taskEndDate"    v:"required#任务结束时间不能为空"`      // 任务结束时间
+	TaskDesc         string      `orm:"task_desc"          json:"taskDesc"`         // 任务说明
+	SupervisorUserId int         `orm:"supervisor_user_id" json:"supervisorUserId"    v:"required|min:1#督办人不能为空|督办人不能为空"` // 督办人
+	WatchUserId      int         `orm:"watch_user_id"      json:"watchUserId"`      // 监办人
+	MainUserId       int         `orm:"main_user_id"       json:"mainUserId"    v:"required|min:1#负责人ID不能为空|负责人ID不能为空"`       // 负责人ID
+	OwnerUserId      string      `orm:"owner_user_id"      json:"ownerUserId"`      // 团队成员ID
+	TaskLabel        string      `orm:"task_label"         json:"taskLabel"`        // 任务标签,号拼接
+	TargetId         int         `orm:"target_id"          json:"targetId"`         // 关联对象ID
+	TargetType       string      `orm:"target_type"        json:"targetType"`       // 关联对象类型(10客户,20项目,30合同,40回款)
+	TargetName       string      `orm:"target_name"        json:"targetName"`       // 关联对象
+	Remark           string      `orm:"remark"             json:"remark"`           // 备注
+}
+
+// 修改状态
+type ChangeStatusReq struct {
+	TaskId       string `json:"taskId"  v:"required#任务Id不能为空"`
+	Type         string  `json:"type"  v:"required#类型不能为空"`
+	OldStatus   string `json:"oldStatus"`
+	NowStatus   string `json:"nowStatus"  v:"required#状态不能为空"`
+}

+ 30 - 0
opms_parent/app/model/plat/plat_task_comment.go

@@ -0,0 +1,30 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// PlatTaskComment is the golang structure for table plat_task_comment.
+type PlatTaskComment internal2.PlatTaskComment
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatTaskCommentReq struct {
+	TaskId string `json:"taskId"`
+	Pid  string     `json:"pid"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatTaskCommentReq struct {
+	TaskId      string      `orm:"task_id"      json:"taskId"     v:"required#关联任务不能为空"`    // 关联任务
+	Content     string      `orm:"content"      json:"content"`                                     // 评论内容
+	Pid         int         `orm:"pid"          json:"pid"`                                         // 回复对象ID
+	Remark      string      `orm:"remark"       json:"remark"`                                      // 备注
+}

+ 21 - 0
opms_parent/app/model/plat/plat_task_log.go

@@ -0,0 +1,21 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// PlatTaskLog is the golang structure for table plat_task_log.
+type PlatTaskLog internal2.PlatTaskLog
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatTaskLogReq struct {
+	TaskId string `json:"taskId"`
+	request.PageReq
+}

+ 30 - 0
opms_parent/app/model/plat/plat_task_progress.go

@@ -0,0 +1,30 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package plat
+
+import (
+	internal2 "dashoo.cn/micro/app/model/plat/internal"
+	"dashoo.cn/opms_libary/request"
+)
+
+// PlatTaskProgress is the golang structure for table plat_task_progress.
+type PlatTaskProgress internal2.PlatTaskProgress
+
+// Fill with you ideas below.
+
+// 查询
+type SearchPlatTaskProgressReq struct {
+	TaskId string `json:"taskId"`
+	request.PageReq
+}
+
+// 添加数据
+type AddPlatTaskProgressReq struct {
+	TaskId      int         `orm:"task_id"      json:"taskId"     v:"required|min:1#关联任务不能为空|关联任务不能为空"`      // 关联任务
+	ProgDate    string      `orm:"prog_date"    json:"progDate"`    // 进展时间
+	ProgDesc    string      `orm:"prog_desc"    json:"progDesc"     v:"required#进展说明不能为空"`    // 进展说明
+	ProgFile    string      `orm:"prog_file"    json:"progFile"`    // 相关附件
+	Remark      string      `orm:"remark"       json:"remark"`      // 备注
+}

+ 185 - 0
opms_parent/app/service/plat/plat_followup.go

@@ -0,0 +1,185 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"database/sql"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gconv"
+	"strconv"
+	"strings"
+)
+
+type followupService struct {
+	*service.ContextService
+
+	Dao *plat.PlatFollowupDao
+}
+
+func NewFollowupService(ctx context.Context) (svc *followupService, err error) {
+	svc = new(followupService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatFollowupDao(svc.Tenant)
+	return svc, nil
+}
+
+// 跟进记录信息列表
+func (s *followupService) GetList(req *model.SearchPlatFollowupReq) (total int, followupList []*model.PlatFollowup, err error) {
+	followupModel := s.Dao.M
+
+	if req.CustId != "" {
+		followupModel = followupModel.Where("cust_id", req.CustId)
+	}
+	if req.TargetId != "" {
+		followupModel = followupModel.Where("target_id", req.TargetId)
+	}
+	if req.TargetType != "" {
+		followupModel = followupModel.Where("target_type", req.TargetType)
+	}
+	// 负责人查询
+	if req.ManagerId != "" {
+		followupModel = followupModel.Where("created_by", req.ManagerId)
+	}
+
+	total, err = followupModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = followupModel.Page(req.PageNum, req.PageSize).Order("follow_date DESC").Scan(&followupList)
+	return
+}
+
+// 添加信息
+func (s *followupService) Create(req *model.AddPlatFollowupReq) (err error) {
+	platFollowup := new(model.PlatFollowup)
+	var files []*model.PlatFollowupFile
+	if err = gconv.Struct(req, platFollowup); err != nil {
+		return
+	}
+	// 填充创建信息
+	service.SetCreatedInfo(platFollowup, s.GetCxtUserId(), s.GetCxtUserName())
+	// 填充更新信息
+	//service.SetUpdatedInfo(platFollowup, s.GetCxtUserId(), s.GetCxtUserName())
+	Model := s.Dao.M
+	res, err := Model.Insert(platFollowup)
+	if err != nil {
+		return
+	}
+	// 更新附件数据
+	id, _ := res.LastInsertId()
+	for _, file := range req.Files {
+		var fileData model.PlatFollowupFile
+		if err = gconv.Struct(file, &fileData); err != nil {
+			return
+		}
+		fileData.FollowId = strconv.Itoa(int(id))
+		// 填充创建信息
+		service.SetCreatedInfo(&fileData, s.GetCxtUserId(), s.GetCxtUserName())
+		// 填充更新信息
+		//service.SetUpdatedInfo(fileData, s.GetCxtUserId(), s.GetCxtUserName())
+		files = append(files, &fileData)
+	}
+
+	// 保存附件信息
+	if len(files) > 0 {
+		_, err = s.Dao.DB.Insert(plat.PlatFollowupFile.Table, files)
+	}
+
+	return
+}
+
+// 跟进记录信息列表:按照日期显示,并附带评论
+func (s *followupService) GetListByDay(req *model.SearchPlatFollowupReq) (total int, followupList []*model.FollowupInfoResp, err error) {
+	followupModel := s.Dao.M
+
+	if req.CustId != "" {
+		followupModel = followupModel.Where("cust_id", req.CustId)
+	}
+	if req.TargetId != "" {
+		followupModel = followupModel.Where("target_id", req.TargetId)
+	}
+	if req.TargetType != "" {
+		followupModel = followupModel.Where("target_type", req.TargetType)
+	}
+	// 负责人查询
+	if req.ManagerId != "" {
+		followupModel = followupModel.Where("created_by", req.ManagerId)
+	}
+	// 日期条件
+	if req.DaysBeforeToday >= 0 { // 获取前N天的跟进记录
+		now := gtime.Now()
+		begin := now.AddDate(0, 0, -req.DaysBeforeToday).Format("Y-m-d 00:00:00")
+		followupModel = followupModel.Where("follow_date>=?", begin)
+	}
+	// 获取日期区间范围内的记录
+	if req.BeginTime != "" && req.EndTime != "" {
+		begin := strings.Split(req.BeginTime, " ")[0] + " 00:00:00"
+		end := strings.Split(req.EndTime, " ")[0] + " 23:59:59"
+		followupModel = followupModel.Where("follow_date>=? AND follow_date<=?", begin, end)
+	}
+
+	//total, err = followupModel.Count()
+	//if err != nil {
+	//	g.Log().Error(err)
+	//	err = gerror.New("获取总行数失败")
+	//	return
+	//}
+
+	// 查询原始记录
+	var originalFollowupList []model.FollowupInfo
+	err = followupModel.Order("follow_date DESC").Scan(&originalFollowupList)
+	if err != nil && err != sql.ErrNoRows {
+		return
+	}
+	// 查询一级评论
+	var comments []model.PlatFollowupComment
+	err = s.Dao.InnerJoin(plat.PlatFollowupComment.Table, "plat_followup.id=plat_followup_comment.follow_id").Where("plat_followup_comment.pid=0 OR plat_followup_comment.pid IS NULL").Fields("plat_followup_comment.*").Structs(&comments)
+	if err != nil && err != sql.ErrNoRows {
+		return
+	}
+	// 构造数据
+	var days []string
+	followupMap := make(map[string][]*model.FollowupInfo, 0)
+	commentMap := make(map[int][]*model.PlatFollowupComment, 0)
+	// 评论数据map
+	for index, comment := range comments {
+		if _, ok := commentMap[comment.FollowId]; !ok {
+			commentMap[comment.FollowId] = make([]*model.PlatFollowupComment, 0)
+		}
+		commentMap[comment.FollowId] = append(commentMap[comment.FollowId], &comments[index])
+	}
+	// 跟进记录map
+	for index, followup := range originalFollowupList {
+		if _, ok := followupMap[followup.FollowDate.Format("Y-m-d")]; !ok {
+			days = append(days, followup.FollowDate.Format("Y-m-d"))
+			followupMap[followup.FollowDate.Format("Y-m-d")] = make([]*model.FollowupInfo, 0)
+		}
+		if followup.Comments == nil {
+			originalFollowupList[index].Comments = make([]*model.PlatFollowupComment, 0)
+		}
+		// 为跟进记录填充评论数据
+		if _, ok := commentMap[followup.Id]; ok {
+			originalFollowupList[index].Comments = append(originalFollowupList[index].Comments, commentMap[followup.Id]...)
+		}
+		originalFollowupList[index].CommentNumber = len(originalFollowupList[index].Comments)
+		followupMap[followup.FollowDate.Format("Y-m-d")] = append(followupMap[followup.FollowDate.Format("Y-m-d")], &originalFollowupList[index])
+	}
+
+	for _, day := range days {
+		var followup model.FollowupInfoResp
+		followup.FollowDay = day
+		followup.FollowupList = followupMap[day]
+		followupList = append(followupList, &followup)
+	}
+
+	return
+}

+ 66 - 0
opms_parent/app/service/plat/plat_followup_comment.go

@@ -0,0 +1,66 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gconv"
+)
+
+type followupCommentService struct {
+	*service.ContextService
+
+	Dao *plat.PlatFollowupCommentDao
+}
+
+func NewFollowupCommentService(ctx context.Context) (svc *followupCommentService, err error) {
+	svc = new(followupCommentService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatFollowupCommentDao(svc.Tenant)
+	return svc, nil
+}
+
+// 跟进记录留言信息列表
+func (s *followupCommentService) GetList(req *model.SearchPlatFollowupCommentReq) (total int, followupCommentList []*model.PlatFollowupComment, err error) {
+	followupCommentModel := s.Dao.M
+
+	if req.FollowId != "" {
+		followupCommentModel = followupCommentModel.Where("follow_id", req.FollowId)
+	}
+	if req.Pid != "" {
+		followupCommentModel = followupCommentModel.Where("pid", req.Pid)
+	}
+	total, err = followupCommentModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = followupCommentModel.Order("created_time DESC").Scan(&followupCommentList)
+	return
+}
+
+// 添加信息
+func (s *followupCommentService) Create(req *model.AddPlatFollowupCommentReq) (err error) {
+	platFollowupComment := new(model.PlatFollowupComment)
+	if err = gconv.Struct(req, platFollowupComment); err != nil {
+		return
+	}
+	// 填充创建信息
+	service.SetCreatedInfo(platFollowupComment, s.GetCxtUserId(), s.GetCxtUserName())
+	// 填充更新信息
+	//service.SetUpdatedInfo(platFollowupComment, s.GetCxtUserId(), s.GetCxtUserName())
+	Model := s.Dao.M
+	_, err = Model.Insert(platFollowupComment)
+	if err != nil {
+		return
+	}
+
+	return
+}

+ 43 - 0
opms_parent/app/service/plat/plat_followup_file.go

@@ -0,0 +1,43 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+)
+
+type followupFileService struct {
+	*service.ContextService
+
+	Dao *plat.PlatFollowupFileDao
+}
+
+func NewFollowupFileService(ctx context.Context) (svc *followupFileService, err error) {
+	svc = new(followupFileService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatFollowupFileDao(svc.Tenant)
+	return svc, nil
+}
+
+// 跟进记录附件信息列表
+func (s *followupFileService) GetList(req *model.SearchPlatFollowupFileReq) (total int, followupFileList []*model.PlatFollowupFile, err error) {
+	followupFileModel := s.Dao.M
+
+	if req.FollowId != "" {
+		followupFileModel = followupFileModel.Where("follow_id", req.FollowId)
+	}
+	total, err = followupFileModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = followupFileModel.Order("created_time ASC").Scan(&followupFileList)
+	return
+}

+ 182 - 0
opms_parent/app/service/plat/plat_task.go

@@ -0,0 +1,182 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"database/sql"
+	"fmt"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gconv"
+	"strconv"
+)
+
+type taskService struct {
+	*service.ContextService
+
+	Dao *plat.PlatTaskDao
+}
+
+func NewTaskService(ctx context.Context) (svc *taskService, err error) {
+	svc = new(taskService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatTaskDao(svc.Tenant)
+	return svc, nil
+}
+
+// 任务信息列表
+func (s *taskService) GetList(req *model.SearchPlatTaskReq) (total int, TaskList []*model.PlatTask, err error) {
+	TaskModel := s.Dao.M
+	if req.TaskTitle != "" {
+		TaskModel = TaskModel.Where("task_title LIKE ?", "%" + req.TaskTitle + "%")
+	}
+	if req.TaskType != "" {
+		TaskModel = TaskModel.Where("task_type", req.TaskType)
+	}
+	if req.TaskStatus != "" {
+		TaskModel = TaskModel.Where("task_status", req.TaskStatus)
+	}
+	if req.IsOverdue != "" {
+		TaskModel = TaskModel.Where("is_overdue", req.IsOverdue)
+	}
+	if req.MainUserId != "" {
+		TaskModel = TaskModel.Where("main_user_id", req.MainUserId)
+	}
+	if req.TargetId != "" {
+		TaskModel = TaskModel.Where("target_id", req.TargetId)
+	}
+	if req.TargetType != "" {
+		TaskModel = TaskModel.Where("target_type", req.TargetType)
+	}
+	total, err = TaskModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = TaskModel.Page(req.PageNum, req.PageSize).Order("created_time DESC").Scan(&TaskList)
+	return
+}
+
+// 添加信息
+func (s *taskService) Create(req *model.AddPlatTaskReq) (err error) {
+	platTask := new(model.PlatTask)
+	if err = gconv.Struct(req, platTask); err != nil {
+		return
+	}
+	platTask.IsOverdue = "10" // 是否超期(10否20是)
+	if platTask.TaskStartDate == nil {
+		platTask.TaskStartDate = gtime.Now()
+	}
+	// 填充创建信息
+	service.SetCreatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
+	// 填充更新信息
+	//service.SetUpdatedInfo(platTask, s.GetCxtUserId(), s.GetCxtUserName())
+	Model := s.Dao.M
+	res, err := Model.Insert(platTask)
+	if err != nil {
+		return
+	}
+	// 流程日志
+	id, _ := res.LastInsertId()
+	err = CreateTaskLog(s, nil, int(id), s.GetCxtUserId(), s.GetCxtUserName(), "创建任务", "创建任务成功", "")
+
+	return
+}
+
+// 修改状态
+func (s *taskService) ChangeStatus(req *model.ChangeStatusReq) (err error) {
+	data := ""
+	where := fmt.Sprintf("id='%v'", req.TaskId)
+	nodeName := "状态修改"
+	desc := "修改成功"
+	// 类型合规判断
+	if req.Type == "TaskStatus" {
+		data = fmt.Sprintf("task_status='%v'", req.NowStatus)
+		nodeName = "任务状态修改"
+		if req.NowStatus == "20" {
+			desc = "任务关闭"
+		} else if req.NowStatus == "30" {
+			desc = "任务完成"
+			data += fmt.Sprintf(",task_end_date='%v'", gtime.Now().Format("Y-m-d H:i:s"))
+		}
+	} else if req.Type == "IsOverdue" {
+		nodeName = "超期状态修改"
+		if req.NowStatus == "20" {
+			desc = "任务超期"
+		}
+		data = fmt.Sprintf("is_overdue='%v'", req.NowStatus)
+	} else {
+		return fmt.Errorf("类型不匹配,请仔细检查")
+	}
+	// 读取现有数据
+	task, err := s.Dao.FindOne(where)
+	if err != nil {
+		return err
+	}
+	// 状态数据一致性判断
+	if (req.Type == "TaskStatus" && task.TaskStatus != req.OldStatus) || (req.Type == "IsOverdue" && task.IsOverdue != req.OldStatus) {
+		return fmt.Errorf("状态不匹配,进行该操作")
+	}
+	// 更新数据
+	_, err = s.Dao.Update(data, where)
+	if err != nil {
+		return
+	}
+
+	// 流程日志
+	taskId, _ := strconv.Atoi(req.TaskId)
+	err = CreateTaskLog(s, nil, taskId, s.GetCxtUserId(), s.GetCxtUserName(), nodeName, desc, "")
+
+	return
+}
+
+// 任务日志创建方法
+func CreateTaskLog(s1 *taskService, s2 *taskProgressService, taskId, userId int, userName, nodeName, desc, remark string) (err error) {
+	var log model.PlatTaskLog
+	startTime := gtime.Now()
+	endTime := startTime
+	// 默认为当前时间,然后随已有日志情况进行更新
+	if s1 != nil {
+		logs, err := s1.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
+		if err != nil && err != sql.ErrNoRows {
+			return err
+		}
+		if len(logs) > 0 {
+			startTime = logs[0]["end_time"].GTime()
+		}
+	} else {
+		logs, err := s2.Dao.DB.Model(plat.PlatTaskLog.Table).Where(fmt.Sprintf("task_id='%v'", taskId)).Order("created_time DESC").FindAll()
+		if err != nil && err != sql.ErrNoRows {
+			return err
+		}
+		if len(logs) > 0 {
+			startTime = logs[0]["end_time"].GTime()
+		}
+	}
+
+	// 填入日志相关数据
+	log.TaskId = taskId
+	log.NodeName = nodeName
+	log.Desc = desc
+	log.StartTime = startTime
+	log.EndTime = endTime
+	log.Remark = remark
+	log.CreatedTime = endTime
+	log.CreatedName = userName
+	log.CreatedBy = userId
+
+	if s1 != nil {
+		_, err = s1.Dao.DB.Save(plat.PlatTaskLog.Table, log)
+	} else {
+		_, err = s2.Dao.DB.Save(plat.PlatTaskLog.Table, log)
+	}
+
+	return err
+}

+ 66 - 0
opms_parent/app/service/plat/plat_task_comment.go

@@ -0,0 +1,66 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gconv"
+)
+
+type taskCommentService struct {
+	*service.ContextService
+
+	Dao *plat.PlatTaskCommentDao
+}
+
+func NewTaskCommentService(ctx context.Context) (svc *taskCommentService, err error) {
+	svc = new(taskCommentService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatTaskCommentDao(svc.Tenant)
+	return svc, nil
+}
+
+// 任务评论信息列表
+func (s *taskCommentService) GetList(req *model.SearchPlatTaskCommentReq) (total int, TaskCommentList []*model.PlatTaskComment, err error) {
+	TaskCommentModel := s.Dao.M
+
+	if req.TaskId != "" {
+		TaskCommentModel = TaskCommentModel.Where("task_id", req.TaskId)
+	}
+	if req.Pid != "" {
+		TaskCommentModel = TaskCommentModel.Where("pid", req.Pid)
+	}
+	total, err = TaskCommentModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = TaskCommentModel.Order("created_time DESC").Scan(&TaskCommentList)
+	return
+}
+
+// 添加信息
+func (s *taskCommentService) Create(req *model.AddPlatTaskCommentReq) (err error) {
+	platTaskComment := new(model.PlatTaskComment)
+	if err = gconv.Struct(req, platTaskComment); err != nil {
+		return
+	}
+	// 填充创建信息
+	service.SetCreatedInfo(platTaskComment, s.GetCxtUserId(), s.GetCxtUserName())
+	// 填充更新信息
+	//service.SetUpdatedInfo(platTaskComment, s.GetCxtUserId(), s.GetCxtUserName())
+	Model := s.Dao.M
+	_, err = Model.Insert(platTaskComment)
+	if err != nil {
+		return
+	}
+
+	return
+}

+ 43 - 0
opms_parent/app/service/plat/plat_task_log.go

@@ -0,0 +1,43 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+)
+
+type taskLogService struct {
+	*service.ContextService
+
+	Dao *plat.PlatTaskLogDao
+}
+
+func NewTaskLogService(ctx context.Context) (svc *taskLogService, err error) {
+	svc = new(taskLogService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatTaskLogDao(svc.Tenant)
+	return svc, nil
+}
+
+// 任务日志信息列表
+func (s *taskLogService) GetList(req *model.SearchPlatTaskLogReq) (total int, TaskLogList []*model.PlatTaskLog, err error) {
+	TaskLogModel := s.Dao.M
+
+	if req.TaskId != "" {
+		TaskLogModel = TaskLogModel.Where("task_id", req.TaskId)
+	}
+	total, err = TaskLogModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = TaskLogModel.Order("created_time DESC").Scan(&TaskLogList)
+	return
+}

+ 66 - 0
opms_parent/app/service/plat/plat_task_progress.go

@@ -0,0 +1,66 @@
+package plat
+
+import (
+	"context"
+	"dashoo.cn/micro/app/dao/plat"
+	model "dashoo.cn/micro/app/model/plat"
+	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gconv"
+)
+
+type taskProgressService struct {
+	*service.ContextService
+
+	Dao *plat.PlatTaskProgressDao
+}
+
+func NewTaskProgressService(ctx context.Context) (svc *taskProgressService, err error) {
+	svc = new(taskProgressService)
+	if svc.ContextService, err = svc.Init(ctx); err != nil {
+		return nil, err
+	}
+	svc.Dao = plat.NewPlatTaskProgressDao(svc.Tenant)
+	return svc, nil
+}
+
+// 任务进展信息列表
+func (s *taskProgressService) GetList(req *model.SearchPlatTaskProgressReq) (total int, taskProgressList []*model.PlatTaskProgress, err error) {
+	taskProgressModel := s.Dao.M
+
+	if req.TaskId != "" {
+		taskProgressModel = taskProgressModel.Where("task_id", req.TaskId)
+	}
+	total, err = taskProgressModel.Count()
+	if err != nil {
+		g.Log().Error(err)
+		err = gerror.New("获取总行数失败")
+		return
+	}
+
+	err = taskProgressModel.Order("created_time DESC").Scan(&taskProgressList)
+	return
+}
+
+// 添加信息
+func (s *taskProgressService) Create(req *model.AddPlatTaskProgressReq) (err error) {
+	platTaskProgress := new(model.PlatTaskProgress)
+	if err = gconv.Struct(req, platTaskProgress); err != nil {
+		return
+	}
+	// 填充创建信息
+	service.SetCreatedInfo(platTaskProgress, s.GetCxtUserId(), s.GetCxtUserName())
+	// 填充更新信息
+	//service.SetUpdatedInfo(platTaskProgress, s.GetCxtUserId(), s.GetCxtUserName())
+	Model := s.Dao.M
+	_, err = Model.Insert(platTaskProgress)
+	if err != nil {
+		return
+	}
+
+	// 流程日志
+	err = CreateTaskLog(nil, s, req.TaskId, s.GetCxtUserId(), s.GetCxtUserName(), "添加进展", "任务进展更新", "")
+
+	return
+}

+ 11 - 0
opms_parent/main.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"context"
+	"dashoo.cn/micro/app/handler/plat"
 
 	"dashoo.cn/micro/app/handler/base"
 	"dashoo.cn/micro/app/handler/cust"
@@ -22,7 +23,17 @@ func main() {
 	s.RegisterName("Region", new(base.RegionHandler), "")
 	s.RegisterName("Customer", new(cust.CustomerHeader), "")
 	s.RegisterName("Contant", new(cust.CustomerContantHeader), "")
+<<<<<<< HEAD
 	s.RegisterName("Belong", new(cust.CustBelongHeader), "")
+=======
+	s.RegisterName("FollowUp", new(plat.FollowUpHandler), "")
+	s.RegisterName("FollowUpComment", new(plat.FollowUpCommentHandler), "")
+	s.RegisterName("FollowUpFile", new(plat.FollowUpFileHandler), "")
+	s.RegisterName("Task", new(plat.TaskHandler), "")
+	s.RegisterName("TaskComment", new(plat.TaskCommentHandler), "")
+	s.RegisterName("TaskLog", new(plat.TaskLogHandler), "")
+	s.RegisterName("TaskProgress", new(plat.TaskProgressHandler), "")
+>>>>>>> 55eb68c6490055b84c20771a167be1896e34fb07
 
 	// 注册服务对象
 	//s.RegisterName("Auth", new(handler.Auth), "")