package controllers import ( "encoding/json" "io" "strconv" "strings" "time" "server/models" beego "github.com/beego/beego/v2/server/web" ) // ============================================================= // CRM 招投标管理 - 子表 CRUD(统一接口) // ============================================================= // // 每个子表控制器提供统一的接口: // - List 按外键 bid_id / tender_id 列出 // - Create 新增(关联外键由请求体传入) // - Delete 软删除 // - Update 更新(用于文件改名、任务进度等) // ============================================================= // ------------------------------ 投标文件 ------------------------------ // BackendCrmBiddingBidFileController 投标文件 type BackendCrmBiddingBidFileController struct { beego.Controller } // bidFilePayload type bidFilePayload struct { BidID uint64 `json:"bid_id"` FileType string `json:"file_type"` FileName string `json:"file_name"` FileURL string `json:"file_url"` FileSize uint64 `json:"file_size"` FileExt string `json:"file_ext"` Version string `json:"version"` UploadUserID string `json:"upload_user_id"` UploadUserName string `json:"upload_user_name"` Remark string `json:"remark"` } // List GET /backend/crm/bidding/bid-file/list?bid_id=1 func (c *BackendCrmBiddingBidFileController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidFile _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create POST /backend/crm/bidding/bid-file func (c *BackendCrmBiddingBidFileController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidFilePayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.BidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } if strings.TrimSpace(p.FileName) == "" || strings.TrimSpace(p.FileURL) == "" { pipelineErr(&c.Controller, 400, 400, "文件信息不完整") return } now := time.Now() row := models.TenantCrmBiddingBidFile{ TenantID: pipelineTenantID(claims), BidID: p.BidID, FileType: firstNonEmpty(p.FileType, "1"), FileName: strings.TrimSpace(p.FileName), FileURL: strings.TrimSpace(p.FileURL), FileSize: p.FileSize, FileExt: strings.TrimSpace(p.FileExt), Version: firstNonEmpty(p.Version, "1.0"), UploadUserID: firstNonEmpty(p.UploadUserID, pipelineUID(claims)), UploadUserName: firstNonEmpty(p.UploadUserName, resolveUserName(claims)), Remark: p.Remark, CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "上传失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "上传投标文件", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Delete DELETE /backend/crm/bidding/bid-file/:id func (c *BackendCrmBiddingBidFileController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingBidFile _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidFile)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标文件", claims) pipelineOk(&c.Controller, nil) } // ------------------------------ 投标任务 ------------------------------ // BackendCrmBiddingBidTaskController 投标任务 type BackendCrmBiddingBidTaskController struct { beego.Controller } type bidTaskPayload struct { BidID uint64 `json:"bid_id"` TaskName string `json:"task_name"` TaskType string `json:"task_type"` Content string `json:"content"` OwnerUserID string `json:"owner_user_id"` OwnerUserName string `json:"owner_user_name"` StartDate string `json:"start_date"` EndDate string `json:"end_date"` Status int8 `json:"status"` Progress int8 `json:"progress"` Files string `json:"files"` Remark string `json:"remark"` } // List func (c *BackendCrmBiddingBidTaskController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidTask _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create func (c *BackendCrmBiddingBidTaskController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidTaskPayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.BidID == 0 || strings.TrimSpace(p.TaskName) == "" { pipelineErr(&c.Controller, 400, 400, "任务信息不完整") return } now := time.Now() row := models.TenantCrmBiddingBidTask{ TenantID: pipelineTenantID(claims), BidID: p.BidID, TaskName: strings.TrimSpace(p.TaskName), TaskType: firstNonEmpty(p.TaskType, "1"), Content: p.Content, OwnerUserID: firstNonEmpty(p.OwnerUserID, pipelineUID(claims)), OwnerUserName: firstNonEmpty(p.OwnerUserName, resolveUserName(claims)), StartDate: parsePipelineDate(p.StartDate), EndDate: parsePipelineDate(p.EndDate), Status: p.Status, Progress: p.Progress, Files: p.Files, Remark: p.Remark, CreateUserID: pipelineUID(claims), CreateUserName: resolveUserName(claims), CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新建投标任务", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Update func (c *BackendCrmBiddingBidTaskController) Update() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidTaskPayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } var row models.TenantCrmBiddingBidTask if err := models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Filter("delete_time__isnull", true).One(&row); err != nil { pipelineErr(&c.Controller, 404, 404, "任务未找到") return } if strings.TrimSpace(p.TaskName) != "" { row.TaskName = strings.TrimSpace(p.TaskName) } if strings.TrimSpace(p.TaskType) != "" { row.TaskType = p.TaskType } row.Content = p.Content if strings.TrimSpace(p.OwnerUserID) != "" { row.OwnerUserID = strings.TrimSpace(p.OwnerUserID) row.OwnerUserName = strings.TrimSpace(p.OwnerUserName) } row.StartDate = parsePipelineDate(p.StartDate) row.EndDate = parsePipelineDate(p.EndDate) row.Status = p.Status row.Progress = p.Progress row.Files = p.Files row.Remark = p.Remark row.UpdateTime = time.Now() if _, err := models.Orm.Update(&row); err != nil { pipelineErr(&c.Controller, 500, 500, "更新失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, row.BidID, "update", "更新投标任务", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": row.ID}) } // Delete func (c *BackendCrmBiddingBidTaskController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingBidTask _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidTask)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标任务", claims) pipelineOk(&c.Controller, nil) } // ------------------------------ 投标结果 ------------------------------ // BackendCrmBiddingBidResultController 投标结果 type BackendCrmBiddingBidResultController struct { beego.Controller } // List func (c *BackendCrmBiddingBidResultController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidResult _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidResult)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Detail func (c *BackendCrmBiddingBidResultController) Detail() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } var row models.TenantCrmBiddingBidResult err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidResult)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Filter("delete_time__isnull", true).One(&row) if err != nil { pipelineErr(&c.Controller, 404, 404, "投标结果未找到") return } pipelineOk(&c.Controller, row) } // ------------------------------ 投标报价 ------------------------------ // BackendCrmBiddingBidQuoteController 投标报价 type BackendCrmBiddingBidQuoteController struct { beego.Controller } type bidQuotePayload struct { BidID uint64 `json:"bid_id"` QuoteName string `json:"quote_name"` TotalAmount float64 `json:"total_amount"` Currency string `json:"currency"` TaxRate float64 `json:"tax_rate"` ValidDate string `json:"valid_date"` Products string `json:"products"` CostAnalysis string `json:"cost_analysis"` ProfitRate float64 `json:"profit_rate"` Status int8 `json:"status"` Remark string `json:"remark"` } // List func (c *BackendCrmBiddingBidQuoteController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidQuote _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create func (c *BackendCrmBiddingBidQuoteController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidQuotePayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.BidID == 0 || strings.TrimSpace(p.QuoteName) == "" { pipelineErr(&c.Controller, 400, 400, "报价信息不完整") return } now := time.Now() row := models.TenantCrmBiddingBidQuote{ TenantID: pipelineTenantID(claims), BidID: p.BidID, QuoteName: strings.TrimSpace(p.QuoteName), TotalAmount: p.TotalAmount, Currency: firstNonEmpty(p.Currency, "CNY"), TaxRate: p.TaxRate, ValidDate: parsePipelineDate(p.ValidDate), Products: p.Products, CostAnalysis: p.CostAnalysis, ProfitRate: p.ProfitRate, Status: 1, SubmitUserID: pipelineUID(claims), SubmitUserName: resolveUserName(claims), SubmitTime: &now, Remark: p.Remark, CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新建投标报价", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Delete func (c *BackendCrmBiddingBidQuoteController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingBidQuote _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidQuote)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标报价", claims) pipelineOk(&c.Controller, nil) } // ------------------------------ 投标竞争对手 ------------------------------ // BackendCrmBiddingBidCompetitorController type BackendCrmBiddingBidCompetitorController struct { beego.Controller } type bidCompetitorPayload struct { BidID uint64 `json:"bid_id"` CompetitorName string `json:"competitor_name"` CompetitorType int8 `json:"competitor_type"` QuoteAmount float64 `json:"quote_amount"` Advantages string `json:"advantages"` Weaknesses string `json:"weaknesses"` Source string `json:"source"` Remark string `json:"remark"` } // List func (c *BackendCrmBiddingBidCompetitorController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidCompetitor _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create func (c *BackendCrmBiddingBidCompetitorController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidCompetitorPayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.BidID == 0 || strings.TrimSpace(p.CompetitorName) == "" { pipelineErr(&c.Controller, 400, 400, "竞争对手信息不完整") return } now := time.Now() row := models.TenantCrmBiddingBidCompetitor{ TenantID: pipelineTenantID(claims), BidID: p.BidID, CompetitorName: strings.TrimSpace(p.CompetitorName), CompetitorType: firstNonEmptyInt8(p.CompetitorType, 1), QuoteAmount: p.QuoteAmount, Advantages: p.Advantages, Weaknesses: p.Weaknesses, Source: strings.TrimSpace(p.Source), Remark: p.Remark, CreateUserID: pipelineUID(claims), CreateUserName: resolveUserName(claims), CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "新增竞争对手", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Delete func (c *BackendCrmBiddingBidCompetitorController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingBidCompetitor _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidCompetitor)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除竞争对手", claims) pipelineOk(&c.Controller, nil) } // ------------------------------ 投标费用 ------------------------------ // BackendCrmBiddingBidExpenseController type BackendCrmBiddingBidExpenseController struct { beego.Controller } type bidExpensePayload struct { BidID uint64 `json:"bid_id"` ExpenseType int8 `json:"expense_type"` ExpenseName string `json:"expense_name"` Amount float64 `json:"amount"` Currency string `json:"currency"` PaymentStatus int8 `json:"payment_status"` PaymentDate string `json:"payment_date"` Description string `json:"description"` VoucherURL string `json:"voucher_url"` } // List func (c *BackendCrmBiddingBidExpenseController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } bidID, _ := c.GetInt64("bid_id") if bidID == 0 { pipelineErr(&c.Controller, 400, 400, "bid_id 必填") return } var list []models.TenantCrmBiddingBidExpense _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)). Filter("tenant_id", pipelineTenantID(claims)). Filter("bid_id", bidID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create func (c *BackendCrmBiddingBidExpenseController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p bidExpensePayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.BidID == 0 || strings.TrimSpace(p.ExpenseName) == "" { pipelineErr(&c.Controller, 400, 400, "费用信息不完整") return } now := time.Now() row := models.TenantCrmBiddingBidExpense{ TenantID: pipelineTenantID(claims), BidID: p.BidID, ExpenseType: firstNonEmptyInt8(p.ExpenseType, 1), ExpenseName: strings.TrimSpace(p.ExpenseName), Amount: p.Amount, Currency: firstNonEmpty(p.Currency, "CNY"), PaymentStatus: p.PaymentStatus, PaymentDate: parsePipelineDateTime(p.PaymentDate), Description: p.Description, VoucherURL: strings.TrimSpace(p.VoucherURL), CreateUserID: pipelineUID(claims), CreateUserName: resolveUserName(claims), CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "创建失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.BidID, "create", "登记投标费用", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Delete func (c *BackendCrmBiddingBidExpenseController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingBidExpense _ = models.Orm.QueryTable(new(models.TenantCrmBiddingBidExpense)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.BidID, "delete", "删除投标费用", claims) pipelineOk(&c.Controller, nil) } // ------------------------------ 招标文件 ------------------------------ // BackendCrmBiddingTenderFileController 招标文件 type BackendCrmBiddingTenderFileController struct { beego.Controller } type tenderFilePayload struct { TenderID uint64 `json:"tender_id"` FileType string `json:"file_type"` FileName string `json:"file_name"` FileURL string `json:"file_url"` FileSize uint64 `json:"file_size"` FileExt string `json:"file_ext"` UploadUserID string `json:"upload_user_id"` UploadUserName string `json:"upload_user_name"` Remark string `json:"remark"` } // List func (c *BackendCrmBiddingTenderFileController) List() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } tenderID, _ := c.GetInt64("tender_id") if tenderID == 0 { pipelineErr(&c.Controller, 400, 400, "tender_id 必填") return } var list []models.TenantCrmBiddingTenderFile _, _ = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)). Filter("tenant_id", pipelineTenantID(claims)). Filter("tender_id", tenderID). Filter("delete_time__isnull", true). OrderBy("-id").All(&list) pipelineOk(&c.Controller, map[string]interface{}{"list": list}) } // Create func (c *BackendCrmBiddingTenderFileController) Create() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } raw, _ := io.ReadAll(c.Ctx.Request.Body) var p tenderFilePayload if err := json.Unmarshal(raw, &p); err != nil { pipelineErr(&c.Controller, 400, 400, "参数错误") return } if p.TenderID == 0 || strings.TrimSpace(p.FileName) == "" || strings.TrimSpace(p.FileURL) == "" { pipelineErr(&c.Controller, 400, 400, "文件信息不完整") return } now := time.Now() row := models.TenantCrmBiddingTenderFile{ TenantID: pipelineTenantID(claims), TenderID: p.TenderID, FileType: firstNonEmpty(p.FileType, "1"), FileName: strings.TrimSpace(p.FileName), FileURL: strings.TrimSpace(p.FileURL), FileSize: p.FileSize, FileExt: strings.TrimSpace(p.FileExt), UploadUserID: firstNonEmpty(p.UploadUserID, pipelineUID(claims)), UploadUserName: firstNonEmpty(p.UploadUserName, resolveUserName(claims)), Remark: p.Remark, CreateTime: now, UpdateTime: now, } id, err := models.Orm.Insert(&row) if err != nil { pipelineErr(&c.Controller, 500, 500, "上传失败: "+err.Error()) return } crmWriteLog(pipelineTenantID(claims), 5, p.TenderID, "create", "上传招标文件", claims) pipelineOk(&c.Controller, map[string]interface{}{"id": id}) } // Delete func (c *BackendCrmBiddingTenderFileController) Delete() { claims, err := pipelineClaims(&c.Controller) if err != nil { pipelineErr(&c.Controller, 401, 401, err.Error()) return } id, _ := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if id == 0 { pipelineErr(&c.Controller, 400, 400, "无效的ID") return } now := time.Now() _, err = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)). Filter("id", id). Filter("tenant_id", pipelineTenantID(claims)). Update(map[string]interface{}{"delete_time": now, "update_time": now}) if err != nil { pipelineErr(&c.Controller, 500, 500, "删除失败: "+err.Error()) return } var delRow models.TenantCrmBiddingTenderFile _ = models.Orm.QueryTable(new(models.TenantCrmBiddingTenderFile)).Filter("id", id).One(&delRow) crmWriteLog(pipelineTenantID(claims), 5, delRow.TenderID, "delete", "删除招标文件", claims) pipelineOk(&c.Controller, nil) } // ===================================================================== // 工具函数 // ===================================================================== // firstNonEmptyInt8 返回第一个非零的 int8 func firstNonEmptyInt8(v, def int8) int8 { if v == 0 { return def } return v }