Parcourir la source

Merge branch 'feature/eta_2.6.9'

hsun il y a 5 jours
Parent
commit
ed8c9cd2ac

+ 32 - 1
controllers/report_chapter.go

@@ -8,6 +8,7 @@ import (
 	"eta/eta_api/services"
 	"eta/eta_api/services/data"
 	"eta/eta_api/utils"
+	"fmt"
 	"html"
 	"os"
 	"path"
@@ -923,6 +924,7 @@ func (this *ReportController) GetDayWeekChapter() {
 		ReportChapterItem:      *chapterItem,
 		GrandAdminIdList:       chapterGrantIdList,
 		PermissionIdList:       chapterPermissionIdList,
+		FreeReportRatio:        reportInfo.FreeReportRatio,
 	}
 
 	// 获取当前编辑状态
@@ -974,11 +976,31 @@ func (this *ReportController) ChapterMove() {
 		br.ErrMsg = "参数解析失败,Err:" + e.Error()
 		return
 	}
-
 	if req.ReportChapterId == 0 {
 		br.Msg = "请选择要移动的章节"
 		return
 	}
+	chapter, e := models.GetReportChapterInfoById(req.ReportChapterId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "章节不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取报告章节失败, %v", e)
+		return
+	}
+	reportItem, e := models.GetReportByReportId(chapter.ReportId)
+	if e != nil {
+		if e.Error() == utils.ErrNoRow() {
+			br.Msg = "报告不存在,请刷新页面"
+			return
+		}
+		br.Msg = "操作失败"
+		br.ErrMsg = fmt.Sprintf("获取报告失败, %v", e)
+		return
+	}
+
 	e, msg := services.MoveReportChapter(&req)
 	if e != nil {
 		br.Msg = msg
@@ -986,6 +1008,15 @@ func (this *ReportController) ChapterMove() {
 		return
 	}
 
+	// 如果报告的布局是自由布局,那么查询下涉及移动的章节是否均已发布,如果均已发布那么需要重新排序页脚(未发布时会重新排不用管)
+	if reportItem.ReportLayout == 3 {
+		if e = services.ResortFreeChapter(reportItem.Id); e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = fmt.Sprintf("自由布局章节重新排序失败, %v", e)
+			return
+		}
+	}
+
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "操作成功"

+ 1 - 0
controllers/report_v2.go

