Преглед на файлове

feat: 运维事件支持事件级附件上传

程健 преди 1 месец
родител
ревизия
dd20c1e3fa

+ 432 - 0
opms_parent/app/dao/opsdev/internal/ops_delivery_project_delegate.go

@@ -0,0 +1,432 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY.
+// ==========================================================================
+
+package internal
+
+import (
+	"context"
+	"database/sql"
+	"time"
+
+	"dashoo.cn/opms_parent/app/model/opsdev"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/frame/gmvc"
+)
+
+// OpsDeliveryProjectDelegateDao is the manager for logic model data accessing
+// and custom defined data operations functions management.
+type OpsDeliveryProjectDelegateDao struct {
+	gmvc.M
+	DB      gdb.DB
+	Table   string
+	Columns opsDeliveryProjectDelegateColumns
+}
+
+// OpsDeliveryProjectDelegateColumns defines and stores column names for table ops_delivery_project_delegate.
+type opsDeliveryProjectDelegateColumns struct {
+	Id          string // 主键
+	ProjectId   string // 项目id
+	ProjectName string // 项目名称
+	UserId      string // 被授权人ID
+	UserName    string // 被授权人姓名
+	Remark      string // 备注
+	CreatedBy   string // 创建者
+	CreatedName string // 创建人
+	CreatedTime string // 创建时间
+	UpdatedBy   string // 更新者
+	UpdatedName string // 更新人
+	UpdatedTime string // 更新时间
+	DeletedTime string // 删除时间
+}
+
+var (
+	// OpsDeliveryProjectDelegate is globally public accessible object for table ops_delivery_project_delegate operations.
+	OpsDeliveryProjectDelegate = OpsDeliveryProjectDelegateDao{
+		M:     g.DB("default").Model("ops_delivery_project_delegate").Safe(),
+		DB:    g.DB("default"),
+		Table: "ops_delivery_project_delegate",
+		Columns: opsDeliveryProjectDelegateColumns{
+			Id:          "id",
+			ProjectId:   "project_id",
+			ProjectName: "project_name",
+			UserId:      "user_id",
+			UserName:    "user_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 NewOpsDeliveryProjectDelegateDao(tenant string) OpsDeliveryProjectDelegateDao {
+	var dao OpsDeliveryProjectDelegateDao
+	dao = OpsDeliveryProjectDelegateDao{
+		M:     g.DB(tenant).Model("ops_delivery_project_delegate").Safe(),
+		DB:    g.DB(tenant),
+		Table: "ops_delivery_project_delegate",
+		Columns: opsDeliveryProjectDelegateColumns{
+			Id:          "id",
+			ProjectId:   "project_id",
+			ProjectName: "project_name",
+			UserId:      "user_id",
+			UserName:    "user_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 *OpsDeliveryProjectDelegateDao) Ctx(ctx context.Context) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Ctx(ctx)}
+}
+
+// As sets an alias name for current table.
+func (d *OpsDeliveryProjectDelegateDao) As(as string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.As(as)}
+}
+
+// TX sets the transaction for current operation.
+func (d *OpsDeliveryProjectDelegateDao) TX(tx *gdb.TX) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.TX(tx)}
+}
+
+// Master marks the following operation on master node.
+func (d *OpsDeliveryProjectDelegateDao) Master() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Slave() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Slave()}
+}
+
+// Args sets custom arguments for model operation.
+func (d *OpsDeliveryProjectDelegateDao) Args(args ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) LeftJoin(table ...string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) RightJoin(table ...string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) InnerJoin(table ...string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Fields(fieldNamesOrMapStruct ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)}
+}
+
+// Option sets the extra operation option for the model.
+func (d *OpsDeliveryProjectDelegateDao) Option(option int) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) OmitEmpty() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.OmitEmpty()}
+}
+
+// Filter marks filtering the fields which does not exist in the fields of the operated table.
+func (d *OpsDeliveryProjectDelegateDao) Filter() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Where(where interface{}, args ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) WherePri(where interface{}, args ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.WherePri(where, args...)}
+}
+
+// And adds "AND" condition to the where statement.
+func (d *OpsDeliveryProjectDelegateDao) And(where interface{}, args ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.And(where, args...)}
+}
+
+// Or adds "OR" condition to the where statement.
+func (d *OpsDeliveryProjectDelegateDao) Or(where interface{}, args ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Or(where, args...)}
+}
+
+// Group sets the "GROUP BY" statement for the model.
+func (d *OpsDeliveryProjectDelegateDao) Group(groupBy string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Group(groupBy)}
+}
+
+// Order sets the "ORDER BY" statement for the model.
+func (d *OpsDeliveryProjectDelegateDao) Order(orderBy ...string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Limit(limit ...int) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Offset(offset int) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Page(page, limit int) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Page(page, limit)}
+}
+
+// Batch sets the batch operation number for the model.
+func (d *OpsDeliveryProjectDelegateDao) Batch(batch int) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Cache(duration time.Duration, name ...string) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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 *OpsDeliveryProjectDelegateDao) Data(data ...interface{}) *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{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.OpsDeliveryProjectDelegate.
+// 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 *OpsDeliveryProjectDelegateDao) All(where ...interface{}) ([]*opsdev.OpsDeliveryProjectDelegate, error) {
+	all, err := d.M.All(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*opsdev.OpsDeliveryProjectDelegate
+	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.OpsDeliveryProjectDelegate.
+// 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 *OpsDeliveryProjectDelegateDao) One(where ...interface{}) (*opsdev.OpsDeliveryProjectDelegate, error) {
+	one, err := d.M.One(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *opsdev.OpsDeliveryProjectDelegate
+	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 *OpsDeliveryProjectDelegateDao) FindOne(where ...interface{}) (*opsdev.OpsDeliveryProjectDelegate, error) {
+	one, err := d.M.FindOne(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entity *opsdev.OpsDeliveryProjectDelegate
+	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 *OpsDeliveryProjectDelegateDao) FindAll(where ...interface{}) ([]*opsdev.OpsDeliveryProjectDelegate, error) {
+	all, err := d.M.FindAll(where...)
+	if err != nil {
+		return nil, err
+	}
+	var entities []*opsdev.OpsDeliveryProjectDelegate
+	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 *OpsDeliveryProjectDelegateDao) 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 *OpsDeliveryProjectDelegateDao) 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 *OpsDeliveryProjectDelegateDao) Scan(pointer interface{}, where ...interface{}) error {
+	return d.M.Scan(pointer, where...)
+}
+
+// Chunk iterates the table with given size and callback function.
+func (d *OpsDeliveryProjectDelegateDao) Chunk(limit int, callback func(entities []*opsdev.OpsDeliveryProjectDelegate, err error) bool) {
+	d.M.Chunk(limit, func(result gdb.Result, err error) bool {
+		var entities []*opsdev.OpsDeliveryProjectDelegate
+		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 *OpsDeliveryProjectDelegateDao) LockUpdate() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.LockUpdate()}
+}
+
+// LockShared sets the lock in share mode for current operation.
+func (d *OpsDeliveryProjectDelegateDao) LockShared() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.LockShared()}
+}
+
+// Unscoped enables/disables the soft deleting feature.
+func (d *OpsDeliveryProjectDelegateDao) Unscoped() *OpsDeliveryProjectDelegateDao {
+	return &OpsDeliveryProjectDelegateDao{M: d.M.Unscoped()}
+}

