package pkg2024 import ( "bytes" "compress/gzip" "encoding/json" "errors" "io/ioutil" "math" "os" "sort" "strings" "time" "zhiyuan/models" "zhiyuan/models/final" "zhiyuan/pkg/app" "zhiyuan/pkg/config" "zhiyuan/pkg/db" "zhiyuan/pkg/utils" "github.com/gin-gonic/gin" "github.com/xuri/excelize/v2" ) type Map map[string]interface{} const ( A10 int = iota A8 A5 ZZ1_0 ) type Pkg struct { Type int `form:"type" json:"type"` Layout []int `form:"layout" json:"layout"` Area float64 `form:"area" json:"area"` } type Window struct { Length float64 `form:"length" json:"length"` Width float64 `form:"width" json:"width"` Height float64 `form:"height" json:"height"` } type Space struct { Area float64 `form:"area" json:"area"` WetArea float64 `form:"wet_area" json:"wet_area"` Perimeter float64 `form:"perimeter" json:"perimeter"` DoorwayWidth float64 `form:"doorway_width" json:"doorway_width"` DoorwayHeight float64 `form:"doorway_height" json:"doorway_height"` DoorwayWallThickness float64 `form:"doorway_wall_thickness" json:"doorway_wall_thickness"` WindowNumber int `form:"window_number" json:"window_number"` Windows []Window `form:"windows" json:"windows"` SinkBackfill bool `form:"sink_backfill" json:"sink_backfill"` WideBed bool `form:"wide_bed" json:"wide_bed"` DryWetSeparation bool `form:"dry_wet_separation" json:"dry_wet_separation"` } type RoomData struct { Pkg Pkg `form:"pkg" json:"pkg"` Space [][]Space `form:"space" json:"space"` } type ContractData struct { Design float64 `form:"design" json:"design"` Chart float64 `form:"chart" json:"chart"` Taxes bool `form:"taxes" json:"taxes"` Discount float64 `form:"discount" json:"discount"` } type PkgForm struct { RoomData RoomData `json:"room_data"` RegionData RegionData `json:"region_data"` ContractData ContractData `json:"contract_data"` AdditionalData AdditionalData `json:"additional_data"` DeductionData DeductionData `json:"deduction_data"` BuildBudget BuildBudget `json:"build_budget"` } type BuildItemReturn struct { Name string `json:"name"` Type int `json:"type"` Price float64 `json:"price"` Unit string `json:"unit"` Remark string `json:"remark"` } type PkgReturn struct { RoomData RoomData `json:"room_data"` RegionData RegionReturns `json:"region_data"` ContractData ContractData `json:"contract_data"` BuildBudget BuildBudget `json:"build_budget"` BuildItems []BuildItemReturn `json:"build_item"` } func (from *PkgForm) Init(pkgId int64, area float64, layout []int) error { layouts := []int{1, 1, 1, 1, 0} if layout != nil { for i, l := range layout { if i < len(layouts) && l > layouts[i] { layouts[i] = l } } } pkgs := map[int64]int{3: A10, 4: A8, 5: A5, 16: ZZ1_0} from.RoomData = RoomData{ Pkg: Pkg{ Area: area, Type: pkgs[pkgId], Layout: layouts, }, Space: [][]Space{ {}, {}, {}, {}, {}, }, } for n, l := range layouts { if n == 1 && l > 1 { l = l - 1 } space := Space{ DoorwayHeight: 2.2, DoorwayWidth: 0.9, DoorwayWallThickness: 0.14, WindowNumber: 1, Windows: []Window{ { Length: 1.6, Height: 1.7, Width: 0.24, }, }, } if n == 1 { space = Space{ DoorwayHeight: 2.1, DoorwayWidth: 1.2, DoorwayWallThickness: 0.24, WindowNumber: 0, Windows: []Window{}, } } if n >= 2 { space = Space{ DoorwayHeight: 2, DoorwayWidth: 0.8, DoorwayWallThickness: 0.14, WindowNumber: 1, Windows: []Window{ { Length: 0.8, Height: 1.4, Width: 0.24, }, }, } } if n == 4 { space = Space{ DoorwayHeight: 2.35, DoorwayWidth: 2.4, DoorwayWallThickness: 0.24, WindowNumber: 1, Windows: []Window{ { Length: 5, Height: 2.2, Width: 0.24, }, }, } } for o := 0; o < l; o++ { from.RoomData.Space[n] = append(from.RoomData.Space[n], space) } } from.ContractData.Chart = 15 from.ContractData.Discount = 1 from.RegionData = make(RegionData) from.DeductionData = make(DeductionData) from.AdditionalData.Builds = []BuildAdditionalItem{{ Item: "拆除砖墙(有电梯)", }, { Item: "拆除门垛", }, { Item: "拆除后水泥沙浆粉刷(宽30㎝以内)", }, { Item: "砌门垛", }, { Item: "新砌砖墙(12墙)", }, { Item: "新砌砖墙(24墙)", }, { Item: "过桥板", }, { Item: "卫生间墙面打磨(油性防水层)", }, { Item: "卫生间回填(陶粒回填)", }, { Item: "安装石基", }, { Item: "外墙乳胶漆打磨", }, { Item: "阳台地面防水", }, { Item: "地面找平", }, { Item: "墙面贴砖(400*800mm)", }} from.AdditionalData.Materials = make([]MaterialAdditionalItem, 0) from.AdditionalData.Specials = make([]SpecialProjectItem, 0) return from.Calc() } func (from *PkgForm) UpdateData(data RoomData) error { if data.Pkg.Layout == nil || len(data.Pkg.Layout) != 5 { return errors.New("请输入户型") } if data.Space == nil || len(data.Space) != len(data.Pkg.Layout) { return errors.New("房间数据错误") } for typ, spaces := range data.Space { num := data.Pkg.Layout[typ] if typ == 1 && num > 1 { num = num - 1 } if spaces == nil || len(spaces) != num { return errors.New("房间数据错误") } for _, space := range spaces { if space.WindowNumber != 0 { if space.Windows == nil || len(space.Windows) != space.WindowNumber { return errors.New("房间数据错误") } } } } context := from.NewContext() context.oldRoomData = from.RoomData from.RoomData = data return from.CalcInContext(context) } func (from *PkgForm) RefreshRegion(context *ItemContext) { if from.RegionData == nil { from.RegionData = RegionData{ -1: {}, 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, } } if from.DeductionData == nil { from.DeductionData = DeductionData{ -1: {}, 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, } } for _, n := range []int{-1, 0, 1, 2, 3, 4} { num := 1 if n >= 0 { num = from.RoomData.Pkg.Layout[n] } if n == 1 && num > 1 { num = num - 1 } spaceN := 1 if n >= 0 { spaceN = len(context.Pkg.RoomData.Space[n]) } if spaceN > len(from.RegionData[n]) { spaceN = len(from.RegionData[n]) } context.SpaceType = n for index := 0; index < spaceN; index++ { if n < 0 { context.Space = Space{Area: context.Pkg.RoomData.Pkg.Area} } else { context.Space = context.Pkg.RoomData.Space[n][index] } context.SpaceIndex = index for typ := range from.RegionData[n][index] { region := from.RegionData[n][index][typ] default_ := false suppliers := Regions[n][typ].Suppliers(context) if suppliers != nil { mat := context.GetMat(region.Material) if mat == nil { default_ = true } else { inSupplier := false for _, supplier := range suppliers { if supplier == mat.SupplierId { inSupplier = true break } } if !inSupplier { default_ = true } } } if !default_ && Regions[n][typ].DefaultCalc != nil { defau, _ := Regions[n][typ].DefaultCalc(context) default_ = defau } if context.oldRoomData.Pkg.Type != from.RoomData.Pkg.Type || default_ { material := int64(0) materialName := "" if Regions[n][typ].DefaultMaterialCalc != nil { materia, _ := Regions[n][typ].DefaultMaterialCalc(context) material = materia } else { if Regions[n][typ].DefaultMaterial != nil { material = Regions[n][typ].DefaultMaterial[from.RoomData.Pkg.Type] } } mat := context.GetMat(material) if mat != nil { materialName = mat.Brand + " " + mat.Series + " " + mat.Model + " " + mat.Specs + " " + mat.Color } region.Material = material region.MaterialName = materialName from.RegionData[n][index][typ] = region } } } for m := len(from.RegionData[n]); m < num; m++ { if n < 0 { context.Space = Space{Area: context.Pkg.RoomData.Pkg.Area} } else { context.Space = context.Pkg.RoomData.Space[n][m] } context.SpaceIndex = m regions := make(map[int]Region) for i, region := range Regions[n] { material := int64(0) materialName := "" if region.DefaultMaterialCalc != nil { materia, _ := region.DefaultMaterialCalc(context) material = materia } else { if region.DefaultMaterial != nil { material = region.DefaultMaterial[from.RoomData.Pkg.Type] } } mat := context.GetMat(material) if mat != nil { materialName = mat.Brand + " " + mat.Series + " " + mat.Model + " " + mat.Specs + " " + mat.Color } regions[i] = Region{ Material: material, MaterialName: materialName, Brand: region.DefaultBrand[from.RoomData.Pkg.Type], Series: region.DefaultSeries[from.RoomData.Pkg.Type], } } from.RegionData[n] = append(from.RegionData[n], regions) } for m := len(from.DeductionData[n]); m < num; m++ { from.DeductionData[n] = append(from.DeductionData[n], []int{}) } from.RegionData[n] = from.RegionData[n][:num] from.DeductionData[n] = from.DeductionData[n][:num] } context.Space = Space{} context.SpaceType = 0 context.SpaceIndex = 0 } func (from *PkgForm) Load(pkgId int64, content []byte) error { if len(content) != 0 { gzJson := bytes.NewBuffer(content) gz, err := gzip.NewReader(gzJson) if err != nil { return err } defer gz.Close() jsonData, err := ioutil.ReadAll(gz) if err != nil { return err } decoder := json.NewDecoder(strings.NewReader(string(jsonData))) decoder.UseNumber() err = decoder.Decode(from) if err != nil { return err } /*err = json.Unmarshal(jsonData, from) if err != nil { return nil, err }*/ } else { return from.Init(pkgId, 0, nil) } return nil } func (from *PkgForm) Content() ([]byte, error) { jsonData, err := json.Marshal(from) if err != nil { return nil, err } var gzJson bytes.Buffer gz := gzip.NewWriter(&gzJson) if _, err := gz.Write(jsonData); err != nil { return nil, err } if err := gz.Close(); err != nil { return nil, err } return gzJson.Bytes(), nil } func (from *PkgForm) ReturnResult(statistics []string) interface{} { return from.Return(statistics) } func (from *PkgForm) Return(statistics []string) (pkgReturn PkgReturn) { context := from.NewContext() context.oldRoomData = from.RoomData pkgReturn.RoomData = from.RoomData pkgReturn.RegionData = make(RegionReturns) pkgReturn.BuildItems = make([]BuildItemReturn, 0) pkgReturn.ContractData = from.ContractData for roomType, roomRegions := range from.RegionData { pkgReturn.RegionData[roomType] = make([][]RegionReturn, 0) context.SpaceType = roomType for index, regions := range roomRegions { context.SpaceIndex = index if roomType < 0 { context.Space = Space{Area: from.RoomData.Pkg.Area} } else { context.Space = from.RoomData.Space[roomType][index] } rs := make([]RegionReturn, 0) for n, regionObject := range Regions[roomType] { if region, ok := regions[n]; ok { context.Region = region if regionObject.Show(context) { rs = append(rs, RegionReturn{ Name: regionObject.Name, MaterialName: region.MaterialName, Type: regionObject.Type, BrandList: regionObject.Brand, SeriesList: regionObject.Series, Material: region.Material, Brand: region.Brand, Series: region.Series, Index: n, Note: regionObject.Note, ControlPrice: regionObject.ControlPrice[from.RoomData.Pkg.Type], Convert: regionObject.Convert, Convert1: regionObject.Convert1, Unit: regionObject.Unit, Suppliers: regionObject.Suppliers(context), }) } } } pkgReturn.RegionData[roomType] = append(pkgReturn.RegionData[roomType], rs) } } pkgReturn.BuildBudget = from.BuildBudget statisticMap := make(map[string]int) for _, statistic := range statistics { ss := strings.Split(statistic, ",") for _, s := range ss { statisticMap[s] = statisticMap[s] + 1 } } statisticss := make(map[int][]BuildItemReturn) for _, item := range BuildItems { if item.Price != 0 { if _, ok := statisticss[statisticMap[item.Name]]; !ok { statisticss[statisticMap[item.Name]] = make([]BuildItemReturn, 0) } statisticss[statisticMap[item.Name]] = append(statisticss[statisticMap[item.Name]], BuildItemReturn{ Name: item.Name, Type: item.Type, Price: item.Price, Unit: item.Unit, Remark: item.Remark, }) } } ss := make([]int, 0) for s := range statisticss { ss = append(ss, s) } sort.Ints(ss) sort.Sort(sort.Reverse(sort.IntSlice(ss))) for _, s := range ss { pkgReturn.BuildItems = append(pkgReturn.BuildItems, statisticss[s]...) } return } func (from *PkgForm) UpdateRegion(region RegionFrom) error { context := from.NewContext() materialName := "" if region.Material != 0 { mat := context.GetMat(region.Material) if mat != nil { materialName = mat.Brand + " " + mat.Series + " " + mat.Model + " " + mat.Specs + " " + mat.Color } } from.RegionData[region.SpaceType][region.SpaceIndex][region.Index] = Region{ Material: region.Material, MaterialName: materialName, Brand: region.Brand, Series: region.Series, } context.oldRoomData = from.RoomData return from.CalcInContext(context) } func (from *PkgForm) UpdateContractData(contractData ContractData) error { from.ContractData = contractData if from.ContractData.Discount < 0 { from.ContractData.Discount = 0 } if from.ContractData.Discount > 1 { from.ContractData.Discount = 1 } return from.Calc() } func (from *PkgForm) AddBuildAdditionalItem(item BuildAdditionalItem) error { from.AdditionalData.Builds = append(from.AdditionalData.Builds, item) return from.Calc() } type EditAdditionalItem struct { Index int `json:"index"` Number float64 `json:"number"` } func (from *PkgForm) EditBuildAdditionalItem(item EditAdditionalItem) error { if len(from.AdditionalData.Builds) > item.Index { from.AdditionalData.Builds[item.Index].Number = item.Number } return from.Calc() } func (from *PkgForm) DelBuildAdditionalItem(item EditAdditionalItem) error { from.AdditionalData.Builds = append(from.AdditionalData.Builds[:item.Index], from.AdditionalData.Builds[item.Index+1:]...) return from.Calc() } func (from *PkgForm) AddMaterialAdditionalItem(item MaterialAdditionalItem) error { from.AdditionalData.Materials = append(from.AdditionalData.Materials, item) return from.Calc() } type EditMaterialAdditionalItem struct { Index int `json:"index"` Number float64 `json:"number"` Purchase bool `json:"purchase"` } func (from *PkgForm) EditMaterialAdditionalItem(item EditMaterialAdditionalItem) error { if len(from.AdditionalData.Materials) > item.Index { from.AdditionalData.Materials[item.Index].Number = item.Number from.AdditionalData.Materials[item.Index].Purchase = item.Purchase } return from.Calc() } func (from *PkgForm) DelMaterialAdditionalItem(item EditAdditionalItem) error { from.AdditionalData.Materials = append(from.AdditionalData.Materials[:item.Index], from.AdditionalData.Materials[item.Index+1:]...) return from.Calc() } type Deductionitem struct { SpaceType int `json:"space_type"` SpaceIndex int `json:"space_index"` Index int `json:"index"` } func (from *PkgForm) AddDeductionItem(item Deductionitem) error { if _, ok := from.DeductionData[item.SpaceType]; ok { if len(from.DeductionData[item.SpaceType]) > item.SpaceIndex { have := false for _, d := range from.DeductionData[item.SpaceType][item.SpaceIndex] { if d == item.Index { have = true break } } if !have { from.DeductionData[item.SpaceType][item.SpaceIndex] = append(from.DeductionData[item.SpaceType][item.SpaceIndex], item.Index) } } } return from.Calc() } func (from *PkgForm) DelDeductionItem(item Deductionitem) error { if _, ok := from.DeductionData[item.SpaceType]; ok { if len(from.DeductionData[item.SpaceType]) > item.SpaceIndex { for n, d := range from.DeductionData[item.SpaceType][item.SpaceIndex] { if d == item.Index { from.DeductionData[item.SpaceType][item.SpaceIndex] = append(from.DeductionData[item.SpaceType][item.SpaceIndex][:n], from.DeductionData[item.SpaceType][item.SpaceIndex][n+1:]...) break } } } } return from.Calc() } func (from *PkgForm) AddSpecialProjectItem(item SpecialProjectItem) error { from.AdditionalData.Specials = append(from.AdditionalData.Specials, item) return from.Calc() } type EditSpecialProjectItem struct { Index int `json:"index"` Name string `json:"name"` Type int `json:"type"` Number float64 `json:"number"` Price float64 `json:"price"` Unit string `json:"unit"` Remark string `json:"remark"` } func (from *PkgForm) EditSpecialProjectItem(item EditSpecialProjectItem) error { if len(from.AdditionalData.Specials) > item.Index { from.AdditionalData.Specials[item.Index].Name = item.Name from.AdditionalData.Specials[item.Index].Type = item.Type from.AdditionalData.Specials[item.Index].Number = item.Number from.AdditionalData.Specials[item.Index].Price = item.Price from.AdditionalData.Specials[item.Index].Unit = item.Unit from.AdditionalData.Specials[item.Index].Remark = item.Remark } return from.Calc() } func (from *PkgForm) DelSpecialProjectItem(item EditSpecialProjectItem) error { from.AdditionalData.Specials = append(from.AdditionalData.Specials[:item.Index], from.AdditionalData.Specials[item.Index+1:]...) return from.Calc() } func (from *PkgForm) Handle(c *gin.Context, name string) error { switch name { case "UpdateData": var form RoomData if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.UpdateData(form) case "UpdateContractData": var form ContractData if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.UpdateContractData(form) case "UpdateRegion": var form RegionFrom if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.UpdateRegion(form) case "AddBuildAdditionalItem": var form BuildAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.AddBuildAdditionalItem(form) case "EditBuildAdditionalItem": var form EditAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.EditBuildAdditionalItem(form) case "DelBuildAdditionalItem": var form EditAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.DelBuildAdditionalItem(form) case "AddMaterialAdditionalItem": var form MaterialAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.AddMaterialAdditionalItem(form) case "EditMaterialAdditionalItem": var form EditMaterialAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.EditMaterialAdditionalItem(form) case "DelMaterialAdditionalItem": var form EditAdditionalItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.DelMaterialAdditionalItem(form) case "AddDeductionItem": var form Deductionitem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.AddDeductionItem(form) case "DelDeductionItem": var form Deductionitem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.DelDeductionItem(form) case "AddSpecialProjectItem": var form SpecialProjectItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.AddSpecialProjectItem(form) case "EditSpecialProjectItem": var form EditSpecialProjectItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.EditSpecialProjectItem(form) case "DelSpecialProjectItem": var form EditSpecialProjectItem if app.Bind(c, &form) != nil { return errors.New("参数错误") } return from.DelSpecialProjectItem(form) } return errors.New("找不到操作") } func (from *PkgForm) Export(siteId int64) (string, error) { var site final.FinalSite db.GetModel(map[string]interface{}{"id": siteId}, &site) var designer models.Admin db.GetModel(map[string]interface{}{"id": site.DesignerId}, &designer) types := map[int]string{A10: "1房1价A10套餐", A8: "1房1价A8套餐", A5: "1房1价A5套餐", ZZ1_0: "整装1.0"} template, err := excelize.OpenFile("2024志远1房1价套餐预算模板.xlsx") if err != nil { return "", err } for _, sheet := range template.GetSheetList() { addRows := 0 err = XlsxSetCellValue(template, sheet, 1, 1+addRows, "2024年志远\""+types[from.RoomData.Pkg.Type]+"\"工程预算书(南昌)") if err != nil { return "", err } worksite := site.Village + site.RoomNo if worksite == "" { worksite = site.Address } err = XlsxSetCellValue(template, sheet, 1, 2+addRows, "客 户:"+site.Username+" 联系电话:"+site.Phone+" 工程地址:"+worksite) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 1, 3+addRows, "房 型:("+db.ToString(from.RoomData.Pkg.Layout[0])+")房("+db.ToString(from.RoomData.Pkg.Layout[1])+")厅("+db.ToString(from.RoomData.Pkg.Layout[2])+")厨("+db.ToString(from.RoomData.Pkg.Layout[3])+")卫("+db.ToString(from.RoomData.Pkg.Layout[4])+")阳台 外框面积:"+db.ToString(from.RoomData.Pkg.Area)+"㎡ 设计师:"+db.ToString(designer.Username)) if err != nil { return "", err } spaceTypes := map[int]string{ 0: "房间", 1: "客餐厅", 2: "厨房", 3: "卫生间", 4: "阳台", } type AreaData struct { Name string Value float64 } Areas1 := make([]AreaData, 0) Areas2 := make([]AreaData, 0) Areas3 := make([]AreaData, 0) for _, spaceType := range []int{1, 2, 0, 3, 4} { spaces := from.RoomData.Space[spaceType] for spaceIndex, space := range spaces { spaceName := spaceTypes[spaceType] if len(spaces) > 1 { spaceName += db.ToString(spaceIndex + 1) } areas := []AreaData{{ Name: spaceName + "面积", Value: space.Area, }, { Name: spaceName + "周长", Value: space.Perimeter, }} if spaceType == 3 { Areas2 = append(Areas2, areas...) } else if spaceType == 4 { Areas3 = append(Areas3, areas...) } else { Areas1 = append(Areas1, areas...) } } } areas2Col := 4 if len(Areas3) == 0 { areas2Col = 6 } addLine := int(math.Max(math.Max(math.Ceil(float64(len(Areas1))/float64(areas2Col)), math.Ceil(float64(len(Areas2))/2)), math.Ceil(float64(len(Areas3))/2)) - 3) if addLine > 0 { for n := 0; n < addLine; n++ { err := XlsxInsertRow(template, sheet, 6+addRows) if err != nil { return "", err } } } for i, area := range Areas1 { row := int(float64(i) / float64(areas2Col)) col := (i - int(row)*areas2Col) * 2 err = XlsxSetCellValue(template, sheet, 1+col, 4+addRows+row, area.Name) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 2+col, 4+addRows+row, area.Value) if err != nil { return "", err } } for i, area := range Areas2 { row := int(float64(i) / 2) col := (i - int(row)*2) * 2 err = XlsxSetCellValue(template, sheet, 1+col+areas2Col*2, 4+addRows+row, area.Name) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 2+col+areas2Col*2, 4+addRows+row, area.Value) if err != nil { return "", err } } for i, area := range Areas3 { row := int(float64(i) / 2) col := (i - int(row)*2) * 2 err = XlsxSetCellValue(template, sheet, 3+col+areas2Col*2, 4+addRows+row, area.Name) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 4+col+areas2Col*2, 4+addRows+row, area.Value) if err != nil { return "", err } } if addLine > 0 { addRows += addLine } err = XlsxSetCellValue(template, sheet, 1, 15+addRows, ""+types[from.RoomData.Pkg.Type]+"预算") if err != nil { return "", err } err = XlsxSetRow(template, sheet, 16+addRows, []interface{}{"", 1, "", "", types[from.RoomData.Pkg.Type], "房", 1, from.BuildBudget.Contract.PkgPrice, "", from.BuildBudget.Contract.PkgPrice, "内容详见《2024年志远" + types[from.RoomData.Pkg.Type] + "产品说明表》"}) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 8, 17+addRows, from.BuildBudget.Contract.PkgTotal) if err != nil { return "", err } addLine = len(from.BuildBudget.MaterialAdditionalItems) - 1 if addLine > 0 { for n := 0; n < addLine; n++ { err := template.DuplicateRow(sheet, 20+addRows) if err != nil { return "", err } } } if addLine < 0 { template.RemoveRow(sheet, 20+addRows) } for i, item := range from.BuildBudget.MaterialAdditionalItems { err = XlsxSetRow(template, sheet, 20+addRows+i, []interface{}{"", i + 1, "", "", item.Name, item.Unit, item.Number, item.Price, "", item.Total, item.Remark}) if err != nil { return "", err } } addRows += addLine err = XlsxSetCellValue(template, sheet, 10, 21+addRows, from.BuildBudget.Contract.MaterialTotal) if err != nil { return "", err } addLine = len(from.BuildBudget.BuildAdditionalItems) - 1 if addLine > 0 { for n := 0; n < addLine; n++ { err := template.DuplicateRow(sheet, 23+addRows) if err != nil { return "", err } } } if addLine < 0 { template.RemoveRow(sheet, 23+addRows) } for i, item := range from.BuildBudget.BuildAdditionalItems { err = XlsxSetRow(template, sheet, 23+addRows+i, []interface{}{"", i + 1, "", "", item.Name, item.Unit, item.Number, item.Price, "", item.Total, item.Remark}) if err != nil { return "", err } } addRows += addLine err = XlsxSetCellValue(template, sheet, 10, 24+addRows, from.BuildBudget.PersonalBuildCost.Direct) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 25+addRows, from.BuildBudget.Contract.PersonalAmount) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 26+addRows, from.BuildBudget.Contract.PersonalTransport) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 27+addRows, from.BuildBudget.Contract.PersonalSanitation) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 28+addRows, from.BuildBudget.Contract.PersonalManage) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 29+addRows, from.BuildBudget.Contract.PersonalTotal) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 7, 30+addRows, from.RoomData.Pkg.Area) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 8, 30+addRows, from.ContractData.Chart) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 30+addRows, from.BuildBudget.Contract.ChartPrice) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 7, 31+addRows, from.RoomData.Pkg.Area) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 8, 31+addRows, from.ContractData.Design) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 31+addRows, from.BuildBudget.Contract.DesignPrice) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 32+addRows, from.BuildBudget.Contract.DirectTotal) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 33+addRows, from.BuildBudget.Contract.DirectCost) if err != nil { return "", err } addLine = len(from.BuildBudget.MaterialPurchaseItems) - 1 if addLine > 0 { for n := 0; n < addLine; n++ { err := template.DuplicateRow(sheet, 36+addRows) if err != nil { return "", err } } } if addLine < 0 { template.RemoveRow(sheet, 36+addRows) } for i, item := range from.BuildBudget.MaterialPurchaseItems { err = XlsxSetRow(template, sheet, 36+addRows+i, []interface{}{"", i + 1, "", "", item.Name, item.Unit, item.Number, item.Price, "", item.Total, item.Remark}) if err != nil { return "", err } } addRows += addLine err = XlsxSetCellValue(template, sheet, 10, 37+addRows, from.BuildBudget.Contract.MaterialPurchaseTotal) if err != nil { return "", err } addLine = len(from.BuildBudget.BuildSpecialItems) - 1 if addLine > 0 { for n := 0; n < addLine; n++ { err := template.DuplicateRow(sheet, 39+addRows) if err != nil { return "", err } } } if addLine < 0 { template.RemoveRow(sheet, 39+addRows) } for i, item := range from.BuildBudget.BuildSpecialItems { err = XlsxSetRow(template, sheet, 39+addRows+i, []interface{}{"", i + 1, "", "", item.Name, item.Unit, item.Number, item.Price, "", item.Total, item.Remark}) if err != nil { return "", err } } addRows += addLine err = XlsxSetCellValue(template, sheet, 10, 40+addRows, from.BuildBudget.Contract.SpecialProjectTotal) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 41+addRows, from.BuildBudget.Contract.PurchaseTotal) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 42+addRows, from.BuildBudget.Contract.Cost) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 43+addRows, from.BuildBudget.Contract.Taxes) if err != nil { return "", err } err = XlsxSetCellValue(template, sheet, 10, 44+addRows, from.BuildBudget.Contract.CostTotal) if err != nil { return "", err } addLine = len(from.BuildBudget.MaterialDeductionItems) - 1 if addLine > 0 { for n := 0; n < addLine; n++ { err := template.DuplicateRow(sheet, 50+addRows) if err != nil { return "", err } } } if addLine < 0 { template.RemoveRow(sheet, 50+addRows) } for i, item := range from.BuildBudget.MaterialDeductionItems { err = XlsxSetRow(template, sheet, 50+addRows+i, []interface{}{"", i + 1, "", "", item.Name, item.Unit, item.Number, item.Price, "", item.Total, item.Remark}) if err != nil { return "", err } } addRows += addLine err = XlsxSetCellValue(template, sheet, 10, 51+addRows, from.BuildBudget.Contract.MaterialDeductionTotal) if err != nil { return "", err } } exportFileName := utils.ToStr(time.Now().UnixNano()) + ".xlsx" b, err := template.WriteToBuffer() if err != nil { return "", err } f, err := os.Create(config.Cfg.App.ExportPath + exportFileName) if err != nil { return "", err } defer f.Close() _, _ = b.WriteTo(f) return exportFileName, nil } func (from *PkgForm) UpdateAmount(data map[string]interface{}) map[string]interface{} { data["套餐小计"] = from.BuildBudget.Contract.PkgTotal data["个性化汇总"] = from.BuildBudget.Contract.PersonalTotal data["个性化材料小计"] = from.BuildBudget.Contract.MaterialTotal data["个性化施工小计"] = from.BuildBudget.Contract.PersonalBuildTotal data["制图费"] = from.BuildBudget.Contract.ChartPrice data["设计费"] = from.BuildBudget.Contract.DesignPrice data["工程直接费"] = from.BuildBudget.Contract.DirectTotal data["工程直接费优惠后金额"] = from.BuildBudget.Contract.DirectCost data["主材代购汇总"] = from.BuildBudget.Contract.MaterialPurchaseTotal data["特殊项目金额汇总"] = from.BuildBudget.Contract.SpecialProjectTotal data["税金"] = from.BuildBudget.Contract.Taxes data["减项金额"] = from.BuildBudget.Contract.MaterialDeductionTotal data["合同总金额"] = from.BuildBudget.Contract.CostTotal return data } func (from *PkgForm) ManagerPrice() map[string]float64 { return map[string]float64{ "项目监理承包额": from.BuildBudget.PackageAmount, "补贴费": from.BuildBudget.SubsidyCollect, } } func (from *PkgForm) BuildControl() map[string]float64 { return map[string]float64{ "拆除": from.BuildBudget.ControlAmount[拆除], "水电基础": from.BuildBudget.ControlAmount[水电基础], "水电安装": from.BuildBudget.ControlAmount[水电安装], "防水": from.BuildBudget.ControlAmount[防水], "泥工": from.BuildBudget.ControlAmount[泥工], "木工": from.BuildBudget.ControlAmount[木工], "油漆工": from.BuildBudget.ControlAmount[油漆], "沙石材料": from.BuildBudget.ControlAmount[沙石材料], "封包管道": from.BuildBudget.ControlAmount[封包管道], "杂费": from.BuildBudget.ControlAmount[杂费], "开关面板": from.BuildBudget.ControlAmount[开关面板], } } func (from *PkgForm) AuxiliaryControl() map[string]float64 { return map[string]float64{ "水电材料": from.BuildBudget.ControlAmount[水电材料], "木工材料": from.BuildBudget.ControlAmount[木工材料], "油漆材料": from.BuildBudget.ControlAmount[油漆材料], "开工形象": from.BuildBudget.ControlAmount[开工形象], } } func (from *PkgForm) Materials() map[int64]float64 { materials := make(map[int64]float64) for _, mss := range from.BuildBudget.Materials { for _, ms := range mss { for _, m := range ms { if m.Material != 0 { materials[m.Material] = utils.FloatAdd(materials[m.Material], m.Number, -1) } } } } return materials } func (from *PkgForm) Statistics() string { items := make([]string, 0) for _, build := range from.AdditionalData.Builds { items = append(items, build.Item) } return strings.Join(items, ",") } func XlsxInsertRow(file *excelize.File, sheet string, row int) error { err := file.InsertRows(sheet, row+1, 1) if err != nil { return err } height, err := file.GetRowHeight(sheet, row) if err != nil { return err } err = file.SetRowHeight(sheet, row+1, height) if err != nil { return err } mergeCells, err := file.GetMergeCells(sheet) if err != nil { return err } for _, mergeCell := range mergeCells { sc, sr, err := excelize.CellNameToCoordinates(mergeCell.GetStartAxis()) if err != nil { return err } if sr == row { ec, er, err := excelize.CellNameToCoordinates(mergeCell.GetEndAxis()) if err != nil { return err } cell1, _ := excelize.CoordinatesToCellName(sc, sr+1) cell2, _ := excelize.CoordinatesToCellName(ec, er+1) err = file.MergeCell(sheet, cell1, cell2) if err != nil { return err } } } for n := 1; n <= 20; n++ { cell, err := excelize.CoordinatesToCellName(n, row) if err != nil { return err } style, err := file.GetCellStyle(sheet, cell) if err != nil { return err } cell, err = excelize.CoordinatesToCellName(n, row+1) if err != nil { return err } err = file.SetCellStyle(sheet, cell, cell, style) if err != nil { return err } } return nil } func XlsxSetCellValue(file *excelize.File, sheet string, col int, row int, value interface{}) error { cell, err := excelize.CoordinatesToCellName(col, row) if err != nil { return err } err = file.SetCellValue(sheet, cell, value) if err != nil { return err } return nil } func XlsxSetRow(file *excelize.File, sheet string, row int, values []interface{}) error { for i, value := range values { cell, err := excelize.CoordinatesToCellName(i+1, row) if err != nil { return err } err = file.SetCellValue(sheet, cell, value) if err != nil { return err } } return nil }