package bus_apis import ( "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-admin-team/go-admin-core/sdk/api" "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" "github.com/google/uuid" "github.com/pkg/errors" "go-admin/app/admin/models/bus_models" "go-admin/app/admin/service/bus_service" "go-admin/tools/app" "go-admin/tools/crypto" "io" "strings" ) type SmsApi struct { api.Api } // MassImportPhone 导入号码(群发短信) // @Summary 导入号码(群发短信) // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param file body string true "上传excel文件" // @Success 200 {object} bus_models.MassImportPhoneResp // @Router /api/v1/sms/mass_import_phone [post] func (e SmsApi) MassImportPhone(c *gin.Context) { var smsService bus_service.SmsService // 绑定 JSON 数据,获取 secret_key err := e.MakeContext(c). MakeOrm(). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } // 获取上传的文件 file, _, err := c.Request.FormFile("file") if err != nil { e.Logger.Error("获取文件失败:", err) e.Error(400, err, "请上传有效的文件") return } defer file.Close() // 读取文件内容并处理 fileBytes, err := io.ReadAll(file) if err != nil { e.Logger.Error("读取文件内容失败:", err) e.Error(500, err, "读取文件失败") return } // 使用 SmsService 读取 Excel 文件 phones, err := smsService.ReadExcelFile(fileBytes) if err != nil { e.Error(500, err, "读取文件失败") return } if len(phones) == 0 { e.Error(400, nil, "导入的手机号为空") return } importSerial := uuid.New().String() fmt.Println("uuid importSerial:", importSerial) err = smsService.CachePhonesByShard(importSerial, phones) if err != nil { fmt.Println("手机号缓存失败") e.Error(500, err, "手机号缓存失败") return } // 返回加密后的数据 resp := bus_models.MassImportPhoneResp{ ImportSerialNumber: importSerial, } if len(phones) > bus_models.ShowCount { resp.List = phones[0:200] } else { resp.List = phones } // 将JSON数据转换为字符串 plainText, err := json.Marshal(resp) if err != nil { e.Logger.Error("JSON 序列化失败:", err) e.Error(500, err, "数据转换失败") return } // 使用AES加密手机号 encryptedData, err := crypto.AESEncryptJson(bus_models.AESKey, string(plainText)) if err != nil { e.Logger.Error("AES 加密失败:", err) e.Error(500, err, "加密失败") return } app.OK(c, encryptedData, "导入成功") return } func (e SmsApi) SelfImportPhone(c *gin.Context) { s := bus_service.ProductService{} var req bus_models.ProductListReq err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&s.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } } func (e SmsApi) FileImportPhone(c *gin.Context) { s := bus_service.ProductService{} var req bus_models.ProductListReq err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&s.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } } func (e SmsApi) ExcelImportPhone(c *gin.Context) { s := bus_service.ProductService{} var req bus_models.ProductListReq err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&s.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } } // ExportMessPhone 导出号码(群发短信) // @Summary 导出号码(群发短信) // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.ExportMessPhoneReq true "导出号码(群发短信)模型" // @Success 200 {object} bus_models.ExportMessPhoneResp // @Router /api/v1/sms/export_mess_phone [post] func (e SmsApi) ExportMessPhone(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.ExportMessPhoneReq err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } // 解密 decryptedText, err := crypto.AESDecryptJson(bus_models.AESKey, req.Data) if err != nil { fmt.Println("解密失败:", err) return } var l bus_models.ExportMessPhoneReq err = json.Unmarshal([]byte(decryptedText), &l) if err != nil { err = fmt.Errorf("json Unmarshal error, %s", err.Error()) return } req = l // 调用导出函数 url, err := smsService.ExportPhoneListToExcel(req.ImportSerialNumber, req.PhoneList) if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } resp := bus_models.ExportMessPhoneResp{ ExportUrl: url, } app.OK(c, resp, "OK") return } // CheckSensitiveWords 敏感词检测 // @Summary 敏感词检测 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.CheckSensitiveWordsReq true "敏感词检测模型" // @Success 200 {object} bus_models.CheckSensitiveWordsResponse // @Router /api/v1/sms/check_sensitive_words [post] func (e SmsApi) CheckSensitiveWords(c *gin.Context) { var req bus_models.CheckSensitiveWordsReq s := bus_service.SmsService{} err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&s.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } hits, err := s.CheckSensitiveWords(req.Content) if err != nil { e.Logger.Error(err) e.Error(500, err, "敏感词检测失败") return } hasSensitiveWords := len(hits) > 0 resp := bus_models.CheckSensitiveWordsResponse{ HasSensitiveWords: hasSensitiveWords, SensitiveWords: hits, } app.OK(c, resp, "OK") } // SendSms 提交发送任务 // @Summary 提交发送任务 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.SendSmsReq true "提交发送任务模型" // @Success 200 {object} app.Response // @Router /api/v1/sms/send_sms [post] func (e SmsApi) SendSms(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SendSmsReq err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } userName := user.GetUserName(c) fmt.Println("userName is:", userName) // 查询合作商的编号和名称 coopNum, coopName, err := bus_models.GetCooperativeInfoByAccount(e.Orm, userName) if err != nil { err = fmt.Errorf("GetCooperativeInfoByAccount error, %s", err.Error()) return } // 解密 decryptedText, err := crypto.AESDecryptJson(bus_models.AESKey, req.Data) if err != nil { fmt.Println("解密失败:", err) return } var l bus_models.SendSmsReq err = json.Unmarshal([]byte(decryptedText), &l) if err != nil { err = fmt.Errorf("json Unmarshal error, %s", err.Error()) return } req = l if req.ImportSerialNumber == "" && len(req.PhoneList) == 0 { e.Error(400, nil, "手机号不能为空") return } if req.ImportSerialNumber != "" { // 如果有导入编号还有额外手机号,直接追加到 Redis 缓存列表 if len(req.PhoneList) > 0 { err = smsService.AppendPhonesToRedis(req.ImportSerialNumber, req.PhoneList) if err != nil { e.Logger.Error("手机号追加失败:", err) e.Error(500, err, "手机号追加失败") return } } } else { importSerial := uuid.New().String() fmt.Println("uuid importSerial:", importSerial) err = smsService.CachePhonesByShard(importSerial, req.PhoneList) if err != nil { fmt.Println("手机号缓存失败") e.Error(500, err, "手机号缓存失败") return } req.ImportSerialNumber = importSerial } // 创建发送任务,使用 redis 缓存中的数据分片处理 err = smsService.SubmitSmsTaskFromRedis(c.Request.Context(), req.ImportSerialNumber, req.SmsContent, req.SendTime, coopNum, coopName) if err != nil { e.Logger.Error("任务提交失败:", err) e.Error(500, err, "短信任务提交失败") return } app.OK(c, nil, "短信发送任务提交成功") return } // QuerySmsTaskList 查询短信下行记录 // @Summary 查询短信下行记录 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.SmsTaskQueryRequest true "查询短信下行记录模型" // @Success 200 {object} bus_models.SmsTaskQueryResponse // @Router /api/v1/sms/sms_log [post] func (e SmsApi) QuerySmsTaskList(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsTaskQueryRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } result, err := smsService.QuerySmsTaskList(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询短信下行记录失败") return } app.OK(c, result, "查询成功") } // SmsSendRecordQuery 查询短信下行明细 // @Summary 查询短信下行明细 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.SmsTaskQueryRequest true "查询短信下行明细模型" // @Success 200 {object} bus_models.SmsTaskQueryResponse // @Router /api/v1/sms/sms_phone_log [post] func (e SmsApi) SmsSendRecordQuery(c *gin.Context) { var req bus_models.SmsSendRecordQueryReq s := bus_service.SmsService{} err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&s.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, "参数解析失败") return } resp, err := s.QuerySmsSendRecords(req) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询失败") return } app.OK(c, resp, "查询成功") } // GetPhonesByBatchID 根据批次ID获取手机号 // @Summary 根据批次ID获取手机号 // @Tags 短信管理-V1.0.0 // @Produce json // @Param request body bus_models.GetPhonesByBatchIDReq true "根据批次ID获取手机号模型" // @Success 200 {object} bus_models.GetPhonesByBatchIDResp // @Router /api/v1/sms/get_phones [post] func (e SmsApi) GetPhonesByBatchID(c *gin.Context) { var smsService bus_service.SmsService var req bus_models.GetPhonesByBatchIDReq // 初始化服务 err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } if req.BatchID == "" { e.Error(400, nil, "缺少参数:batch_id") return } // 根据 batch_id 查询导入ID var task bus_models.SmsTask if err = e.Orm.Where("batch_id = ?", req.BatchID).First(&task).Error; err != nil { e.Logger.Error("查询任务失败:", err) e.Error(404, err, "未找到对应批次任务") return } if task.ImportID == "" { e.Error(400, nil, "该批次未绑定导入记录") return } // 查询缓存的手机号 phones, err := smsService.GetPhonesFromCache(task.ImportID, 30) if err != nil { e.Logger.Error("获取手机号失败:", err) } // 如果缓存中没有手机号,再查询已发送记录 if len(phones) == 0 { phones, err = smsService.GetSentPhonesByBatchID(e.Orm, req.BatchID, 30) if err != nil { e.Logger.Error("从数据库查询已发送手机号失败:", err) e.Error(500, err, "获取手机号失败") return } } resp := bus_models.GetPhonesByBatchIDResp{ Phones: phones, } // 将JSON数据转换为字符串 plainText, err := json.Marshal(resp) if err != nil { e.Logger.Error("JSON 序列化失败:", err) e.Error(500, err, "数据转换失败") return } // 使用AES加密手机号 encryptedData, err := crypto.AESEncryptJson(bus_models.AESKey, string(plainText)) if err != nil { e.Logger.Error("AES 加密失败:", err) e.Error(500, err, "加密失败") return } app.OK(c, encryptedData, "查询成功") } // QueryScheduledSmsTaskList 查询定时短信任务列表 // @Summary 查询定时短信任务列表 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.SmsTaskScheduledQueryRequest true "查询定时短信任务列表请求" // @Success 200 {object} bus_models.SmsTaskQueryResponse // @Router /api/v1/sms/sms_timing_list [post] func (e SmsApi) QueryScheduledSmsTaskList(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsTaskScheduledQueryRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } result, err := smsService.QueryScheduledSmsTaskList(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询定时短信任务失败") return } app.OK(c, result, "查询成功") } // QuerySmsUplinkList 查询短信上行记录 // @Summary 查询短信上行记录 // @Tags 短信管理-V1.0.0 // @Produce json // @Accept json // @Param request body bus_models.SmsUplinkQueryRequest true "查询条件" // @Success 200 {object} bus_models.SmsUplinkQueryResponse // @Router /api/v1/sms/uplink_log [post] func (e SmsApi) QuerySmsUplinkList(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsUplinkQueryRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } resp, err := smsService.QuerySmsUplinkList(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询短信上行记录失败") return } app.OK(c, resp, "查询成功") } // BatchUpdateScheduledSmsContent 批量修改定时短信内容 // @Summary 批量修改定时短信内容 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.BatchUpdateSmsContentRequest true "批量修改定时短信内容请求" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/batch_update_content [post] func (e SmsApi) BatchUpdateScheduledSmsContent(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.BatchUpdateSmsContentRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } if len(req.TaskIDs) == 0 || strings.TrimSpace(req.SmsContent) == "" { app.Error(c, 500, errors.New("任务ID列表和短信内容不能为空"), "") } if err := smsService.BatchUpdateSmsContent(req, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "批量修改短信内容失败") return } app.OK(c, nil, "修改成功") } // BatchCancelScheduledSms 批量取消定时短信任务 // @Summary 批量取消定时短信任务 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.BatchUpdateRequest true "任务ID列表" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/batch_cancel [post] func (e SmsApi) BatchCancelScheduledSms(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.BatchUpdateRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } if err := smsService.BatchCancelSmsTasks(req, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "批量取消任务失败") return } app.OK(c, nil, "取消成功") } // BatchResetScheduledSms 批量重置定时发送时间 // @Summary 批量重置定时发送时间 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.BatchResetScheduleTimeRequest true "重置定时时间请求" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/batch_reset_schedule [post] func (e SmsApi) BatchResetScheduledSms(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.BatchResetScheduleTimeRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } if err := smsService.BatchResetScheduleTime(req, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "重置定时时间失败") return } app.OK(c, nil, "重置成功") } // CreateSignatureRealname 新增实名签名 // @Summary 新增实名签名 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.SmsSignatureRealname true "实名签名信息" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/signature_realname/create [post] func (e SmsApi) CreateSignatureRealname(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsSignatureRealname err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } userName := user.GetUserName(c) fmt.Println("userName is:", userName) // 查询合作商的编号和名称 coopNum, coopName, err := bus_models.GetCooperativeInfoByAccount(e.Orm, userName) if err != nil { err = fmt.Errorf("GetCooperativeInfoByAccount error, %s", err.Error()) return } req.CooperativeName = coopName req.CooperativeNumber = coopNum if err := smsService.CreateSignatureRealname(&req, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "创建失败") return } app.OK(c, nil, "创建成功") } // UpdateSignatureRealname 编辑实名签名 // @Summary 编辑实名签名 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.SmsSignatureRealname true "实名签名信息" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/signature_realname/update [post] func (e SmsApi) UpdateSignatureRealname(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsSignatureRealname err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } if err := smsService.UpdateSignatureRealname(&req, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "更新失败") return } app.OK(c, nil, "更新成功") } // DeleteSignatureRealname 批量删除签名实名记录 // @Summary 批量删除签名实名记录 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.DeleteSignatureRealnameRequest true "删除请求" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/signature_realname/delete [post] func (e SmsApi) DeleteSignatureRealname(c *gin.Context) { var req bus_models.DeleteSignatureRealnameRequest smsService := bus_service.SmsService{} err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, "参数绑定失败") return } if len(req.IDs) == 0 { e.Error(400, nil, "请选择要删除的记录") return } if err := smsService.BatchDeleteSignatureRealname(req.IDs, e.Orm); err != nil { e.Logger.Error(err) e.Error(500, err, "删除失败") return } app.OK(c, nil, "删除成功") } // ListSignatureRealname 查询签名实名制列表 // @Summary 查询签名实名制列表 // @Tags 短信管理-V1.0.0 // @Accept json // @Produce json // @Param request body bus_models.SignatureRealnameQuery true "实名签名信息" // @Success 200 {object} app.Response{msg=string} // @Router /api/v1/sms/signature_realname/list [get] func (e SmsApi) ListSignatureRealname(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SignatureRealnameQuery err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.Query). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } resp, err := smsService.ListSignatureRealname(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询失败") return } app.OK(c, resp, "查询成功") } // ListContacts 查询通讯录列表 // @Summary 查询通讯录列表 // @Tags 短信管理-通讯录 // @Accept json // @Produce json // @Param request query bus_models.ContactQuery true "查询参数" // @Success 200 {object} bus_models.ContactQueryResp // @Router /api/v1/sms/contacts/list [get] func (e SmsApi) ListContacts(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.ContactQuery err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.Query). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } resp, err := smsService.ListContacts(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "查询失败") return } app.OK(c, resp, "查询成功") } // AddContact 新增联系人 // @Summary 新增联系人 // @Tags 短信管理-通讯录 // @Accept json // @Produce json // @Param request body bus_models.SmsContact true "联系人信息" // @Success 200 {object} app.Response // @Router /api/v1/sms/contacts/add [post] func (e SmsApi) AddContact(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsContact err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } err = smsService.AddContact(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "新增联系人失败") return } app.OK(c, nil, "新增联系人成功") } // EditContact 编辑联系人 // @Summary 编辑联系人 // @Tags 短信管理-通讯录 // @Accept json // @Produce json // @Param id path int true "联系人ID" // @Param request body bus_models.SmsContact true "联系人信息" // @Success 200 {object} app.Response // @Router /api/v1/sms/contacts/edit [post] func (e SmsApi) EditContact(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.SmsContact id := c.Param("id") err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } err = smsService.EditContact(id, req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "编辑联系人失败") return } app.OK(c, nil, "编辑联系人成功") } // BulkDeleteContacts 批量删除联系人 // @Summary 批量删除联系人 // @Tags 短信管理-通讯录 // @Accept json // @Produce json // @Param request body bus_models.ContactDeleteRequest true "删除联系人ID列表" // @Success 200 {object} app.Response // @Router /api/v1/sms/contacts/batch_delete [post] func (e SmsApi) BulkDeleteContacts(c *gin.Context) { smsService := bus_service.SmsService{} var req bus_models.ContactDeleteRequest err := e.MakeContext(c). MakeOrm(). Bind(&req, binding.JSON). MakeService(&smsService.Service). Errors if err != nil { e.Logger.Error(err) e.Error(500, err, err.Error()) return } err = smsService.BulkDeleteContacts(req, e.Orm) if err != nil { e.Logger.Error(err) e.Error(500, err, "批量删除联系人失败") return } app.OK(c, nil, "批量删除联系人成功") }