+ 36 - 0
opms_parent/app/dao/opsdev/ops_delivery_project_delegate.go

@@ -0,0 +1,36 @@
+// ============================================================================
+// This is auto-generated by gf cli tool only once. Fill this file as you wish.
+// ============================================================================
+
+package opsdev
+
+import (
+	"dashoo.cn/opms_parent/app/dao/opsdev/internal"
+)
+
+// opsDeliveryProjectDelegateDao 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 opsDeliveryProjectDelegateDao struct {
+	internal.OpsDeliveryProjectDelegateDao
+}
+
+var (
+	// OpsDeliveryProjectDelegate is globally public accessible object for table ops_delivery_project_delegate operations.
+	OpsDeliveryProjectDelegate = opsDeliveryProjectDelegateDao{
+		internal.OpsDeliveryProjectDelegate,
+	}
+)
+
+type OpsDeliveryProjectDelegateDao struct {
+	internal.OpsDeliveryProjectDelegateDao
+}
+
+func NewOpsDeliveryProjectDelegateDao(tenant string) *OpsDeliveryProjectDelegateDao {
+	dao := internal.NewOpsDeliveryProjectDelegateDao(tenant)
+	return &OpsDeliveryProjectDelegateDao{
+		dao,
+	}
+}
+
+// Fill with you ideas below.