@@ -479,6 +479,7 @@ func (this *ReportController) Add() {
 	item.AdminRealName = sysUser.RealName
 	item.ClassifyIdThird = req.ClassifyIdThird
 	item.ClassifyNameThird = classifyMap[req.ClassifyIdThird]
+	item.FreeReportRatio = req.FreeReportRatio
 
 	// 产品要求,如果是多人协作,那么就是章节类型的报告
 	if req.CollaborateType == 2 {

+ 8 - 3
models/report.go

@@ -94,6 +94,7 @@ type Report struct {
 	RaiReportId         int       `description:"RAI报告ID"`
 	FreeLayoutConfig    string    `description:"'自由布局配置"`
 	MiniShow            int       `description:"是否在C端展示:0-否;1-是"`
+	FreeReportRatio     string    `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 func (m *Report) AfterFind(db *gorm.DB) (err error) {
@@ -173,6 +174,7 @@ type ReportList struct {
 	InheritReportId     int       `description:"待继承的报告ID"`
 	RaiReportId         int       `description:"RAI报告ID"`
 	MiniShow            int       `description:"是否在C端展示:0-否;1-是"`
+	FreeReportRatio     string    `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 func (m *ReportList) AfterFind(db *gorm.DB) (err error) {
@@ -453,6 +455,7 @@ type ReportDetail struct {
 	RaiReportId         int       `description:"RAI报告ID"`
 	FreeLayoutConfig    string    `description:"'自由布局配置"`
 	MiniShow            int       `description:"是否在C端展示:0-否;1-是"`
+	FreeReportRatio     string    `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 func (m *ReportDetail) AfterFind(db *gorm.DB) (err error) {
@@ -626,6 +629,7 @@ type AddReq struct {
 	InheritReportId    int    `description:"待继承的报告ID"`
 	GrantAdminIdList   []int  `description:"授权用户id列表"`
 	MiniShow           int    `description:"是否在C端展示:0-否;1-是"`
+	FreeReportRatio    string `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 type PrePublishReq struct {
@@ -674,9 +678,10 @@ type EditReq struct {
 	EndResourceId      int    `description:"版尾资源ID"`
 	//CollaborateType    int8   `description:"协作方式,1:个人,2:多人协作。默认:1"`
 	//ReportLayout       int8   `description:"报告布局,1:常规布局,2:智能布局,3:自由布局。默认:1"`
-	IsPublicPublish  int8  `description:"是否公开发布,1:是,2:否"`
-	GrantAdminIdList []int `description:"授权用户id列表"`
-	MiniShow         int   `description:"是否在C端展示:0-否;1-是"`
+	IsPublicPublish  int8   `description:"是否公开发布,1:是,2:否"`
+	GrantAdminIdList []int  `description:"授权用户id列表"`
+	MiniShow         int    `description:"是否在C端展示:0-否;1-是"`
+	FreeReportRatio  string `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 type EditResp struct {

+ 15 - 0
models/report/report_free_layout.go

@@ -4,6 +4,7 @@ import (
 	sql2 "database/sql"
 	"eta/eta_api/global"
 	"eta/eta_api/utils"
+	"fmt"
 	"gorm.io/gorm"
 	"gorm.io/gorm/clause"
 	"time"
@@ -264,3 +265,17 @@ func GetAllReportFreeLayoutListByReportId(reportId int) (list []*ReportFreeLayou
 
 	return
 }
+
+// ResetReportFreeLayoutsPage 更新自由布局页脚
+func ResetReportFreeLayoutsPage(items []*ReportFreeLayout) (err error) {
+	if len(items) == 0 {
+		return
+	}
+	sql := `UPDATE report_free_layout SET page = ? WHERE id = ? LIMIT 1`
+	for _, v := range items {
+		if e := global.DbMap[utils.DbNameReport].Exec(sql, v.Page, v.Id).Error; e != nil {
+			return fmt.Errorf("ResetReportFreeLayoutsPage, %v", e)
+		}
+	}
+	return
+}

+ 1 - 0
models/report_chapter.go

@@ -145,6 +145,7 @@ type ReportChapterItemResp struct {
 	EndImg                 string `description:"报告尾图地址"`
 	HeadStyle              string `description:"版头样式"`
 	EndStyle               string `description:"版尾样式"`
+	FreeReportRatio        string `description:"自由布局页面比例:A4; 16:9; 4:3; 10:7"`
 }
 
 type ReportChapterResp struct {

+ 1 - 1
models/report_v2.go

@@ -377,7 +377,7 @@ func GetReportListCountByAuthorized(condition string, pars []interface{}) (count
 func GetReportListByAuthorized(condition string, pars []interface{}, startSize, pageSize int) (items []*ReportList, err error) {
 	o := global.DbMap[utils.DbNameReport]
 
-	sql := `SELECT id,classify_id_first,classify_name_first,classify_id_second,classify_name_second,classify_id_third,classify_name_third,title,stage,create_time,author,report_layout,collaborate_type,is_public_publish,abstract,has_chapter,publish_time,mini_show FROM report as a WHERE 1=1  `
+	sql := `SELECT id,classify_id_first,classify_name_first,classify_id_second,classify_name_second,classify_id_third,classify_name_third,title,stage,create_time,author,report_layout,collaborate_type,is_public_publish,abstract,has_chapter,publish_time,mini_show,free_report_ratio FROM report as a WHERE 1=1  `
 	if condition != "" {
 		sql += condition
 	}

+ 53 - 0
services/report_chapter.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_api/models/system"
 	"eta/eta_api/utils"
 	"fmt"
+	"sort"
 	"time"
 )
 
@@ -240,3 +241,55 @@ func CheckChapterAuthByReportChapterInfo(sysUser *system.Admin, createAdminId in
 
 	return
 }
+
+// ResortFreeChapter 自由布局章节重新排序页脚
+func ResortFreeChapter(reportId int) (err error) {
+	// 获取排序后的章节列表
+	chapters, e := models.GetChapterListByReportId(reportId)
+	if e != nil {
+		err = fmt.Errorf("获取报告章节列表失败, %v", e)
+		return
+	}
+	sortChapter := make(map[int]int)
+	for _, v := range chapters {
+		// 如果存在任一章节未发布,那么无需重排
+		if v.PublishState != 2 {
+			return
+		}
+		sortChapter[v.ReportChapterId] = v.Sort
+	}
+
+	// 获取自由章节布局,根据章节顺序重新排序
+	layouts, e := report.GetAllReportFreeLayoutListByReportId(reportId)
+	if e != nil {
+		err = fmt.Errorf("获取章节自由布局失败, %v", e)
+		return
+	}
+	sort.Slice(layouts, func(i, j int) bool {
+		a := layouts[i]
+		b := layouts[j]
+		if a.ReportChapterId == b.ReportChapterId {
+			return a.Page < b.Page
+		}
+		return sortChapter[a.ReportChapterId] < sortChapter[b.ReportChapterId]
+	})
+
+	// 重排序并进行更新
+	updateLayouts := make([]*report.ReportFreeLayout, 0)
+	var resort int
+	for _, layout := range layouts {
+		resort += 1
+		if layout.Page != resort {
+			layout.Page = resort
+			updateLayouts = append(updateLayouts, layout)
+		}
+	}
+	if len(updateLayouts) == 0 {
+		return
+	}
+	if e = report.ResetReportFreeLayoutsPage(updateLayouts); e != nil {
+		err = fmt.Errorf("批量更新自由布局页脚失败, %v", e)
+		return
+	}
+	return
+}

+ 2 - 1
services/report_v2.go

@@ -228,7 +228,7 @@ func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.A
 	reportInfo.State = state
 
 	//updateCols := []string{"ClassifyIdFirst", "ClassifyNameFirst", "ClassifyIdSecond", "ClassifyNameSecond", "ClassifyIdThird", "ClassifyNameThird", "Title", "Abstract", "Author", "Frequency", "Stage", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime"}
-	updateCols := []string{"Title", "Abstract", "Author", "Frequency", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime", "State", "MiniShow"}
+	updateCols := []string{"Title", "Abstract", "Author", "Frequency", "CreateTime", "IsPublicPublish", "LastModifyAdminId", "LastModifyAdminName", "ModifyTime", "State", "MiniShow", "FreeReportRatio"}
 
 	if req.HeadResourceId > 0 {
 		reportInfo.HeadResourceId = req.HeadResourceId
@@ -239,6 +239,7 @@ func EditReport(reportInfo *models.Report, req models.EditReq, sysUser *system.A
 		updateCols = append(updateCols, "EndResourceId")
 	}
 	reportInfo.MiniShow = req.MiniShow
+	reportInfo.FreeReportRatio = req.FreeReportRatio
 
 	// 需要添加的报告授权数据
 	addReportAdminList := make([]*report.ReportGrant, 0)

+ 67 - 13
services/smart_report.go

@@ -8,10 +8,12 @@ import (
 	"eta/eta_api/utils"
 	"fmt"
 	"html"
+	"math"
 	"os"
 	"os/exec"
 	"path"
 	"strconv"
+	"strings"
 	"time"
 )
 
@@ -136,7 +138,7 @@ func SmartReportElasticUpsert(smartReportId int, state int) (err error) {
 	return
 }
 
-func ReportToPdf(width int, reportUrl, filePath string, top, bottom, left, right int) (err error) {
+func ReportToPdf(width, height int, reportUrl, filePath string, top, bottom, left, right int) (err error) {
 	pyCode := `
 import asyncio
 from pyppeteer import launch
@@ -152,7 +154,7 @@ async def main():
     page = await browser.newPage()
     await page.setViewport({
         'width': %d,
-        'height': 1697
+        'height': %d
     })
     await page.goto('%s', {
         'waitUntil': 'networkidle0',
@@ -164,7 +166,7 @@ async def main():
 
     await page.pdf({
 		'width': %d,
-        'height': 1697,
+        'height': %d,
         'path': "%s",
         'printBackground': True,
         'margin': {
@@ -187,7 +189,7 @@ finally:
     loop.close()
 `
 
-	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, width, reportUrl, width+left+right, filePath, top, bottom, left, right)
+	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, width, height, reportUrl, width+left+right, height+top+bottom, filePath, top, bottom, left, right)
 	utils.FileLog.Info("pdf pyCode: \n" + pyCode)
 	cmd := exec.Command(utils.CommandPython, "-c", pyCode)
 	output, e := cmd.CombinedOutput()
@@ -204,7 +206,7 @@ finally:
 	return
 }
 
-func ReportToJpeg(width int, reportUrl, filePath string) (err error) {
+func ReportToJpeg(width, height int, reportUrl, filePath string) (err error) {
 	pyCode := `
 import asyncio
 from pyppeteer import launch, errors
@@ -224,7 +226,7 @@ async def main():
         # 设置视口大小
         await page.setViewport({
             'width': %d,
-            'height': 1697
+            'height': %d
         })
         
         # 导航到页面
@@ -265,7 +267,7 @@ finally:
     loop.close()
 `
 
-	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, width, reportUrl, filePath)
+	pyCode = fmt.Sprintf(pyCode, utils.ChromePath, width, height, reportUrl, filePath)
 	utils.FileLog.Info("jpeg pyCode: \n" + pyCode)
 	cmd := exec.Command(utils.CommandPython, "-c", pyCode)
 	output, e := cmd.CombinedOutput()
@@ -304,6 +306,13 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 	}
 	var report *models.ReportDetail
 
+	// 默认宽高,自由布局需要根据比例重新计算
+	var freeRatio string
+	pcWidth := 1200
+	pcHeight := 1697
+	mobileWidth := 600
+	mobileHeight := 1697
+
 	// 先清空字段
 	if reportType == 1 {
 		report, err = models.GetReportById(reportId)
@@ -315,6 +324,9 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 			utils.FileLog.Info("清空pdf长图字段失败, Err: \n" + err.Error())
 			return
 		}
+		if report.ReportLayout == 3 {
+			freeRatio = report.FreeReportRatio
+		}
 	} else if reportType == 2 {
 		err = models.UpdatePdfUrlEnglishReportById(reportId)
 		if err != nil {
@@ -329,6 +341,23 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 		}
 	}
 
+	// 重新计算比例
+	if freeRatio != "" {
+		h, e := calculateReportPdfHeight(pcWidth, freeRatio)
+		if e != nil {
+			err = fmt.Errorf("重新计算PDF生成高度失败, %v", e)
+			return
+		}
+		pcHeight = h
+
+		hm, e := calculateReportPdfHeight(mobileWidth, freeRatio)
+		if e != nil {
+			err = fmt.Errorf("重新计算移动端PDF生成高度失败, %v", e)
+			return
+		}
+		mobileHeight = hm
+	}
+
 	reportCode := utils.MD5(strconv.Itoa(reportId))
 
 	// pc端
@@ -336,7 +365,7 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 		pdfPath := `./static/` + reportCode + "_1200.pdf"
 		jpegPath := `./static/` + reportCode + "_1200.jpg"
 
-		width := 1200
+		//width := 1200
 		top, bottom, left, right := 20, 20, 20, 20
 		if reportType == 1 {
 			if report != nil && report.ReportLayout == 3 {
@@ -346,7 +375,7 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 		//if reportType == 3 {
 		//	width = 800
 		//}
-		err = ReportToPdf(width, reportUrl, pdfPath, top, bottom, left, right)
+		err = ReportToPdf(pcWidth, pcHeight, reportUrl, pdfPath, top, bottom, left, right)
 		if err != nil {
 			utils.FileLog.Info("ReportToPdf failed: , error: \n" + err.Error())
 			go alarm_msg.SendAlarmMsg("ReportToPdf failed:"+err.Error(), 3)
@@ -406,7 +435,7 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 
 		time.Sleep(1 * time.Minute)
 
-		err = ReportToJpeg(width, reportUrl, jpegPath)
+		err = ReportToJpeg(pcWidth, pcHeight, reportUrl, jpegPath)
 		if err != nil {
 			utils.FileLog.Info("ReportToJpeg failed: , error: \n" + err.Error())
 		}
@@ -472,8 +501,8 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 			pdfPathMobile := `./static/` + reportCode + "_600.pdf"
 			jpegPathMobile := `./static/` + reportCode + "_600.jpg"
 			top, bottom, left, right := 20, 20, 20, 20
-			width := 600
-			err = ReportToPdf(width, reportUrl, pdfPathMobile, top, bottom, left, right)
+			//width := 600
+			err = ReportToPdf(mobileWidth, mobileHeight, reportUrl, pdfPathMobile, top, bottom, left, right)
 			if err != nil {
 				utils.FileLog.Info("ReportToPdf failed: , error: \n" + err.Error())
 				go alarm_msg.SendAlarmMsg("ReportToPdf failed:"+err.Error(), 3)
@@ -533,7 +562,7 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 
 			time.Sleep(1 * time.Minute)
 
-			err = ReportToJpeg(width, reportUrl, jpegPathMobile)
+			err = ReportToJpeg(mobileWidth, mobileHeight, reportUrl, jpegPathMobile)
 			if err != nil {
 				utils.FileLog.Info("ReportToJpeg failed: , error: \n" + err.Error())
 			}
@@ -589,3 +618,28 @@ func Report2pdfAndJpeg(reportUrl string, reportId, reportType int) {
 		}()
 	}
 }
+
+// calculateReportPdfHeight 自由布局-根据宽度和布局比例计算高度
+func calculateReportPdfHeight(width int, freeRatio string) (height int, err error) {
+	ratioArr := strings.Split(freeRatio, "/")
+	if len(ratioArr) != 2 {
+		err = fmt.Errorf("布局比例有误, %s", freeRatio)
+		return
+	}
+	m, e := strconv.ParseFloat(ratioArr[0], 64)
+	if e != nil {
+		err = fmt.Errorf("布局比例有误, %s", freeRatio)
+		return
+	}
+	n, e := strconv.ParseFloat(ratioArr[1], 64)
+	if e != nil {
+		err = fmt.Errorf("布局比例有误, %s", freeRatio)
+		return
+	}
+	if m <= 0 {
+		err = fmt.Errorf("布局比例有误, %s", freeRatio)
+		return
+	}
+	height = int(math.Round(float64(width) * n / m))
+	return
+}