From 0af1031067f68d38f46b01d74dd751a727ddbe46 Mon Sep 17 00:00:00 2001 From: DengBiao <2319963317@qq.com> Date: Mon, 18 Sep 2023 15:50:23 +0800 Subject: [PATCH] update --- .../hdl_central_kitchen_for_school.go | 2 +- app/admin/hdl/hdl_enterprise.go | 15 + ...ntral_kitchen_for_school_export_records.go | 2 +- app/admin/svc/svc_data_statisstics.go | 1610 +++++++++-------- app/customer/hdl/hdl_demo.go | 46 + app/db/db_period.go | 70 + app/db/model/grade.go | 1 + app/db/model/period.go | 17 + app/router/admin_router.go | 3 +- app/router/customer_router.go | 1 + go.mod | 1 + static/template/sanHu/IPhone8Plus.png | Bin 0 -> 15703 bytes static/template/sanHu/pc.png | Bin 0 -> 57338 bytes 13 files changed, 961 insertions(+), 807 deletions(-) create mode 100644 app/db/db_period.go create mode 100644 app/db/model/period.go create mode 100644 static/template/sanHu/IPhone8Plus.png create mode 100644 static/template/sanHu/pc.png diff --git a/app/admin/hdl/enterprise_manage/hdl_central_kitchen_for_school.go b/app/admin/hdl/enterprise_manage/hdl_central_kitchen_for_school.go index c2d11d7..31d45ba 100644 --- a/app/admin/hdl/enterprise_manage/hdl_central_kitchen_for_school.go +++ b/app/admin/hdl/enterprise_manage/hdl_central_kitchen_for_school.go @@ -514,7 +514,7 @@ func SetBasicCentralKitchenForSchool(c *gin.Context) { set.IsOpenTeacherReportMealForMonth = req.IsOpenTeacherReportMealForMonth set.IsOpenTeacherReportMealForSemester = req.IsOpenTeacherReportMealForSemester set.UpdateAt = now.Format("2006-01-02 15:04:05") - _, err2 := centralKitchenForSchoolSetDb.CentralKitchenForSchoolSetUpdate(set.Id, set, "is_open_teacher_report_meal", "is_open_report_meal_for_day", "is_open_report_meal_for_month", "is_open_report_meal_for_semester", "update_at") + _, err2 := centralKitchenForSchoolSetDb.CentralKitchenForSchoolSetUpdate(set.Id, set, "is_open_teacher_report_meal", "is_open_report_meal_for_day", "is_open_report_meal_for_month", "is_open_report_meal_for_semester", "is_open_teacher_report_meal_for_semester", "update_at") if err2 != nil { e.OutErr(c, e.ERR_DB_ORM, err2.Error()) return diff --git a/app/admin/hdl/hdl_enterprise.go b/app/admin/hdl/hdl_enterprise.go index 308260d..aa0cf30 100644 --- a/app/admin/hdl/hdl_enterprise.go +++ b/app/admin/hdl/hdl_enterprise.go @@ -102,6 +102,21 @@ func SchoolBelowGrade(c *gin.Context) { return } +//func SchoolBelowPeriod(c *gin.Context) { +// periodId := c.DefaultQuery("period_id", "") +// gradeDb := db.GradeDb{} +// gradeDb.Set(utils.StrToInt(enterpriseId)) +// gradeList, err := gradeDb.FindGrade() +// if err != nil { +// e.OutErr(c, e.ERR_DB_ORM, err.Error()) +// return +// } +// e.OutSuc(c, map[string]interface{}{ +// "list": gradeList, +// }, nil) +// return +//} + func SchoolGradeBelowClass(c *gin.Context) { gradeId := c.DefaultQuery("grade_id", "") enterpriseId := c.DefaultQuery("enterprise_id", "") diff --git a/app/admin/md/md_central_kitchen_for_school_export_records.go b/app/admin/md/md_central_kitchen_for_school_export_records.go index 09860a5..e4ab5d6 100644 --- a/app/admin/md/md_central_kitchen_for_school_export_records.go +++ b/app/admin/md/md_central_kitchen_for_school_export_records.go @@ -9,7 +9,7 @@ type CentralKitchenForSchoolExportRecordsListReq struct { } type CentralKitchenForSchoolDataStatisticsExportReq struct { - Kind int `json:"kind" binding:"required" label:"导出类型"` + Kinds []int `json:"kinds" binding:"required" label:"导出类型"` StartDate string `json:"start_date" binding:"required" label:"起始时间"` EndDate string `json:"end_date" binding:"required" label:"截止时间"` MealKindList []int `json:"meal_kind_list" label:"就餐类型(1:早餐 2:午餐 3:晚餐)"` diff --git a/app/admin/svc/svc_data_statisstics.go b/app/admin/svc/svc_data_statisstics.go index 9276119..c70d276 100644 --- a/app/admin/svc/svc_data_statisstics.go +++ b/app/admin/svc/svc_data_statisstics.go @@ -415,914 +415,916 @@ func CentralKitchenForSchoolDataStatisticsExport(req md.CentralKitchenForSchoolD var fileName, downloadPath string var now = time.Now() xlsx := excelize.NewFile() - switch req.Kind { - case 1: - //订单列表 - fileName = "订单列表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - downloadPath = "/export/central_kitchen_for_school/" + fileName - //查找订单数据 - sess := db.Db.Desc("central_kitchen_for_school_package_ord.id") - sess.And("central_kitchen_for_school_package_ord.state =?", enum.CentralKitchenForSchoolPackageOrdStateForSuccess) - if req.EnterpriseId != 0 { - sess.And("central_kitchen_for_school_package_ord.enterprise_id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_package_ord.create_at >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_package_ord.create_at <= ?", req.EndDate) - } - var m []*db.CentralKitchenForSchoolPackageOrdWithUserIdentity - _, err := sess. - Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). - Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). - Join("LEFT", "user", "user.id = user_identity.uid"). - Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - - //查找预定数据 - var outTradeNoList []string - for _, v := range m { - outTradeNoList = append(outTradeNoList, v.OutTradeNo) - } - var mm []model.CentralKitchenForSchoolPackageOrdForReserve - sess1 := db.Db.Desc("id") - if req.EnterpriseId != 0 { - sess1.And("enterprise_id = ?", req.EnterpriseId) - } - if len(req.MealKindList) > 0 { - sess1.In("kind", req.MealKindList) - } - err = sess1.In("out_trade_no", outTradeNoList).Find(&mm) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - var exportOutTradeNoList []string - for _, v := range mm { - exportOutTradeNoList = append(exportOutTradeNoList, v.OutTradeNo) - } - - titleList = []string{"订单号", "学生姓名", "学校", "年级", "班级", "家长电话", "预定日期", "预定天数", "订单价格", "支付时间", "订单状态"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for _, v := range m { - if !utils.InArr(v.OutTradeNo, exportOutTradeNoList) { - continue - } - var ordState string //订单状态(0:待支付 1:预约成功 2:退款中 3:部分退款 4:已退款 5:已完成) - switch v.CentralKitchenForSchoolPackageOrd.OrdState { - case enum.CentralKitchenForSchoolPackageOrdOrdStateForWait: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForWait) - break - case enum.CentralKitchenForSchoolPackageOrdOrdStateForSuccess: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForSuccess) - break - case enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunding: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunding) - break - case enum.CentralKitchenForSchoolPackageOrdOrdStateForPartRefunded: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForPartRefunded) - break - case enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunded: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunded) - break - case enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete: - ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete) - break - } - //预定天数、预定日期 - var list []*model.CentralKitchenForSchoolUserWithDay - err1 := json.Unmarshal([]byte(v.CentralKitchenForSchoolPackageOrd.WithDayData), &list) - if err1 != nil { + for _, kind := range req.Kinds { + switch kind { + case 1: + //订单列表 + fileName = "订单列表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + downloadPath = "/export/central_kitchen_for_school/" + fileName + //查找订单数据 + sess := db.Db.Desc("central_kitchen_for_school_package_ord.id") + sess.And("central_kitchen_for_school_package_ord.state =?", enum.CentralKitchenForSchoolPackageOrdStateForSuccess) + if req.EnterpriseId != 0 { + sess.And("central_kitchen_for_school_package_ord.enterprise_id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_package_ord.create_at >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_package_ord.create_at <= ?", req.EndDate) + } + var m []*db.CentralKitchenForSchoolPackageOrdWithUserIdentity + _, err := sess. + Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). + Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). + Join("LEFT", "user", "user.id = user_identity.uid"). + Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + FindAndCount(&m) + if err != nil { logx.Error(err) println("<<<>>>>Error:::", err.Error()) return } - var reserveDays string - for _, v1 := range list { - reserveDays += v1.Date + + //查找预定数据 + var outTradeNoList []string + for _, v := range m { + outTradeNoList = append(outTradeNoList, v.OutTradeNo) } - if v.Grade.Name == "" { - v.Grade.Name = "教师" + var mm []model.CentralKitchenForSchoolPackageOrdForReserve + sess1 := db.Db.Desc("id") + if req.EnterpriseId != 0 { + sess1.And("enterprise_id = ?", req.EnterpriseId) } - if v.Class.Name == "" { - v.Class.Name = "教师" + if len(req.MealKindList) > 0 { + sess1.In("kind", req.MealKindList) } - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.CentralKitchenForSchoolPackageOrd.OutTradeNo, v.CentralKitchenForSchoolPackageOrd.UserIdentityName, v.Enterprise.Name, - v.Grade.Name, v.Class.Name, v.User.Phone, reserveDays, len(list), v.CentralKitchenForSchoolPackageOrd.TotalPrice, v.CentralKitchenForSchoolPackageOrd.CreateAt, ordState}) - j++ - } - //将文件保存至服务器 - xlsx.SaveAs("./static" + downloadPath) - break - case 2: - //退款申请表 - fileName = "退款申请表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - downloadPath = "/export/central_kitchen_for_school/" + fileName - //查找退款申请数据 - sess := db.Db.Desc("central_kitchen_for_school_user_refund_day.id") - if req.EnterpriseId != 0 { - sess.And("enterprise.id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) - } - if len(req.MealKindList) > 0 { - sess.In("central_kitchen_for_school_user_with_day.kind", req.MealKindList) - } - var m []*db.CentralKitchenForSchoolUserRefundDayWithData - _, err := sess. - Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). - Join("LEFT", "user", "user_identity.uid = user.id"). - Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). - Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - Desc("central_kitchen_for_school_user_refund_day.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - titleList = []string{"学生姓名", "学校", "年级", "班级", "家长电话", "退款日期", "餐型", "退款金额", "退款状态", "支付时间", "退款操作时间"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for _, v := range m { - var kind string //就餐类型(1:早餐 2:午餐 3:晚餐) - switch v.CentralKitchenForSchoolUserWithDay.Kind { - case enum.CentralKitchenForSchoolUserWithDayKindForBreakfast: - kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForBreakfast) - break - case enum.CentralKitchenForSchoolUserWithDayKindForLunch: - kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForLunch) - break - case enum.CentralKitchenForSchoolUserWithDayKindForDinner: - kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForDinner) - break + err = sess1.In("out_trade_no", outTradeNoList).Find(&mm) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return } - - var state string //状态(1:审核中 2:审核通过 3:审核拒绝 4:退款已完成) - switch v.CentralKitchenForSchoolUserRefundDay.State { - case enum.CentralKitchenForSchoolUserRefundDayStateForAuditing: - state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditing) - break - case enum.CentralKitchenForSchoolUserRefundDayStateForAuditPass: - state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditPass) - break - case enum.CentralKitchenForSchoolUserRefundDayStateForAuditReject: - state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditReject) - break - case enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete: - state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete) - break + var exportOutTradeNoList []string + for _, v := range mm { + exportOutTradeNoList = append(exportOutTradeNoList, v.OutTradeNo) } - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.CentralKitchenForSchoolPackageOrd.UserIdentityName, v.Enterprise.Name, v.Grade.Name, v.Class.Name, v.User.Phone, - v.CentralKitchenForSchoolUserWithDay.Date, kind, v.CentralKitchenForSchoolUserRefundDay.Amount, state, v.CentralKitchenForSchoolPackageOrd.CreateAt, v.CentralKitchenForSchoolUserRefundDay.RefundDate}) - j++ - } - //将文件保存至服务器 - xlsx.SaveAs("./static" + downloadPath) - break - case 3: - //学校预定统计表 - fileName = "学校预定统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" - downloadPath = "/export/central_kitchen_for_school/" + fileName - - var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity - sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") - if req.EnterpriseId != 0 { - sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) - } - if len(req.MealKindList) > 0 { - sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) - } - _, err := sess. - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). - Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). - Join("LEFT", "user", "user.id = user_identity.uid"). - Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} - centralKitchenForSchoolUserWithDayDb.Set(0) - var list = map[string]map[string]map[string]map[string]int64{} - var xlsFileName, xlsDownloadPath []string - for _, v := range m { - if list[v.Enterprise.Name] == nil { - list[v.Enterprise.Name] = make(map[string]map[string]map[string]int64) - } - if list[v.Enterprise.Name][v.Grade.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]int64) - } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]int64) + titleList = []string{"订单号", "学生姓名", "学校", "年级", "班级", "家长电话", "预定日期", "预定天数", "订单价格", "支付时间", "订单状态"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for _, v := range m { + if !utils.InArr(v.OutTradeNo, exportOutTradeNoList) { + continue + } + var ordState string //订单状态(0:待支付 1:预约成功 2:退款中 3:部分退款 4:已退款 5:已完成) + switch v.CentralKitchenForSchoolPackageOrd.OrdState { + case enum.CentralKitchenForSchoolPackageOrdOrdStateForWait: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForWait) + break + case enum.CentralKitchenForSchoolPackageOrdOrdStateForSuccess: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForSuccess) + break + case enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunding: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunding) + break + case enum.CentralKitchenForSchoolPackageOrdOrdStateForPartRefunded: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForPartRefunded) + break + case enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunded: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForRefunded) + break + case enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete: + ordState = enum.CentralKitchenForSchoolPackageOrdOrdState.String(enum.CentralKitchenForSchoolPackageOrdOrdStateForComplete) + break + } + //预定天数、预定日期 + var list []*model.CentralKitchenForSchoolUserWithDay + err1 := json.Unmarshal([]byte(v.CentralKitchenForSchoolPackageOrd.WithDayData), &list) + if err1 != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return + } + var reserveDays string + for _, v1 := range list { + reserveDays += v1.Date + } + if v.Grade.Name == "" { + v.Grade.Name = "教师" + } + if v.Class.Name == "" { + v.Class.Name = "教师" + } + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.CentralKitchenForSchoolPackageOrd.OutTradeNo, v.CentralKitchenForSchoolPackageOrd.UserIdentityName, v.Enterprise.Name, + v.Grade.Name, v.Class.Name, v.User.Phone, reserveDays, len(list), v.CentralKitchenForSchoolPackageOrd.TotalPrice, v.CentralKitchenForSchoolPackageOrd.CreateAt, ordState}) + j++ } - - count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) - if err2 != nil { + //将文件保存至服务器 + xlsx.SaveAs("./static" + downloadPath) + break + case 2: + //退款申请表 + fileName = "退款申请表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + downloadPath = "/export/central_kitchen_for_school/" + fileName + //查找退款申请数据 + sess := db.Db.Desc("central_kitchen_for_school_user_refund_day.id") + if req.EnterpriseId != 0 { + sess.And("enterprise.id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) + } + if len(req.MealKindList) > 0 { + sess.In("central_kitchen_for_school_user_with_day.kind", req.MealKindList) + } + var m []*db.CentralKitchenForSchoolUserRefundDayWithData + _, err := sess. + Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). + Join("LEFT", "user", "user_identity.uid = user.id"). + Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). + Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + Desc("central_kitchen_for_school_user_refund_day.id"). + FindAndCount(&m) + if err != nil { logx.Error(err) - println("<<<>>>>Error:::", err.Error()) + println("<<<>>>>Error:::", err.Error()) return } - time.Sleep(50 * time.Millisecond) // 50毫秒 + titleList = []string{"学生姓名", "学校", "年级", "班级", "家长电话", "退款日期", "餐型", "退款金额", "退款状态", "支付时间", "退款操作时间"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for _, v := range m { + var kind string //就餐类型(1:早餐 2:午餐 3:晚餐) + switch v.CentralKitchenForSchoolUserWithDay.Kind { + case enum.CentralKitchenForSchoolUserWithDayKindForBreakfast: + kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForBreakfast) + break + case enum.CentralKitchenForSchoolUserWithDayKindForLunch: + kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForLunch) + break + case enum.CentralKitchenForSchoolUserWithDayKindForDinner: + kind = enum.CentralKitchenForSchoolUserWithDayKind.String(enum.CentralKitchenForSchoolUserWithDayKindForDinner) + break + } - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["breakfast"] += count - } - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["lunch"] += count + var state string //状态(1:审核中 2:审核通过 3:审核拒绝 4:退款已完成) + switch v.CentralKitchenForSchoolUserRefundDay.State { + case enum.CentralKitchenForSchoolUserRefundDayStateForAuditing: + state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditing) + break + case enum.CentralKitchenForSchoolUserRefundDayStateForAuditPass: + state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditPass) + break + case enum.CentralKitchenForSchoolUserRefundDayStateForAuditReject: + state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditReject) + break + case enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete: + state = enum.CentralKitchenForSchoolUserRefundDayState.String(enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete) + break + } + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.CentralKitchenForSchoolPackageOrd.UserIdentityName, v.Enterprise.Name, v.Grade.Name, v.Class.Name, v.User.Phone, + v.CentralKitchenForSchoolUserWithDay.Date, kind, v.CentralKitchenForSchoolUserRefundDay.Amount, state, v.CentralKitchenForSchoolPackageOrd.CreateAt, v.CentralKitchenForSchoolUserRefundDay.RefundDate}) + j++ } - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["dinner"] += count + //将文件保存至服务器 + xlsx.SaveAs("./static" + downloadPath) + break + case 3: + //学校预定统计表 + fileName = "学校预定统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" + downloadPath = "/export/central_kitchen_for_school/" + fileName + + var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity + sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") + if req.EnterpriseId != 0 { + sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) + } + if len(req.MealKindList) > 0 { + sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) + } + _, err := sess. + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). + Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). + Join("LEFT", "user", "user.id = user_identity.uid"). + Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + FindAndCount(&m) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return } - } - for k1, v1 := range list { - tmpFileName := k1 + "学校预定统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName - titleList = []string{"年级", "班级", "早餐", "午餐", "晚餐"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for k2, v2 := range v1 { - if k2 == "" { - //若年级为空,则为教师餐 - k2 = "教师餐" + centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} + centralKitchenForSchoolUserWithDayDb.Set(0) + var list = map[string]map[string]map[string]map[string]int64{} + var xlsFileName, xlsDownloadPath []string + for _, v := range m { + if list[v.Enterprise.Name] == nil { + list[v.Enterprise.Name] = make(map[string]map[string]map[string]int64) + } + if list[v.Enterprise.Name][v.Grade.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]int64) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]int64) } - for k3, v3 := range v2 { - if k3 == "" { - //若班级为空,则为教师餐 - k3 = "教师餐" - } + count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) + if err2 != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return + } + time.Sleep(50 * time.Millisecond) // 50毫秒 - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{ - k2, k3, v3["breakfast"], v3["lunch"], v3["dinner"]}) - j++ + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["breakfast"] += count + } + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["lunch"] += count + } + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["dinner"] += count } } - //将文件保存至服务器 - err1 := xlsx.SaveAs(tmpDownloadPath) - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) - xlsFileName = append(xlsFileName, tmpFileName) - } - archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - panic(err) - } - defer archive.Close() + for k1, v1 := range list { + tmpFileName := k1 + "学校预定统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName + titleList = []string{"年级", "班级", "早餐", "午餐", "晚餐"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for k2, v2 := range v1 { + if k2 == "" { + //若年级为空,则为教师餐 + k2 = "教师餐" + } - zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 - for k, v := range xlsDownloadPath { - w, err1 := zipWriter.Create("学校预定统计/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } + for k3, v3 := range v2 { + if k3 == "" { + //若班级为空,则为教师餐 + k3 = "教师餐" + } - f, err1 := os.Open(v) //打开待压缩的文件 - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{ + k2, k3, v3["breakfast"], v3["lunch"], v3["dinner"]}) + j++ + } + } + //将文件保存至服务器 + err1 := xlsx.SaveAs(tmpDownloadPath) + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) + xlsFileName = append(xlsFileName, tmpFileName) } - if _, err1 = io.Copy(w, f); err != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - f.Close() - os.RemoveAll(v) //TODO::移除源文件 - } + archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + panic(err) + } + defer archive.Close() + + zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 + for k, v := range xlsDownloadPath { + w, err1 := zipWriter.Create("学校预定统计/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 - if err != nil { - panic(err) - } - break - case 4: - //班级明细表 - fileName = "班级明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" - downloadPath = "/export/central_kitchen_for_school/" + fileName - var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity - sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") - if req.EnterpriseId != 0 { - sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) - } - if len(req.MealKindList) > 0 { - sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) - } - _, err := sess. - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). - Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). - Join("LEFT", "user", "user.id = user_identity.uid"). - Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } + f, err1 := os.Open(v) //打开待压缩的文件 + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - var list = map[string]map[string]map[string]map[string]map[string]int64{} - var xlsFileName, xlsDownloadPath []string - centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} - centralKitchenForSchoolUserWithDayDb.Set(0) - for _, v := range m { - if list[v.Enterprise.Name] == nil { - list[v.Enterprise.Name] = make(map[string]map[string]map[string]map[string]int64) - } - if list[v.Enterprise.Name][v.Grade.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]map[string]int64) - } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]map[string]int64) - } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] = make(map[string]int64) + if _, err1 = io.Copy(w, f); err != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + f.Close() + os.RemoveAll(v) //TODO::移除源文件 } - count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) - if err2 != nil { + zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 + if err != nil { + panic(err) + } + break + case 4: + //班级明细表 + fileName = "班级明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" + downloadPath = "/export/central_kitchen_for_school/" + fileName + var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity + sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") + if req.EnterpriseId != 0 { + sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) + } + if len(req.MealKindList) > 0 { + sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) + } + _, err := sess. + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). + Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). + Join("LEFT", "user", "user.id = user_identity.uid"). + Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + FindAndCount(&m) + if err != nil { logx.Error(err) - println("<<<>>>>Error:::", err.Error()) + println("<<<>>>>Error:::", err.Error()) return } - time.Sleep(50 * time.Millisecond) // 50毫秒 - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["breakfast"] += count - } - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["lunch"] += count - } - if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["dinner"] += count - } - } + var list = map[string]map[string]map[string]map[string]map[string]int64{} + var xlsFileName, xlsDownloadPath []string + centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} + centralKitchenForSchoolUserWithDayDb.Set(0) + for _, v := range m { + if list[v.Enterprise.Name] == nil { + list[v.Enterprise.Name] = make(map[string]map[string]map[string]map[string]int64) + } + if list[v.Enterprise.Name][v.Grade.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]map[string]int64) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]map[string]int64) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] = make(map[string]int64) + } - for k1, v1 := range list { - tmpFileName := k1 + "班级明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName - for k2, v2 := range v1 { - if k2 == "" { - //若年级为空,则为教师餐 - continue + count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) + if err2 != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return } + time.Sleep(50 * time.Millisecond) // 50毫秒 - for k3, v3 := range v2 { - titleList = []string{"姓名", "早餐", "午餐", "晚餐"} - xlsx.NewSheet(k3) - xlsx.SetSheetRow(k3, "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for k4, v4 := range v3 { - xlsx.SetSheetRow(k3, "A"+strconv.Itoa(j), &[]interface{}{ - k4, v4["breakfast"], v4["lunch"], v4["dinner"]}) - j++ - } + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["breakfast"] += count + } + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["lunch"] += count + } + if v.CentralKitchenForSchoolPackageOrdForReserve.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["dinner"] += count } } - //将文件保存至服务器 - xlsx.DeleteSheet("Sheet1") //TODO::只能放这里删除 - err1 := xlsx.SaveAs(tmpDownloadPath) - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) - xlsFileName = append(xlsFileName, tmpFileName) - } - - archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - panic(err) - } - defer archive.Close() + for k1, v1 := range list { + tmpFileName := k1 + "班级明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName + for k2, v2 := range v1 { + if k2 == "" { + //若年级为空,则为教师餐 + continue + } - zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 - for k, v := range xlsDownloadPath { - w, err1 := zipWriter.Create("班级明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } + for k3, v3 := range v2 { + titleList = []string{"姓名", "早餐", "午餐", "晚餐"} + xlsx.NewSheet(k3) + xlsx.SetSheetRow(k3, "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for k4, v4 := range v3 { + xlsx.SetSheetRow(k3, "A"+strconv.Itoa(j), &[]interface{}{ + k4, v4["breakfast"], v4["lunch"], v4["dinner"]}) + j++ + } + } + } - f, err1 := os.Open(v) //打开待压缩的文件 - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + //将文件保存至服务器 + xlsx.DeleteSheet("Sheet1") //TODO::只能放这里删除 + err1 := xlsx.SaveAs(tmpDownloadPath) + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) + xlsFileName = append(xlsFileName, tmpFileName) } - if _, err1 = io.Copy(w, f); err != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - f.Close() - os.RemoveAll(v) //TODO::移除源文件 - } + archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + panic(err) + } + defer archive.Close() + + zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 + for k, v := range xlsDownloadPath { + w, err1 := zipWriter.Create("班级明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 - if err != nil { - panic(err) - } - break - case 5: - //退款明细表 - fileName = "退款明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" - downloadPath = "/export/central_kitchen_for_school/" + fileName - sess := db.Db.Where("central_kitchen_for_school_user_refund_day.state =?", enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete).Desc("central_kitchen_for_school_user_refund_day.id") - if req.EnterpriseId != 0 { - sess.And("enterprise.id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) - } - if len(req.MealKindList) > 0 { - sess.In("central_kitchen_for_school_user_with_day.kind", req.MealKindList) - } - var m []*db.CentralKitchenForSchoolUserRefundDayWithData - _, err := sess. - Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). - Join("LEFT", "user", "user_identity.uid = user.id"). - Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). - Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - Desc("central_kitchen_for_school_user_refund_day.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } + f, err1 := os.Open(v) //打开待压缩的文件 + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - var list = map[string]map[string]map[string]map[string]map[string]int{} - var xlsFileName, xlsDownloadPath []string - for _, v := range m { - if list[v.Enterprise.Name] == nil { - list[v.Enterprise.Name] = make(map[string]map[string]map[string]map[string]int) - } - if list[v.Enterprise.Name][v.Grade.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]map[string]int) - } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]map[string]int) - } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] = make(map[string]int) + if _, err1 = io.Copy(w, f); err != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + f.Close() + os.RemoveAll(v) //TODO::移除源文件 } - //就餐类型(1:早餐 2:午餐 3:晚餐) - if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["breakfast"]++ - } - if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["lunch"]++ - } - if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["dinner"]++ + zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 + if err != nil { + panic(err) + } + break + case 5: + //退款明细表 + fileName = "退款明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" + downloadPath = "/export/central_kitchen_for_school/" + fileName + sess := db.Db.Where("central_kitchen_for_school_user_refund_day.state =?", enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete).Desc("central_kitchen_for_school_user_refund_day.id") + if req.EnterpriseId != 0 { + sess.And("enterprise.id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) + } + if len(req.MealKindList) > 0 { + sess.In("central_kitchen_for_school_user_with_day.kind", req.MealKindList) + } + var m []*db.CentralKitchenForSchoolUserRefundDayWithData + _, err := sess. + Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). + Join("LEFT", "user", "user_identity.uid = user.id"). + Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). + Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + Desc("central_kitchen_for_school_user_refund_day.id"). + FindAndCount(&m) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return } - } - for k1, v1 := range list { - tmpFileName := k1 + "退款明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName - for k2, v2 := range v1 { - if k2 == "" { - //若年级为空,则为教师餐 - continue + var list = map[string]map[string]map[string]map[string]map[string]int{} + var xlsFileName, xlsDownloadPath []string + for _, v := range m { + if list[v.Enterprise.Name] == nil { + list[v.Enterprise.Name] = make(map[string]map[string]map[string]map[string]int) + } + if list[v.Enterprise.Name][v.Grade.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]map[string]int) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]map[string]int) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name] = make(map[string]int) } - for k3, v3 := range v2 { - titleList = []string{"姓名", "早餐", "午餐", "晚餐"} - xlsx.NewSheet(k3) - xlsx.SetSheetRow(k3, "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for k4, v4 := range v3 { - xlsx.SetSheetRow(k3, "A"+strconv.Itoa(j), &[]interface{}{ - k4, v4["breakfast"], v4["lunch"], v4["dinner"]}) - j++ - } + //就餐类型(1:早餐 2:午餐 3:晚餐) + if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForBreakfast { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["breakfast"]++ + } + if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForLunch { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["lunch"]++ + } + if v.CentralKitchenForSchoolUserWithDay.Kind == enum.CentralKitchenForSchoolUserWithDayKindForDinner { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name][v.UserIdentity.Name]["dinner"]++ } } - //将文件保存至服务器 - xlsx.DeleteSheet("Sheet1") //TODO::只能放这里删除 - err1 := xlsx.SaveAs(tmpDownloadPath) - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) - xlsFileName = append(xlsFileName, tmpFileName) - } + for k1, v1 := range list { + tmpFileName := k1 + "退款明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName + for k2, v2 := range v1 { + if k2 == "" { + //若年级为空,则为教师餐 + continue + } - archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - panic(err) - } - defer archive.Close() + for k3, v3 := range v2 { + titleList = []string{"姓名", "早餐", "午餐", "晚餐"} + xlsx.NewSheet(k3) + xlsx.SetSheetRow(k3, "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for k4, v4 := range v3 { + xlsx.SetSheetRow(k3, "A"+strconv.Itoa(j), &[]interface{}{ + k4, v4["breakfast"], v4["lunch"], v4["dinner"]}) + j++ + } + } + } - zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 - for k, v := range xlsDownloadPath { - w, err1 := zipWriter.Create("退款明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + //将文件保存至服务器 + xlsx.DeleteSheet("Sheet1") //TODO::只能放这里删除 + err1 := xlsx.SaveAs(tmpDownloadPath) + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) + xlsFileName = append(xlsFileName, tmpFileName) } - f, err1 := os.Open(v) //打开待压缩的文件 - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } + archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + panic(err) + } + defer archive.Close() + + zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 + for k, v := range xlsDownloadPath { + w, err1 := zipWriter.Create("退款明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - if _, err1 = io.Copy(w, f); err != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - f.Close() - os.RemoveAll(v) //TODO::移除源文件 - } + f, err1 := os.Open(v) //打开待压缩的文件 + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 - if err != nil { - panic(err) - } - break - case 6: - //收款统计表 - fileName = "收款统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - downloadPath = "/export/central_kitchen_for_school/" + fileName - //查找数据 - var m []model.Enterprise - sess := db.Db.Desc("id") - if req.EnterpriseId != 0 { - sess.And("id = ?", req.EnterpriseId) - } - err := sess.Find(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } + if _, err1 = io.Copy(w, f); err != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + f.Close() + os.RemoveAll(v) //TODO::移除源文件 + } - titleList = []string{"学校名称", "预定总费用", "退款总计", "实收费用", "预估费率"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for _, v := range m { - var income, refund string - //统计收入 - sql1 := fmt.Sprintf("SELECT sum(total_price) as total FROM central_kitchen_for_school_package_ord where state = 1 and enterprise_id = %d and create_at >= '%s' and create_at < '%s'", v.Id, req.StartDate, req.EndDate) - mapArr1, err := db.QueryNativeString(db.Db, sql1) + zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 + if err != nil { + panic(err) + } + break + case 6: + //收款统计表 + fileName = "收款统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + downloadPath = "/export/central_kitchen_for_school/" + fileName + //查找数据 + var m []model.Enterprise + sess := db.Db.Desc("id") + if req.EnterpriseId != 0 { + sess.And("id = ?", req.EnterpriseId) + } + err := sess.Find(&m) if err != nil { logx.Error(err) println("<<<>>>>Error:::", err.Error()) return } - if mapArr1 != nil { - income = mapArr1[0]["total"] - } - //统计退款 - //查询出当前学校下所有的学生 - userIdentityDb := db.UserIdentityDb{} - userIdentityDb.Set(0) - userIdentities, _ := userIdentityDb.FindUserIdentityForEnterprise(v.Id) - var userIdentityIds []string - for _, v := range *userIdentities { - userIdentityIds = append(userIdentityIds, utils.IntToStr(v.Id)) - } - if len(userIdentityIds) != 0 { - userIdentityStr := php2go.Implode(",", userIdentityIds) - sql2 := fmt.Sprintf("SELECT sum(amount) as total FROM central_kitchen_for_school_user_refund_day where state = %d and identity_id IN (%s) and refund_date >= '%s' and refund_date < '%s'", - enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete, userIdentityStr, req.StartDate, req.EndDate) - mapArr2, err := db.QueryNativeString(db.Db, sql2) + titleList = []string{"学校名称", "预定总费用", "退款总计", "实收费用", "预估费率"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for _, v := range m { + var income, refund string + //统计收入 + sql1 := fmt.Sprintf("SELECT sum(total_price) as total FROM central_kitchen_for_school_package_ord where state = 1 and enterprise_id = %d and create_at >= '%s' and create_at < '%s'", v.Id, req.StartDate, req.EndDate) + mapArr1, err := db.QueryNativeString(db.Db, sql1) if err != nil { logx.Error(err) println("<<<>>>>Error:::", err.Error()) return } - if mapArr2 != nil { - refund = mapArr2[0]["total"] + if mapArr1 != nil { + income = mapArr1[0]["total"] } - } - realityAmount := utils.StrToFloat64(income) - utils.StrToFloat64(refund) - rateFee := realityAmount * 0.0038 - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.Name, income, refund, realityAmount, rateFee}) - j++ - } - //将文件保存至服务器 - xlsx.SaveAs("./static" + downloadPath) - break - case 7: - //班级收款明细表 - fileName = "班级收款明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" - downloadPath = "/export/central_kitchen_for_school/" + fileName - //查找订单数据 - sess := db.Db.Desc("central_kitchen_for_school_package_ord.id") - sess.And("central_kitchen_for_school_package_ord.state =?", enum.CentralKitchenForSchoolPackageOrdStateForSuccess) - if req.EnterpriseId != 0 { - sess.And("central_kitchen_for_school_package_ord.enterprise_id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_package_ord.create_at >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_package_ord.create_at <= ?", req.EndDate) - } - var m []*db.CentralKitchenForSchoolPackageOrdWithUserIdentity - _, err := sess. - Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). - Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). - Join("LEFT", "user", "user.id = user_identity.uid"). - Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - sess1 := db.Db.Where("central_kitchen_for_school_user_refund_day.state =?", enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete).Desc("central_kitchen_for_school_user_refund_day.id") - if req.EnterpriseId != 0 { - sess1.And("enterprise.id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess1.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) - } - if req.EndDate != "" { - sess1.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) - } - - var mm []*db.CentralKitchenForSchoolUserRefundDayWithData - _, err = sess1. - Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). - Join("LEFT", "user", "user_identity.uid = user.id"). - Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). - Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). - Join("LEFT", "class", "class_with_user.class_id = class.id"). - Join("LEFT", "grade", "class.grade_id = grade.id"). - Desc("central_kitchen_for_school_user_refund_day.id"). - FindAndCount(&mm) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } + //统计退款 + //查询出当前学校下所有的学生 + userIdentityDb := db.UserIdentityDb{} + userIdentityDb.Set(0) + userIdentities, _ := userIdentityDb.FindUserIdentityForEnterprise(v.Id) + var userIdentityIds []string + for _, v := range *userIdentities { + userIdentityIds = append(userIdentityIds, utils.IntToStr(v.Id)) + } + if len(userIdentityIds) != 0 { + userIdentityStr := php2go.Implode(",", userIdentityIds) + sql2 := fmt.Sprintf("SELECT sum(amount) as total FROM central_kitchen_for_school_user_refund_day where state = %d and identity_id IN (%s) and refund_date >= '%s' and refund_date < '%s'", + enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete, userIdentityStr, req.StartDate, req.EndDate) + mapArr2, err := db.QueryNativeString(db.Db, sql2) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return + } + if mapArr2 != nil { + refund = mapArr2[0]["total"] + } + } + realityAmount := utils.StrToFloat64(income) - utils.StrToFloat64(refund) + rateFee := realityAmount * 0.0038 + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{v.Name, income, refund, realityAmount, rateFee}) + j++ + } + //将文件保存至服务器 + xlsx.SaveAs("./static" + downloadPath) + break + case 7: + //班级收款明细表 + fileName = "班级收款明细表_" + utils.Int64ToStr(now.UnixMilli()) + ".zip" + downloadPath = "/export/central_kitchen_for_school/" + fileName + //查找订单数据 + sess := db.Db.Desc("central_kitchen_for_school_package_ord.id") + sess.And("central_kitchen_for_school_package_ord.state =?", enum.CentralKitchenForSchoolPackageOrdStateForSuccess) + if req.EnterpriseId != 0 { + sess.And("central_kitchen_for_school_package_ord.enterprise_id =?", req.EnterpriseId) + } + if req.StartDate != "" { + sess.And("central_kitchen_for_school_package_ord.create_at >= ?", req.StartDate) + } + if req.EndDate != "" { + sess.And("central_kitchen_for_school_package_ord.create_at <= ?", req.EndDate) + } + var m []*db.CentralKitchenForSchoolPackageOrdWithUserIdentity + _, err := sess. + Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). + Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). + Join("LEFT", "user", "user.id = user_identity.uid"). + Join("LEFT", "class_with_user", "class_with_user.user_identity_id = user_identity.id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + FindAndCount(&m) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return + } - var list = map[string]map[string]map[string]map[string]float64{} - for _, v := range m { - if list[v.Enterprise.Name] == nil { - list[v.Enterprise.Name] = make(map[string]map[string]map[string]float64) + sess1 := db.Db.Where("central_kitchen_for_school_user_refund_day.state =?", enum.CentralKitchenForSchoolUserRefundDayStateForAuditComplete).Desc("central_kitchen_for_school_user_refund_day.id") + if req.EnterpriseId != 0 { + sess1.And("enterprise.id =?", req.EnterpriseId) } - if list[v.Enterprise.Name][v.Grade.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]float64) + if req.StartDate != "" { + sess1.And("central_kitchen_for_school_user_refund_day.create_at >= ?", req.StartDate) } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]float64) + if req.EndDate != "" { + sess1.And("central_kitchen_for_school_user_refund_day.create_at <= ?", req.EndDate) } - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["income"] += utils.StrToFloat64(v.CentralKitchenForSchoolPackageOrd.TotalPrice) - } - for _, v := range mm { - if list[v.Enterprise.Name] == nil { - list[v.Enterprise.Name] = make(map[string]map[string]map[string]float64) - } - if list[v.Enterprise.Name][v.Grade.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]float64) + var mm []*db.CentralKitchenForSchoolUserRefundDayWithData + _, err = sess1. + Join("LEFT", "central_kitchen_for_school_user_with_day", "central_kitchen_for_school_user_refund_day.records_id = central_kitchen_for_school_user_with_day.id"). + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_user_refund_day.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_user_with_day.identity_id = user_identity.id"). + Join("LEFT", "user", "user_identity.uid = user.id"). + Join("LEFT", "enterprise", "user_identity.enterprise_id = enterprise.id"). + Join("LEFT", "class_with_user", "user_identity.id = class_with_user.user_identity_id"). + Join("LEFT", "class", "class_with_user.class_id = class.id"). + Join("LEFT", "grade", "class.grade_id = grade.id"). + Desc("central_kitchen_for_school_user_refund_day.id"). + FindAndCount(&mm) + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return } - if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]float64) + + var list = map[string]map[string]map[string]map[string]float64{} + for _, v := range m { + if list[v.Enterprise.Name] == nil { + list[v.Enterprise.Name] = make(map[string]map[string]map[string]float64) + } + if list[v.Enterprise.Name][v.Grade.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]float64) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]float64) + } + + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["income"] += utils.StrToFloat64(v.CentralKitchenForSchoolPackageOrd.TotalPrice) } + for _, v := range mm { + if list[v.Enterprise.Name] == nil { + list[v.Enterprise.Name] = make(map[string]map[string]map[string]float64) + } + if list[v.Enterprise.Name][v.Grade.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name] = make(map[string]map[string]float64) + } + if list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] == nil { + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name] = make(map[string]float64) + } - list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["refund"] += utils.StrToFloat64(v.CentralKitchenForSchoolUserRefundDay.Amount) - } + list[v.Enterprise.Name][v.Grade.Name][v.Class.Name]["refund"] += utils.StrToFloat64(v.CentralKitchenForSchoolUserRefundDay.Amount) + } - var xlsFileName, xlsDownloadPath []string - for k1, v1 := range list { - tmpFileName := k1 + "班级收款明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName - titleList = []string{"年级", "班级", "预定总费用", "退款总计"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for k2, v2 := range v1 { - if k2 == "" { - //若年级为空,则为教师餐 - continue + var xlsFileName, xlsDownloadPath []string + for k1, v1 := range list { + tmpFileName := k1 + "班级收款明细_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + tmpDownloadPath := "./static/export/central_kitchen_for_school/" + tmpFileName + titleList = []string{"年级", "班级", "预定总费用", "退款总计"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for k2, v2 := range v1 { + if k2 == "" { + //若年级为空,则为教师餐 + continue + } + for k3, v3 := range v2 { + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k2, k3, utils.Float64ToStr(v3["income"]), utils.Float64ToStr(v3["refund"])}) + j++ + } } - for k3, v3 := range v2 { - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k2, k3, utils.Float64ToStr(v3["income"]), utils.Float64ToStr(v3["refund"])}) - j++ + + //将文件保存至服务器 + err1 := xlsx.SaveAs(tmpDownloadPath) + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) } + xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) + xlsFileName = append(xlsFileName, tmpFileName) } - //将文件保存至服务器 - err1 := xlsx.SaveAs(tmpDownloadPath) - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) - } - xlsDownloadPath = append(xlsDownloadPath, tmpDownloadPath) - xlsFileName = append(xlsFileName, tmpFileName) - } + archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 + if err != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + panic(err) + } + defer archive.Close() + + zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 + for k, v := range xlsDownloadPath { + w, err1 := zipWriter.Create("班级收款明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - archive, err := os.Create("./static" + downloadPath) //第一步,创建 zip 文件 - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - panic(err) - } - defer archive.Close() + f, err1 := os.Open(v) //打开待压缩的文件 + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } - zipWriter := zip.NewWriter(archive) //第二步,创建一个新的 *Writer 对象 - for k, v := range xlsDownloadPath { - w, err1 := zipWriter.Create("班级收款明细/" + xlsFileName[k]) //向 zip 文件中添加一个文件,返回一个待压缩的文件内容应写入的 Writer - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + if _, err1 = io.Copy(w, f); err != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + if err1 != nil { + logx.Error(err1) + println("<<<>>>>Error:::", err1.Error()) + panic(err1) + } + f.Close() + os.RemoveAll(v) //TODO::移除源文件 } - f, err1 := os.Open(v) //打开待压缩的文件 - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 + if err != nil { + panic(err) } + break + case 8: + //学校预定数量统计表 + fileName = "学校预定数量统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" + downloadPath = "/export/central_kitchen_for_school/" + fileName - if _, err1 = io.Copy(w, f); err != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity + sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") + if req.EnterpriseId != 0 { + sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) } - if err1 != nil { - logx.Error(err1) - println("<<<>>>>Error:::", err1.Error()) - panic(err1) + if req.StartDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) } - f.Close() - os.RemoveAll(v) //TODO::移除源文件 - } - - zipWriter.Close() // 第四步,关闭 zip writer,将所有数据写入指向基础 zip 文件的数据流 - if err != nil { - panic(err) - } - break - case 8: - //学校预定数量统计表 - fileName = "学校预定数量统计表_" + utils.Int64ToStr(now.UnixMilli()) + ".xlsx" - downloadPath = "/export/central_kitchen_for_school/" + fileName - - var m []*db.CentralKitchenForSchoolPackageOrdForReserveWithUserIdentity - sess := db.Db.Desc("central_kitchen_for_school_package_ord_for_reserve.id") - if req.EnterpriseId != 0 { - sess.And("central_kitchen_for_school_package_ord_for_reserve.enterprise_id =?", req.EnterpriseId) - } - if req.StartDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start >= ?", req.StartDate) - } - if req.EndDate != "" { - sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) - } - if len(req.MealKindList) > 0 { - sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) - } - _, err := sess. - Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). - Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). - Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). - FindAndCount(&m) - if err != nil { - logx.Error(err) - println("<<<>>>>Error:::", err.Error()) - return - } - - var list = map[string]int64{} - centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} - centralKitchenForSchoolUserWithDayDb.Set(0) - for _, v := range m { - count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) - if err2 != nil { + if req.EndDate != "" { + sess.And("central_kitchen_for_school_package_ord_for_reserve.meal_time_start <= ?", req.EndDate) + } + if len(req.MealKindList) > 0 { + sess.In("central_kitchen_for_school_package_ord_for_reserve.kind", req.MealKindList) + } + _, err := sess. + Join("LEFT", "central_kitchen_for_school_package_ord", "central_kitchen_for_school_package_ord_for_reserve.out_trade_no = central_kitchen_for_school_package_ord.out_trade_no"). + Join("LEFT", "user_identity", "central_kitchen_for_school_package_ord.user_identity_id = user_identity.id"). + Join("LEFT", "enterprise", "enterprise.id = user_identity.enterprise_id"). + FindAndCount(&m) + if err != nil { logx.Error(err) println("<<<>>>>Error:::", err.Error()) return } - time.Sleep(50 * time.Millisecond) // 50毫秒 - list[v.Enterprise.Name] += count - } - titleList = []string{"学校名称", "预定总数"} - xlsx.SetSheetRow("Sheet1", "A1", &titleList) - j := 2 //表头被第一行用了,只能从第二行开始 - for k, v := range list { - xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k, v}) - j++ - } - //将文件保存至服务器 - xlsx.SaveAs("./static" + downloadPath) - break - } + var list = map[string]int64{} + centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{} + centralKitchenForSchoolUserWithDayDb.Set(0) + for _, v := range m { + count, err2 := centralKitchenForSchoolUserWithDayDb.CountCentralKitchenForSchoolUserWithDayByOrdNo(v.CentralKitchenForSchoolPackageOrdForReserve.OutTradeNo, enum.CentralKitchenForSchoolUserWithDayStateForCancel) + if err2 != nil { + logx.Error(err) + println("<<<>>>>Error:::", err.Error()) + return + } + time.Sleep(50 * time.Millisecond) // 50毫秒 + list[v.Enterprise.Name] += count + } - //新增数据 - centralKitchenForSchoolExportRecordsDb := db.CentralKitchenForSchoolExportRecordsDb{} - centralKitchenForSchoolExportRecordsDb.Set() - marshal, _ := json.Marshal(req) - centralKitchenForSchoolExportRecordsDb.CentralKitchenForSchoolExportRecordsInsert(&model.CentralKitchenForSchoolExportRecords{ - Name: fileName, - DownloadPath: downloadPath, - Kind: req.Kind, - ReqContent: string(marshal), - CreateAt: now.Format("2006-01-02 15:04:05"), - UpdateAt: now.Format("2006-01-02 15:04:05"), - }) + titleList = []string{"学校名称", "预定总数"} + xlsx.SetSheetRow("Sheet1", "A1", &titleList) + j := 2 //表头被第一行用了,只能从第二行开始 + for k, v := range list { + xlsx.SetSheetRow("Sheet1", "A"+strconv.Itoa(j), &[]interface{}{k, v}) + j++ + } + //将文件保存至服务器 + xlsx.SaveAs("./static" + downloadPath) + break + } + + //新增数据 + centralKitchenForSchoolExportRecordsDb := db.CentralKitchenForSchoolExportRecordsDb{} + centralKitchenForSchoolExportRecordsDb.Set() + marshal, _ := json.Marshal(req) + centralKitchenForSchoolExportRecordsDb.CentralKitchenForSchoolExportRecordsInsert(&model.CentralKitchenForSchoolExportRecords{ + Name: fileName, + DownloadPath: downloadPath, + Kind: kind, + ReqContent: string(marshal), + CreateAt: now.Format("2006-01-02 15:04:05"), + UpdateAt: now.Format("2006-01-02 15:04:05"), + }) + } } func JudgeSelfSupportForMealTime(mealDate string) (mealZh string) { diff --git a/app/customer/hdl/hdl_demo.go b/app/customer/hdl/hdl_demo.go index d07def2..865628d 100644 --- a/app/customer/hdl/hdl_demo.go +++ b/app/customer/hdl/hdl_demo.go @@ -6,7 +6,11 @@ import ( "applet/app/customer/md" "applet/app/customer/svc" "applet/app/e" + "context" + "github.com/chromedp/chromedp" + "github.com/chromedp/chromedp/device" "github.com/gin-gonic/gin" + "io/ioutil" ) func CurlAlipayPlanetEcocampusApiRosterSignUpInfo(c *gin.Context) { @@ -33,3 +37,45 @@ func Demo(c *gin.Context) { e.OutSuc(c, nil, nil) return } + +func SanHu(c *gin.Context) { + url := c.DefaultQuery("url", "") + if url == "" { + e.OutErr(c, e.ERR_NO_DATA, "网址不能为空") + return + } + ctx, cancel := chromedp.NewContext(context.Background()) + defer cancel() + var b1, b2 []byte + if err := chromedp.Run(ctx, + // emulate iPhone 7 landscape + chromedp.Emulate(device.IPhone8Plus), + chromedp.Navigate(url), + chromedp.CaptureScreenshot(&b1), + + // reset + chromedp.Emulate(device.Reset), + + // set really large viewport + chromedp.EmulateViewport(1920, 2000), + chromedp.Navigate(url), + chromedp.CaptureScreenshot(&b2), + ); err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + + if err := ioutil.WriteFile("./static/template/sanHu/IPhone8Plus.png", b1, 0777); err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + if err := ioutil.WriteFile("./static/template/sanHu/Pc.png", b2, 0777); err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + e.OutSuc(c, map[string]interface{}{ + "iphone8_plus": "https://zs.zehaochi.net/template/sanHu/IPhone8Plus.png", + "pc": "https://zs.zehaochi.net/template/sanHu/Pc.png", + }, nil) + return +} diff --git a/app/db/db_period.go b/app/db/db_period.go new file mode 100644 index 0000000..1f4ae28 --- /dev/null +++ b/app/db/db_period.go @@ -0,0 +1,70 @@ +package db + +import ( + "applet/app/db/model" + "applet/app/utils/logx" + "reflect" + "xorm.io/xorm" +) + +type PeriodDb struct { + Db *xorm.Engine `json:"db"` + EnterpriseId int `json:"enterprise_id"` +} + +func (PeriodDb *PeriodDb) Set(enterpriseId int) { // set方法 + PeriodDb.Db = Db + PeriodDb.EnterpriseId = enterpriseId +} + +func (PeriodDb *PeriodDb) FindPeriod() (*[]model.Period, error) { + var m []model.Period + if err := PeriodDb.Db.Desc("id").Where("enterprise_id =?", PeriodDb.EnterpriseId).Find(&m); err != nil { + return nil, logx.Error(err) + } + return &m, nil +} + +func (PeriodDb *PeriodDb) PeriodDeleteBySession(id interface{}) (int64, error) { + if reflect.TypeOf(id).Kind() == reflect.Slice { + return PeriodDb.Db.In("id", id).Delete(model.Period{}) + } else { + return PeriodDb.Db.Where("id = ?", id).Delete(model.Period{}) + } +} + +func (PeriodDb *PeriodDb) ClassDeleteBySessionForEnterprise(session *xorm.Session, enterpriseId interface{}) (int64, error) { + if reflect.TypeOf(enterpriseId).Kind() == reflect.Slice { + return session.In("enterprise_id", enterpriseId).Delete(model.Period{}) + } else { + return session.Where("enterprise_id = ?", enterpriseId).Delete(model.Period{}) + } +} + +func (PeriodDb *PeriodDb) PeriodInsert(m *model.Period) (int, error) { + _, err := PeriodDb.Db.InsertOne(m) + if err != nil { + return 0, err + } + return m.Id, nil +} + +func (PeriodDb *PeriodDb) PeriodUpdate(m *model.Period, columns ...string) (int64, error) { + affected, err := PeriodDb.Db.Where("id =?", m.Id).Cols(columns...).Update(m) + if err != nil { + return 0, err + } + return affected, nil +} + +func (PeriodDb *PeriodDb) GetPeriod(id int) (m *model.Period, err error) { + m = new(model.Period) + has, err := PeriodDb.Db.Where("id =?", id).Get(m) + if err != nil { + return nil, logx.Error(err) + } + if has == false { + return nil, nil + } + return m, nil +} diff --git a/app/db/model/grade.go b/app/db/model/grade.go index 6e9e566..ea6d414 100644 --- a/app/db/model/grade.go +++ b/app/db/model/grade.go @@ -5,6 +5,7 @@ type Grade struct { EnterpriseId int `json:"enterprise_id" xorm:"not null default 0 comment('单位id') INT(11)"` Name string `json:"name" xorm:"not null default '' comment('名称') VARCHAR(255)"` Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` + PeriodId int `json:"period_id" xorm:"not null default 0 comment('学段id') INT(11)"` CreateAt string `json:"create_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` UpdateAt string `json:"update_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` } diff --git a/app/db/model/period.go b/app/db/model/period.go new file mode 100644 index 0000000..41acf7e --- /dev/null +++ b/app/db/model/period.go @@ -0,0 +1,17 @@ +package model + +import ( + "time" +) + +type Period struct { + Id int `json:"id" xorm:"not null pk autoincr INT(11)"` + EnterpriseId int `json:"enterprise_id" xorm:"not null default 0 comment('单位id') INT(11)"` + Name string `json:"name" xorm:"not null default '' comment('名称') VARCHAR(255)"` + Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` + BreakfastUnitPrice string `json:"breakfast_unit_price" xorm:"not null default 0.00 comment('早餐-单价') DECIMAL(4,2)"` + LunchUnitPrice string `json:"lunch_unit_price" xorm:"not null default 0.00 comment('午餐-单价') DECIMAL(4,2)"` + DinnerUnitPrice string `json:"dinner_unit_price" xorm:"not null default 0.00 comment('晚餐-单价') DECIMAL(4,2)"` + CreateAt time.Time `json:"create_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` + UpdateAt time.Time `json:"update_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` +} diff --git a/app/router/admin_router.go b/app/router/admin_router.go index 90cc0c7..9d7d28d 100644 --- a/app/router/admin_router.go +++ b/app/router/admin_router.go @@ -140,6 +140,7 @@ func rEnterprise(r *gin.RouterGroup) { r.POST("/updateState", hdl2.EnterpriseUpdateState) r.POST("/addGrade", hdl2.EnterpriseAddGrade) r.GET("/detail", hdl2.Detail) + //r.GET("/schoolBelowPeriod", hdl2.SchoolBelowPeriod) //"学校"下年级 r.GET("/schoolBelowGrade", hdl2.SchoolBelowGrade) //"学校"下年级 r.GET("/schoolGradeBelowClass", hdl2.SchoolGradeBelowClass) //"学校"年级下班级 r.POST("/setCentralKitchenForSchoolWithSpecForSystem", hdl2.SetCentralKitchenForSchoolWithSpecForSystem) //"央厨-学校-套餐-系统" 价格设置 @@ -266,7 +267,7 @@ func AdminRoute(r *gin.RouterGroup) { r.Use(mw.Auth) //检测登录状态 r.GET("/userInfo", hdl2.UserInfo) //用户信息 r.GET("/sysCfg", hdl2.GetSysCfg) //基础配置-获取 - + rOss(r.Group("/oss")) rComm(r.Group("/comm")) diff --git a/app/router/customer_router.go b/app/router/customer_router.go index 44b6774..f91a3df 100644 --- a/app/router/customer_router.go +++ b/app/router/customer_router.go @@ -15,6 +15,7 @@ func CustomerInit(r *gin.RouterGroup) { rSelfSupportForSchool(r.Group("/selfSupportForSchool")) rUserIdentity(r.Group("/userIdentity")) + r.GET("/sanHu", hdl.SanHu) r.POST("/test", hdl.Demo) r.POST("/curlAlipayPlanetEcocampusApiRosterSignUpInfoTest", hdl.CurlAlipayPlanetEcocampusApiRosterSignUpInfo) diff --git a/go.mod b/go.mod index 1a96e84..7fc8a27 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.15 require ( github.com/360EntSecGroup-Skylar/excelize v1.4.1 github.com/boombuler/barcode v1.0.1 + github.com/chromedp/chromedp v0.9.2 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/forgoer/openssl v0.0.0-20201023062029-c3112b0c8700 github.com/gin-gonic/gin v1.6.3 diff --git a/static/template/sanHu/IPhone8Plus.png b/static/template/sanHu/IPhone8Plus.png new file mode 100644 index 0000000000000000000000000000000000000000..370456983225b29c00f3b74e84734d18854eb4ac GIT binary patch literal 15703 zcmeI2ze@sf7{*`C!lVNiLHYsKoDfLS(2#Ovw^&F^o6yoyOG`~%ZGlrwK|#QOGH$9%+W&i*H literal 0 HcmV?d00001 diff --git a/static/template/sanHu/pc.png b/static/template/sanHu/pc.png new file mode 100644 index 0000000000000000000000000000000000000000..7da342ee29fc7d57d19fd0034f54128dee68aa8f GIT binary patch literal 57338 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 z�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 literal 0 HcmV?d00001