+ 26 - 0
opms_parent/app/model/opsdev/internal/ops_delivery_project_delegate.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"
+)
+
+// OpsDeliveryProjectDelegate is the golang structure for table ops_delivery_project_delegate.
+type OpsDeliveryProjectDelegate struct {
+	Id          int         `orm:"id,primary"   json:"id"`          // 主键
+	ProjectId   int         `orm:"project_id"   json:"projectId"`   // 项目id
+	ProjectName string      `orm:"project_name" json:"projectName"` // 项目名称
+	UserId      int         `orm:"user_id"      json:"userId"`      // 被授权人ID
+	UserName    string      `orm:"user_name"    json:"userName"`    // 被授权人姓名
+	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"` // 删除时间
+}

+ 1 - 0
opms_parent/app/model/opsdev/operation.go

@@ -144,6 +144,7 @@ type OpsOperationEventHistorySearchReq struct {
 	OpsUserName      string `json:"opsUserName"`      // 处理人(模糊搜索)
 	BeginTime        string `json:"beginTime"`        // 反馈开始时间
 	EndTime          string `json:"endTime"`          // 反馈结束时间
+	ContractId       string `json:"contractId"`       // 合同ID
 	request.PageReq
 }
 

+ 14 - 0
opms_parent/app/model/opsdev/ops_delivery_project_delegate.go

@@ -0,0 +1,14 @@
+// ==========================================================================
+// This is auto-generated by gf cli tool. Fill this file as you wish.
+// ==========================================================================
+
+package opsdev
+
+import (
+	"dashoo.cn/opms_parent/app/model/opsdev/internal"
+)
+
+// OpsDeliveryProjectDelegate is the golang structure for table ops_delivery_project_delegate.
+type OpsDeliveryProjectDelegate internal.OpsDeliveryProjectDelegate
+
+// Fill with you ideas below.

+ 4 - 1
opms_parent/app/model/opsdev/ops_operation_event.go

@@ -9,5 +9,8 @@ import (
 )
 
 // OpsOperationEvent is the golang structure for table ops_operation_event.
-type OpsOperationEvent internal.OpsOperationEvent
+type OpsOperationEvent struct {
+	internal.OpsOperationEvent
+	Attachments []*OpsOperationEventAttachment `json:"attachments"` // 事件级附件列表
+}
 

+ 1 - 1
opms_parent/app/service/contract/ctr_contract.go

@@ -1837,7 +1837,7 @@ func (s CtrContractService) SearchContract(ctx context.Context, req *model.CtrCo
 		m = m.Where("(c.contract_code LIKE ? OR c.cust_name LIKE ? OR c.signatory_unit LIKE ?)", likestr, likestr, likestr)
 	}
 
-	m = m.Order("c.id DESC").Limit(100)
+	m = m.Order("c.id DESC")
 
 	result, err := m.All()
 	if err != nil {

+ 66 - 3
opms_parent/app/service/opsdev/operation.go

@@ -129,6 +129,17 @@ func (s *OperationService) GetEntityById(req *comm_def.IdReq) (detail *opsdevmod
 		return nil, myerrors.TipsError("运维事件不存在")
 	}
 
+	// 查询事件级附件(eventRecordId = 0 或 null)
+	var attachments []*opsdevmodel.OpsOperationEventAttachment
+	err = s.AttachmentDao.FieldsEx(s.AttachmentDao.Columns.DeletedTime).
+		Where(s.AttachmentDao.Columns.EventId, req.Id).
+		Where("(event_record_id = 0 OR event_record_id IS NULL)").
+		Scan(&attachments)
+	if err != nil {
+		g.Log().Error(err)
+	}
+	detail.Attachments = attachments
+
 	return detail, nil
 }
 
