diff --git a/SIMFANG.TTF b/SIMFANG.TTF new file mode 100644 index 0000000..68334e2 Binary files /dev/null and b/SIMFANG.TTF differ diff --git a/api/manage/auth.go b/api/manage/auth.go index 62435d8..9a807b0 100644 --- a/api/manage/auth.go +++ b/api/manage/auth.go @@ -1 +1,44 @@ package manage + +import ( + "fmt" + "github.com/gin-gonic/gin" + request "insure/dto/request/manage" + "insure/e" + "insure/service" + "insure/utils/result" +) + +func Login(c *gin.Context) (result.Data, error) { + loginRequest := request.LoginRequest{} + err := c.ShouldBindJSON(&loginRequest) + token, err := service.AdminService.Login(loginRequest.Username, loginRequest.Password) + return result.Data{"token": token}, err +} + +func GetAdminInfo(c *gin.Context) (result.Data, error) { + admin := service.AdminService.GetAdminInfo(admin(c).ID) + data := result.Data{ + "admin": admin, + } + return data, nil +} + +func Logout(c *gin.Context) (result.Data, error) { + return nil, nil +} + +func AddAdmin(c *gin.Context) (result.Data, error) { + addAdminRequest := request.AddAdminRequest{} + err := c.ShouldBindJSON(&addAdminRequest) + fmt.Println("addAdminRequest") + fmt.Println(addAdminRequest) + if err != nil { + return nil, e.NewError("参数错误") + } + err = service.AdminService.Add(addAdminRequest.Username, addAdminRequest.Password) + if err != nil { + return nil, err + } + return nil, nil +} diff --git a/api/manage/order.go b/api/manage/order.go new file mode 100644 index 0000000..9a16fce --- /dev/null +++ b/api/manage/order.go @@ -0,0 +1,31 @@ +package manage + +import ( + "github.com/gin-gonic/gin" + request "insure/dto/request/manage" + "insure/e" + "insure/service" + "insure/utils/excel" + "insure/utils/result" +) + +func GetOrders(c *gin.Context) (result.Data, error) { + var req request.OrderQueryRequest + err := c.ShouldBindQuery(&req) + if err != nil { + return nil, e.NewError("参数错误") + } + orders, total := service.OrderService.GetOrders(req) + data := result.Data{ + "records": orders, + "total": total, + } + return data, nil +} + +func DownloadOrders(c *gin.Context) { + var req request.OrderQueryRequest + _ = c.ShouldBindQuery(&req) + f := service.OrderService.GenerateOrdersExcel(req) + excel.Download(f, "订单列表.xlsx", c) +} diff --git a/cmd/web/main.go b/cmd/web/main.go index 36c7fa1..5e2afa6 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -15,8 +15,8 @@ func main() { initial() //testVerify() //runServer() - gen1() - //runServerInWindows() + //gen3() + runServerInWindows() } func initial() { @@ -179,10 +179,48 @@ func gen1() { pdf.AddPage() - pdf.SetFont("宋体", "", float64(40)) + pdf.AddUTF8Font("SIMFANG", "", "./SIMFANG.TTF") + pdf.SetFont("SIMFANG", "", float64(12)) pdf.SetXY(0, float64(40)) - pdf.Cell(40, 10, "注意:请认准阅读所附条款,/n尤其是黑体部分内容") + imgFileStr := "./static/assets/img/zking_logo.png" + infoPtr := pdf.RegisterImage(imgFileStr, "") + imgWd, imgHt := infoPtr.Extent() + pdf.Image(imgFileStr, 0, 0, imgWd, imgHt, false, "", 0, "") + pdf.Cell(40, 10, `注意:请认准阅读所附条款,尤其是黑体部分内容`) + + pdf.Ln(-1) + pdf.SetFontSize(20) + pdf.Cell(40, 10, "投标保证保险投保单") + pdf.Ln(-1) + pdf.SetFontSize(10) + pdf.Cell(40, 10, "在您填写本投保单前,请仔细阅读《紫金财产保险股份有限公司投标保证保险条款》 ,特别注意条款中有") + pdf.Ln(5) + pdf.Cell(40, 10, "关保险责任、 免除保险人责任和投保人、被保险人义务的规定, 同时听取本公司就条款所做的说明,") + pdf.Ln(5) + pdf.Cell(40, 10, "并可就 其中内容要求本公司做出解释。在您已充分理解保险条款后,请您如实填写本投保单并签章确认。") + pdf.Ln(5) + pdf.CellFormat(30, 30, "投保人(投标人)", "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, "法人名称/自然人姓名", "1", 0, "", false, 0, "") + pdf.CellFormat(60, 6, "", "1", 0, "", false, 0, "") + pdf.Ln(-1) + pdf.SetX(40) + pdf.CellFormat(40, 6, "证件类型", "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, "", "1", 0, "", false, 0, "") + pdf.CellFormat(40, 6, "证件号码", "1", 0, "", false, 0, "") + //pdf.MultiCell(40, 6, "证件号码", "1", "", false) + pdf.CellFormat(40, 6, "", "1", 0, "", false, 0, "") + pdf.Ln(-1) + pdf.SetX(40) + pdf.CellFormat(40, 18, "法人性质", "1", 0, "", false, 0, "") + //pdf.MultiCell(40, 6, "□国有 ☑集体 □民营 □私营 □外资 □合资 □其他", "1", "", false) + pdf.CellFormat(40, 18, "□国有 ☑集体 □民营 □私营 □外资 □合资 □其他", "1", 0, "", false, 0, "") + pdf.CellFormat(40, 18, "法人资质", "1", 0, "", false, 0, "") + pdf.CellFormat(40, 18, "□特级 ☑一级 □二级 □三级", "1", 0, "", false, 0, "") + //pdf.MultiCell(40, 6, "□特级 ☑一级 □二级 □三级", "1", "", false) + pdf.Ln(5) + pdf.Ellipse(30, 15, 20, 10, 0, "D") + pdf.Ln(10) pdf.SetFont("Arial", "", 14) basicTable() @@ -195,3 +233,331 @@ func gen1() { fmt.Println(err) } } + +func gen2() { + const ( + thin = 0.2 + thick = 3.0 + ) + pdf := gofpdf.New("", "", "", "") + pdf.SetFont("Helvetica", "", 12) + pdf.SetFillColor(200, 200, 220) + pdf.AddPage() + + y := 15.0 + pdf.Text(10, y, "Circles") + pdf.SetFillColor(200, 200, 220) + pdf.SetLineWidth(thin) + pdf.Circle(20, y+15, 10, "D") + pdf.Circle(45, y+15, 10, "F") + pdf.Circle(70, y+15, 10, "FD") + pdf.SetLineWidth(thick) + pdf.Circle(95, y+15, 10, "FD") + pdf.SetLineWidth(thin) + + y += 40.0 + pdf.Text(10, y, "Ellipses") + pdf.SetFillColor(220, 200, 200) + pdf.Ellipse(30, y+15, 20, 10, 0, "D") + pdf.Ellipse(75, y+15, 20, 10, 0, "F") + pdf.Ellipse(120, y+15, 20, 10, 0, "FD") + pdf.SetLineWidth(thick) + pdf.Ellipse(165, y+15, 20, 10, 0, "FD") + pdf.SetLineWidth(thin) + + y += 40.0 + pdf.Text(10, y, "Curves (quadratic)") + pdf.SetFillColor(220, 220, 200) + pdf.Curve(10, y+30, 15, y-20, 40, y+30, "D") + pdf.Curve(45, y+30, 50, y-20, 75, y+30, "F") + pdf.Curve(80, y+30, 85, y-20, 110, y+30, "FD") + pdf.SetLineWidth(thick) + pdf.Curve(115, y+30, 120, y-20, 145, y+30, "FD") + pdf.SetLineCapStyle("round") + pdf.Curve(150, y+30, 155, y-20, 180, y+30, "FD") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + y += 40.0 + pdf.Text(10, y, "Curves (cubic)") + pdf.SetFillColor(220, 200, 220) + pdf.CurveBezierCubic(10, y+30, 15, y-20, 10, y+30, 40, y+30, "D") + pdf.CurveBezierCubic(45, y+30, 50, y-20, 45, y+30, 75, y+30, "F") + pdf.CurveBezierCubic(80, y+30, 85, y-20, 80, y+30, 110, y+30, "FD") + pdf.SetLineWidth(thick) + pdf.CurveBezierCubic(115, y+30, 120, y-20, 115, y+30, 145, y+30, "FD") + pdf.SetLineCapStyle("round") + pdf.CurveBezierCubic(150, y+30, 155, y-20, 150, y+30, 180, y+30, "FD") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + y += 40.0 + pdf.Text(10, y, "Arcs") + pdf.SetFillColor(200, 220, 220) + pdf.SetLineWidth(thick) + pdf.Arc(45, y+35, 20, 10, 0, 0, 180, "FD") + pdf.SetLineWidth(thin) + pdf.Arc(45, y+35, 25, 15, 0, 90, 270, "D") + pdf.SetLineWidth(thick) + pdf.Arc(45, y+35, 30, 20, 0, 0, 360, "D") + pdf.SetLineCapStyle("round") + pdf.Arc(135, y+35, 20, 10, 135, 0, 180, "FD") + pdf.SetLineWidth(thin) + pdf.Arc(135, y+35, 25, 15, 135, 90, 270, "D") + pdf.SetLineWidth(thick) + pdf.Arc(135, y+35, 30, 20, 135, 0, 360, "D") + pdf.SetLineWidth(thin) + pdf.SetLineCapStyle("butt") + + x1 := 10.0 + y1 := 10.0 + w1 := 5.0 + h1 := 5.0 + + // 绘制复选框 + pdf.Rect(x1, y1, w1, h1, "D") // 边框 + pdf.Rect(x1+1, y+1, w1-2, h1-2, "DF") + + err := pdf.OutputFileAndClose("./test3.pdf") + if err != nil { + fmt.Println(err) + } +} + +type pdfTable struct { + pdf *gofpdf.Fpdf + columnYList []float64 + style string // 风格 F仅填充 D仅边框 或者DF两个都要 + alignStr string // 对其方式 LCR为水平的左、中、右,TMBA为垂直的上、中、下、基准线 + fontH float64 // 字体高度 + cells []pdfCell // + x float64 + y float64 +} + +type point struct { + x float64 + y float64 +} + +type pdfCell struct { + w float64 // 宽度 + h float64 // 行高 + txtStr string // 文本 + lines int // 判断文本会占几行 + x float64 + y float64 +} + +func (s *pdfTable) addRows(style string, alignStr string, cells ...pdfCell) { + s.style = style + s.alignStr = alignStr + _, s.fontH = s.pdf.GetFontSize() + // 记录需要的最高行高 + x, y := s.pdf.GetXY() // 获取当前位置 + s.x = x + s.y = y + x = s.x + y = s.y + for column, cell := range cells { + y = s.columnYList[column] + lines := s.pdf.SplitText(cell.txtStr, cell.w) + //h := float64(len(lines)) * cell.h + cell.lines = len(lines) + fmt.Println(x, y, len(lines), lines) + cell.x = x + cell.y = y + x = x + cell.w + y = y + cell.h + s.columnYList[column] = y + s.cells = append(s.cells, cell) + } + s.write() +} + +func (s *pdfTable) write() { + // 手动记录并移动坐标 + for _, c := range s.cells { + usedH := float64(c.lines) * s.fontH + margin := (c.h - usedH) / 2.0 + s.pdf.Rect(c.x, c.y, c.w, c.h, s.style) + s.pdf.SetXY(c.x, c.y+margin) // 保持单元格内的文字有边距 + s.pdf.MultiCell(c.w, s.fontH, c.txtStr, "", s.alignStr, false) + } + // 重置变量 + s.cells = nil +} + +func gen3() { + pdf := gofpdf.New("P", "mm", "A4", "") + pdf.AddPage() + pdf.AddUTF8Font("SIMFANG", "", "./SIMFANG.TTF") + pdf.SetFont("SIMFANG", "", float64(10)) + myPdf := pdfTable{pdf: pdf} + myPdf.columnYList = make([]float64, 5) + + width, _ := pdf.GetPageSize() // 页面宽度 + left, _, right, _ := pdf.GetMargins() // 左右边距 + usable := width - left - right // 可用的页面宽度 + _, h := pdf.GetFontSize() // 字体高度 + tableH := h + 2 // 行高 多出2mm的边距 + tableWidth := usable / 5 // 每个单元个的宽度 + pdf.SetFillColor(233, 233, 233) + // 表头 + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 7 * tableH, txtStr: "投保人(投标人)"}, + {w: 50, h: tableH, txtStr: "法人名称/自然人姓名"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "证件类型"}, + {w: tableWidth, h: tableH, txtStr: ""}, + {w: tableWidth, h: tableH, txtStr: "证件号码"}, + {w: tableWidth, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: 3 * tableH, txtStr: "法人性质"}, + {w: tableWidth, h: 3 * tableH, txtStr: "□国有 ☑集体 □民营 □私营 □外资 □合资 □其他"}, + {w: tableWidth, h: 3 * tableH, txtStr: "法人资质"}, + {w: tableWidth, h: 3 * tableH, txtStr: "□特级 ☑一级 □二级 □三级"}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "联系人"}, + {w: tableWidth, h: tableH, txtStr: ""}, + {w: tableWidth, h: tableH, txtStr: "联系电话"}, + {w: tableWidth, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "地址"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 5 * tableH, txtStr: "被保险人(招标人)"}, + {w: 50, h: tableH, txtStr: "法人名称/自然人姓名"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "证件类型"}, + {w: tableWidth, h: tableH, txtStr: ""}, + {w: tableWidth, h: tableH, txtStr: "证件号码"}, + {w: tableWidth, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "招标文件编号"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "联系人"}, + {w: tableWidth, h: tableH, txtStr: ""}, + {w: tableWidth, h: tableH, txtStr: "联系电话"}, + {w: tableWidth, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "地址"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 3 * tableH, txtStr: "投标项目"}, + {w: 50, h: tableH, txtStr: "项目名称"}, + {w: tableWidth, h: tableH, txtStr: ""}, + {w: tableWidth, h: tableH, txtStr: "立项文件号"}, + {w: tableWidth, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "CM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "项目性质"}, + {w: 3 * tableWidth, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 20, h: 0, txtStr: ""}, + {w: 50, h: tableH, txtStr: "项目预计金额"}, + {w: 3 * tableWidth, h: tableH, txtStr: "(人民币)大写: 小写:"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: tableH, txtStr: "保险金额"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 3 * tableWidth, h: tableH, txtStr: "(人民币)大写: 小写:"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: tableH, txtStr: "保险费"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 3 * tableWidth, h: tableH, txtStr: "(人民币)大写: 小写:"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: tableH, txtStr: "绝对免赔额/免赔率"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 3 * tableWidth, h: tableH, txtStr: " /"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: 16 * tableH, txtStr: "特别约定"}, + {w: 0, h: 16 * tableH, txtStr: ""}, + {w: 3 * tableWidth, h: 16 * tableH, txtStr: "1、本保单为见索即付保单,本保单发生保险事故,由保险人先行赔付后,享有对 投保人的代位求偿权。2、本保单项下,本保险在投标有效期到期后28日(含)内或被保 险人延长投标有效期后到期日后28日(含)内保持有效,延长投标有效期无需通知本保险 人,但任何索赔要求应在投标有效期内送达我方。保险失效后由平台将本保单交投标人 退回我司注销。3、兹承诺,在收到被保险人书面通知,说明下列中的任何一条时,保 证在10日内无条件给付给被保险人金额为不超过保险金额的款项。1)投保人在投标有效 期内撤销或修改其投标文件的;2)投保人在中标后,非因不可抗力原因放弃中标、无正 当理由不与招标人订立合同、在签订合同时向招标人提出附加条件、或者不按招标文件 要求提交履约担保金的;3)投标人的投标文件存在《福建省住房和城乡建设厅关于施工 招标项目电子投标文件置同认定与处理的指导意见》 (闽建筑[2018]29号)规定的雷同情 形之一4)投标人中标后,因违法行为导致中标被依法确认无效的;5) 法律、法规规定 的其他没收投标保险金情形。4、我单位在收到招标人索赔申请后10日内无条件给予先 行支付预赔款,赔付流程将根据我单位向宁德市公共资源交易中心提供的《金融机构理 赔流程标准》执行。本保险项下所有权利和义务均受中华人民共和国法律管辖和制约。 查验保函网址:http://www.zking.com/dzbdxzcx.jhtml\n尊敬的客户,您可以通过电话(95312)、公司柜面或登陆公司网站\n(www.zking.com)查询您的保单信息、状态以及理赔情况。如您对查询结果有异议, 请及时致电本公司。\n无其他特别约定"}, + {w: 0, h: 16 * tableH, txtStr: ""}, + {w: 0, h: 16 * tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: tableH, txtStr: "保险合同争议解决方式"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 3 * tableWidth, h: tableH, txtStr: "诉讼"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + myPdf.addRows("", "LM", []pdfCell{ + {w: 70, h: tableH, txtStr: "司法管辖"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 3 * tableWidth, h: tableH, txtStr: "中华人民共和国管辖(港澳台除外)"}, + {w: 0, h: tableH, txtStr: ""}, + {w: 0, h: tableH, txtStr: ""}, + }...) + + err := pdf.OutputFileAndClose("./test4.pdf") + if err != nil { + fmt.Println(err) + } +} diff --git a/dto/request/manage/add_admin_request.go b/dto/request/manage/add_admin_request.go new file mode 100644 index 0000000..2346f73 --- /dev/null +++ b/dto/request/manage/add_admin_request.go @@ -0,0 +1,6 @@ +package manage + +type AddAdminRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} diff --git a/dto/request/manage/login_request.go b/dto/request/manage/login_request.go new file mode 100644 index 0000000..9f823d8 --- /dev/null +++ b/dto/request/manage/login_request.go @@ -0,0 +1,6 @@ +package manage + +type LoginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} diff --git a/dto/request/manage/order_query_request.go b/dto/request/manage/order_query_request.go new file mode 100644 index 0000000..6a26344 --- /dev/null +++ b/dto/request/manage/order_query_request.go @@ -0,0 +1,18 @@ +package manage + +type OrderQueryRequest struct { + PageQueryRequest + OrderSn string `form:"orderSn"` + AssuredName string `form:"assuredName"` + AssuredCreditCode string `form:"assuredCreditCode"` + AssuredContactName string `form:"assuredContactName"` + AssuredContactMobile string `form:"assuredContactMobile"` + ProjectName string `form:"projectName"` + TpId string `form:"tpId"` + ApplicantName string `form:"applicantName"` + ApplicantCreditCode string `form:"applicantCreditCode"` + ApplicantContactName string `form:"applicantContactName"` + ApplicantContactMobile string `form:"applicantContactMobile"` + PolicyNo string `form:"policyNo"` + CreatedAt string `form:"createdAt"` +} diff --git a/dto/request/manage/page_query_request.go b/dto/request/manage/page_query_request.go new file mode 100644 index 0000000..b62dc04 --- /dev/null +++ b/dto/request/manage/page_query_request.go @@ -0,0 +1,6 @@ +package manage + +type PageQueryRequest struct { + Page int `form:"page"` + PageSize int `form:"pageSize"` +} diff --git a/go.mod b/go.mod index 35bfcab..21084de 100644 --- a/go.mod +++ b/go.mod @@ -48,8 +48,9 @@ require ( github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect golang.org/x/arch v0.8.0 // indirect + golang.org/x/image v0.17.0 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/text v0.16.0 // indirect google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/go.sum b/go.sum index 52a6ad0..f7ca780 100644 --- a/go.sum +++ b/go.sum @@ -149,6 +149,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= +golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco= +golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -176,6 +178,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/model/order.go b/model/order.go index e4e2ff8..5f278de 100644 --- a/model/order.go +++ b/model/order.go @@ -6,16 +6,17 @@ import ( ) type Order struct { - ID int - RequestID string - OrderSn string - Token string - User *User `gorm:"foreignKey:OrderSn;references:OrderSn"` - Project *Project `gorm:"foreignKey:OrderSn;references:OrderSn"` - Applicant *Applicant `gorm:"foreignKey:OrderSn;references:OrderSn"` - Assured *Assured `gorm:"foreignKey:OrderSn;references:OrderSn"` - CreatedAt time.Time - UpdatedAt time.Time `json:"-"` + ID int + RequestID string + OrderSn string + Token string + User *User `gorm:"foreignKey:OrderSn;references:OrderSn"` + Project *Project `gorm:"foreignKey:OrderSn;references:OrderSn"` + Applicant *Applicant `gorm:"foreignKey:OrderSn;references:OrderSn"` + Assured *Assured `gorm:"foreignKey:OrderSn;references:OrderSn"` + OrderResult *OrderResult `gorm:"foreignKey:OrderSn;references:OrderSn"` + CreatedAt time.Time + UpdatedAt time.Time `json:"-"` } func (Order) TableName() string { diff --git a/router/manage.go b/router/manage.go index 096bffa..54b1b4c 100644 --- a/router/manage.go +++ b/router/manage.go @@ -2,7 +2,23 @@ package router import ( "github.com/gin-gonic/gin" + "insure/api/manage" + "insure/router/middleware" + "insure/utils/result" ) func adminRouteInit(r *gin.Engine) { + manageGroup := r.Group("/manage") + manageGroup.Use(middleware.CorsMiddleware("manage")) + manageGroup.Match([]string{"POST", "OPTIONS"}, "/login", result.Json(manage.Login)) + + authGroup := manageGroup.Group("") + authGroup.Use(middleware.JwtMiddleware("admin")) + { + authGroup.Match([]string{"GET", "OPTIONS"}, "/get-admin-info", result.Json(manage.GetAdminInfo)) + authGroup.Match([]string{"POST", "OPTIONS"}, "/logout", result.Json(manage.Logout)) + authGroup.Match([]string{"POST", "OPTIONS"}, "/add-admin", result.Json(manage.AddAdmin)) + authGroup.Match([]string{"GET", "OPTIONS"}, "/get-orders", result.Json(manage.GetOrders)) + authGroup.Match([]string{"GET", "OPTIONS"}, "/download-orders", manage.DownloadOrders) + } } diff --git a/service/admin_service.go b/service/admin_service.go index 8c05fae..6ae3355 100644 --- a/service/admin_service.go +++ b/service/admin_service.go @@ -1,6 +1,12 @@ package service -import "insure/model" +import ( + "gorm.io/gorm" + "insure/e" + "insure/global" + "insure/model" + "insure/utils" +) var AdminService = adminService{} @@ -10,3 +16,52 @@ type adminService struct { func (adminService) GetInfo(id int) *model.Admin { return &model.Admin{} } +func (adminService) Login(username string, password string) (string, error) { + admin := &model.Admin{} + err := global.DB.Where("username", username).First(admin).Error + if e.Is(err, gorm.ErrRecordNotFound) { + return "", e.NewError("账号或密码错误") + } + if utils.PasswordVerify(password, admin.PasswordHash) { + return utils.GenerateToken(admin.ID, "admin") + } + return "", e.NewError("账号或密码错误") +} + +func (adminService) Add(username string, password string) error { + admin := &model.Admin{} + err := global.DB.Where("username", username).First(admin).Error + if err == nil { + return e.NewError("账号已存在") + } + admin.Username = username + passwordHash, _ := utils.PasswordHash(password) + admin.PasswordHash = passwordHash + return global.DB.Save(admin).Error +} + +func (adminService) ModifyPassword(password string, oldPassword string, admin *model.Admin) error { + if !utils.PasswordVerify(oldPassword, admin.PasswordHash) { + return e.NewError("旧密码错误") + } + passwordHash, _ := utils.PasswordHash(password) + admin.PasswordHash = passwordHash + return global.DB.Save(admin).Error +} + +func (adminService) ResetPassword(adminID int, password string) error { + admin := &model.Admin{} + err := global.DB.Where("id", adminID).First(admin).Error + if e.Is(err, gorm.ErrRecordNotFound) { + return e.NewError("账号不存在") + } + passwordHash, _ := utils.PasswordHash(password) + admin.PasswordHash = passwordHash + return global.DB.Save(admin).Error +} + +func (adminService) GetAdminInfo(adminID int) *model.Admin { + admin := &model.Admin{} + global.DB.Where("id", adminID).First(admin) + return admin +} diff --git a/service/order_service.go b/service/order_service.go index e49522f..452d74a 100644 --- a/service/order_service.go +++ b/service/order_service.go @@ -4,7 +4,9 @@ import ( "encoding/json" "errors" "fmt" + "github.com/xuri/excelize/v2" "gorm.io/gorm" + "insure/dto/request/manage" "insure/e" "insure/global" "insure/model" @@ -12,6 +14,7 @@ import ( "insure/third_party/suixing" "insure/third_party/zking" "insure/utils" + "insure/utils/excel" "strconv" "time" ) @@ -374,3 +377,134 @@ func (s *orderService) GetOrderResultByToken(token string) (*model.OrderResult, } return &orderResult, nil } + +func (s *orderService) GetOrders(req manage.OrderQueryRequest) ([]model.Order, int64) { + orders := make([]model.Order, req.PageSize) + offset := (req.Page - 1) * req.PageSize + var total int64 + tx := s.buildQuery(req) + tx.Preload("User"). + Preload("Project"). + Preload("Applicant"). + Preload("Assured"). + Order("id desc").Offset(offset).Limit(req.PageSize).Find(&orders) + tx.Model(&model.Order{}).Count(&total) + return orders, total +} +func (s *orderService) buildQuery(req manage.OrderQueryRequest) *gorm.DB { + tx := global.DB + if req.OrderSn != "" { + tx = tx.Where("order_sn", req.OrderSn) + } + if req.AssuredName != "" { + var orderSns []string + global.DB.Model(&model.Assured{}).Where("assured_name", req.AssuredName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredCreditCode != "" { + var orderSns []string + global.DB.Model(&model.Assured{}).Where("credit_code", req.AssuredCreditCode).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredContactName != "" { + var orderSns []string + global.DB.Model(&model.Assured{}).Where("contact_name", req.AssuredContactName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredContactMobile != "" { + var orderSns []string + global.DB.Model(&model.Assured{}).Where("contact_mobile", req.AssuredContactMobile).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.ProjectName != "" { + var orderSns []string + global.DB.Model(&model.Project{}).Where("name", req.ProjectName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.TpId != "" { + var orderSns []string + global.DB.Model(&model.Project{}).Where("tp_id", req.TpId).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.ApplicantName != "" { + var orderSns []string + global.DB.Model(&model.Applicant{}).Where("applicant_name", req.ApplicantName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.ApplicantName != "" { + var orderSns []string + global.DB.Model(&model.Applicant{}).Where("applicant_name", req.ApplicantName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredCreditCode != "" { + var orderSns []string + global.DB.Model(&model.Applicant{}).Where("credit_code", req.AssuredCreditCode).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredContactName != "" { + var orderSns []string + global.DB.Model(&model.Applicant{}).Where("contact_name", req.AssuredContactName).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.AssuredContactMobile != "" { + var orderSns []string + global.DB.Model(&model.Applicant{}).Where("contact_mobile", req.AssuredContactMobile).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + if req.PolicyNo != "" { + var orderSns []string + global.DB.Model(&model.OrderResult{}).Where("policy_no", req.PolicyNo).Pluck("order_sn", &orderSns) + tx = tx.Where("order_sn", orderSns) + } + return tx +} + +func (s *orderService) GenerateOrdersExcel(req manage.OrderQueryRequest) *excelize.File { + pageSize := 200 + lastID := 0 + tx := s.buildQuery(req) + + f := excel.NewFile() + headers := []string{"订单号", "项目编号", "项目名称", "招标人名称", "招标联系人", "招标人身份证", "招标联系手机", "投标人名称", "投标联系人", "投标人身份证", "投标联系手机", "保单号", "下单时间"} + excel.SetSimpleHeaders(headers, "Sheet1", f) + for { + orders := make([]model.Order, pageSize) + tx.Preload("User"). + Preload("Project"). + Preload("Applicant"). + Preload("Assured").Where("id > ?", lastID).Limit(pageSize).Find(&orders) + count := len(orders) + if count == 0 { + break + } + s.buildOrdersExcel(orders, "Sheet1", f) + lastIndex := count - 1 + lastID = orders[lastIndex].ID + } + return f +} + +func (orderService) buildOrdersExcel(orders []model.Order, sheet string, f *excelize.File) { + row := 2 + for _, order := range orders { + col := 0 + policyNo := "" + if order.OrderResult != nil { + policyNo = order.OrderResult.PolicyNo + } + f.SetCellValue(sheet, excel.CellKey(row, &col), order.OrderSn) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Project.TpID) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Project.Name) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Assured.AssuredName) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Assured.ContactName) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Assured.CreditCode) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Assured.ContactMobile) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Applicant.ApplicantName) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Applicant.ContactName) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Applicant.CreditCode) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.Applicant.ContactMobile) + f.SetCellValue(sheet, excel.CellKey(row, &col), policyNo) + f.SetCellValue(sheet, excel.CellKey(row, &col), order.CreatedAt.Format(time.DateTime)) + row++ + } +} diff --git a/static/assets/img/zking_logo.png b/static/assets/img/zking_logo.png new file mode 100644 index 0000000..55c101f Binary files /dev/null and b/static/assets/img/zking_logo.png differ diff --git a/test2.pdf b/test2.pdf index 586708b..a164853 100644 Binary files a/test2.pdf and b/test2.pdf differ diff --git a/test3.pdf b/test3.pdf new file mode 100644 index 0000000..f0dca63 Binary files /dev/null and b/test3.pdf differ diff --git a/test4.pdf b/test4.pdf new file mode 100644 index 0000000..aea900d Binary files /dev/null and b/test4.pdf differ