@@ -143,8 +154,12 @@ func (s *OperationService) Create(req *opsdevmodel.OpsOperationEventReq) (err er
 	service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
 	data["eventNo"] = s.generateEventNo()
 	data["eventStatus"] = opsdevmodel.EventStatusProcessing
-	data["opsUserId"] = s.GetCxtUserId()
-	data["opsUserName"] = s.GetCxtUserName()
+	if _, ok := data["opsUserId"]; !ok || data["opsUserId"] == 0 {
+		data["opsUserId"] = s.GetCxtUserId()
+	}
+	if _, ok := data["opsUserName"]; !ok || data["opsUserName"] == "" {
+		data["opsUserName"] = s.GetCxtUserName()
+	}
 
 	if v, ok := data["feedbackDate"]; ok && v == "" {
 		data["feedbackDate"] = gtime.Now()
@@ -162,11 +177,27 @@ func (s *OperationService) Create(req *opsdevmodel.OpsOperationEventReq) (err er
 		return myerrors.DbError("创建运维事件失败")
 	}
 
-	_, err = result.LastInsertId()
+	eventId, err := result.LastInsertId()
 	if err != nil {
 		g.Log().Error(err)
 		return myerrors.DbError("获取运维事件ID失败")
 	}
+
+	// 保存事件级附件
+	for _, att := range req.Attachments {
+		attData := g.Map{
+			s.AttachmentDao.Columns.EventId:  eventId,
+			s.AttachmentDao.Columns.FileName: att.FileName,
+			s.AttachmentDao.Columns.FileUrl:  att.FileUrl,
+			s.AttachmentDao.Columns.FileType: att.FileType,
+		}
+		service.SetCreatedInfo(attData, s.GetCxtUserId(), s.GetCxtUserName())
+		_, err := s.AttachmentDao.Data(attData).Insert()
+		if err != nil {
+			g.Log().Error(err)
+		}
+	}
+
 	return nil
 }
 
@@ -289,6 +320,9 @@ func (s *OperationService) GetHistoryList(req *opsdevmodel.OpsOperationEventHist
 	if req.EndTime != "" {
 		db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
 	}
+	if req.ContractId != "" {
+		db = db.Where(s.Dao.Columns.ContractId, req.ContractId)
+	}
 
 	total, err = db.Count()
 	if err != nil {
@@ -334,6 +368,9 @@ func (s *OperationService) Export(ctx context.Context, req *opsdevmodel.OpsOpera
 	if req.EndTime != "" {
 		db = db.Where(s.Dao.Columns.FeedbackDate+" <= ?", req.EndTime)
 	}
+	if req.ContractId != "" {
+		db = db.Where(s.Dao.Columns.ContractId, req.ContractId)
+	}
 
 	var list []*opsdevmodel.OpsOperationEvent
 	err = db.Order(s.Dao.Columns.CompleteTime + " desc").Scan(&list)
@@ -818,6 +855,8 @@ func (s *OperationService) createDevTaskFromEvent(event *opsdevmodel.OpsOperatio
 		TaskDesc:    event.EventDesc,
 		TaskType:    taskType,
 		Priority:    event.PriorityLevel,
+		OpsUserId:   event.OpsUserId,
+		OpsUserName: event.OpsUserName,
 		EventId:     event.Id,
 		EventType:   opsdevmodel.EventTypeOps,
 		Attachments: taskAttachments,
@@ -973,6 +1012,29 @@ func (s *OperationService) UpdateById(req *opsdevmodel.UpdateOpsOperationEventRe
 		return myerrors.DbError("更新运维事件失败")
 	}
 
+	// 同步事件级附件:删除旧附件,插入新附件
+	if req.Attachments != nil {
+		_, _ = s.AttachmentDao.Data(g.Map{
+			s.AttachmentDao.Columns.DeletedTime: gtime.Now(),
+		}).Where(s.AttachmentDao.Columns.EventId, req.Id).
+			Where("(event_record_id = 0 OR event_record_id IS NULL)").
+			Update()
+
+		for _, att := range req.Attachments {
+			attData := g.Map{
+				s.AttachmentDao.Columns.EventId:  req.Id,
+				s.AttachmentDao.Columns.FileName: att.FileName,
+				s.AttachmentDao.Columns.FileUrl:  att.FileUrl,
+				s.AttachmentDao.Columns.FileType: att.FileType,
+			}
+			service.SetCreatedInfo(attData, s.GetCxtUserId(), s.GetCxtUserName())
+			_, err := s.AttachmentDao.Data(attData).Insert()
+			if err != nil {
+				g.Log().Error(err)
+			}
+		}
+	}
+
 	return nil
 }
 
@@ -1312,6 +1374,7 @@ func (s *OperationService) AddRecord(req *opsdevmodel.AddRecordReq) error {
 		s.RecordDao.Columns.HandleUserName: opsUserName,
 		s.RecordDao.Columns.HandleContent:  req.HandleContent,
 		s.RecordDao.Columns.HandleResult:   req.HandleResult,
+		s.RecordDao.Columns.OperateType:    opsdevmodel.OperateTypeProcess,
 		s.RecordDao.Columns.HandleDate:     gtime.Now(),
 	}
 	service.SetCreatedInfo(recordData, opsUserId, opsUserName)

+ 26 - 8
opms_parent/app/service/opsdev/ops_event_task.go

@@ -638,16 +638,34 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
 
 	// 使用事务
 	return s.TaskDao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
-		// 1. 更新任务状态
+		// 1. 从工时登记表汇总真实的累计工时(数据权威来源,避免前端异常值覆盖)
+		existingWorkHourTotal := entity.ActualWorkHour
+		if totalVal, err := g.DB(s.Tenant).GetValue(
+			"SELECT COALESCE(SUM(actual_work_hour), 0) FROM ops_event_task_work_hour WHERE task_id = ? AND deleted_time IS NULL",
+			req.Id,
+		); err == nil {
+			existingWorkHourTotal = totalVal.Float64()
+		}
+
+		// 计算实际应写入的工时:不允许用小于真实汇总值的数覆盖
+		finalWorkHour := req.ActualWorkHour
+		if finalWorkHour < existingWorkHourTotal {
+			finalWorkHour = existingWorkHourTotal
+		}
+
+		// 更新 data 中的工时字段为修正后的值
+		data[s.TaskDao.Columns.ActualWorkHour] = finalWorkHour
+
+		// 2. 更新任务状态与工时
 		_, err := s.TaskDao.TX(tx).FieldsEx(service.UpdateFieldEx...).Data(data).WherePri(s.TaskDao.Columns.Id, req.Id).Update()
 		if err != nil {
 			g.Log().Error(err)
 			return myerrors.DbError("完成任务失败")
 		}
 
-		// 2. 检查实际工时差异,自动登记工时差额
-		delta := req.ActualWorkHour - entity.ActualWorkHour
-		if delta != 0 {
+		// 3. 仅在前端额外追加了工时(高于工时表汇总)时,创建差额工时记录
+		delta := finalWorkHour - existingWorkHourTotal
+		if delta > 0 {
 			workHourData := g.Map{
 				s.WorkHourDao.Columns.TaskId:         req.Id,
 				s.WorkHourDao.Columns.OpsUserId:      s.GetCxtUserId(),
@@ -664,7 +682,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
 			}
 		}
 
-		// 3. 创建过程记录
+		// 4. 创建过程记录
 		var handleContent string
 		if entity.TaskType == opsdevmodel.TaskTypeFeatureTest && req.TestResult != "" {
 			testResultText := "通过"
@@ -702,7 +720,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
 
 		recordId, _ := result.LastInsertId()
 
-		// 4. 保存附件
+		// 5. 保存附件
 		if len(req.Attachments) > 0 {
 			for _, att := range req.Attachments {
 				attData := g.Map{
@@ -722,7 +740,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
 			}
 		}
 
-		// 5. 根据任务类型自动创建下游任务
+		// 6. 根据任务类型自动创建下游任务
 		// 5.1 功能开发完成时,自动创建功能测试任务(原4.2)
 		if entity.TaskType == opsdevmodel.TaskTypeFeatureDev {
 			testTaskData := g.Map{
@@ -843,7 +861,7 @@ func (s *OpsEventTaskService) doComplete(req *opsdevmodel.OpsEventTaskCompleteRe
 			}
 		}
 
-		// 6. 任务完成时自动更新关联的交付事件状态为完成并生成过程记录
+		// 7. 任务完成时自动更新关联的交付事件状态为完成并生成过程记录
 		if entity.EventId > 0 && entity.EventType == opsdevmodel.EventTypeDelivery {
 			// 触发事件自动完成的任务类型:10(需求评审)、30(功能测试-通过)、38(系统发版)、40(系统发版/硬件发货)、41(硬件安装)
 			if s.shouldAutoCompleteEvent(entity.TaskType, req.TestResult) {

+ 20 - 25
opms_storage/.idea/workspace.xml

@@ -5,12 +5,7 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" id="4b134288-d3a1-4921-afb3-1d33e2bcaa16" name="更改" comment="">
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/dao/opsdev/internal/ops_operation_event.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/dao/opsdev/internal/ops_operation_event.go" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/handler/opsdev/operation.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/handler/opsdev/operation.go" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/model/opsdev/internal/ops_operation_event.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/model/opsdev/internal/ops_operation_event.go" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/model/opsdev/operation.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/model/opsdev/operation.go" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/service/base.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/service/base.go" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/../opms_parent/app/service/opsdev/operation.go" beforeDir="false" afterPath="$PROJECT_DIR$/../opms_parent/app/service/opsdev/operation.go" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -34,26 +29,26 @@
     <option name="hideEmptyMiddlePackages" value="true" />
     <option name="showLibraryContents" value="true" />
   </component>
-  <component name="PropertiesComponent"><![CDATA[{
-  "keyToString": {
-    "Go 构建.go build opms_storage/cmd/server.executor": "Run",
-    "ModuleVcsDetector.initialDetectionPerformed": "true",
-    "RunOnceActivity.GoLinterPluginOnboarding": "true",
-    "RunOnceActivity.GoLinterPluginStorageMigration": "true",
-    "RunOnceActivity.ShowReadmeOnStart": "true",
-    "RunOnceActivity.git.unshallow": "true",
-    "RunOnceActivity.go.formatter.settings.were.checked": "true",
-    "RunOnceActivity.go.migrated.go.modules.settings": "true",
-    "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
-    "git-widget-placeholder": "develop",
-    "go.import.settings.migrated": "true",
-    "last_opened_file_path": "/Users/chengjian",
-    "node.js.detected.package.eslint": "true",
-    "node.js.selected.package.eslint": "(autodetect)",
-    "nodejs_package_manager_path": "npm",
-    "settings.editor.selected.configurable": "preferences.pluginManager"
+  <component name="PropertiesComponent">{
+  &quot;keyToString&quot;: {
+    &quot;Go 构建.go build opms_storage/cmd/server.executor&quot;: &quot;Run&quot;,
+    &quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.GoLinterPluginOnboarding&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.GoLinterPluginStorageMigration&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.go.formatter.settings.were.checked&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.go.migrated.go.modules.settings&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.go.modules.go.list.on.any.changes.was.set&quot;: &quot;true&quot;,
+    &quot;git-widget-placeholder&quot;: &quot;develop&quot;,
+    &quot;go.import.settings.migrated&quot;: &quot;true&quot;,
+    &quot;last_opened_file_path&quot;: &quot;/Users/chengjian&quot;,
+    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
+    &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
+    &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
+    &quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;
   }
-}]]></component>
+}</component>
   <component name="RunManager">
     <configuration name="go build opms_storage/cmd/server" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
       <module name="opms_storage" />