1 配置

因为本平台功能之一为项目查询用,所以必要的项目信息是必不可少的。
还要区分水利、电力、市政、交通……

2 工程费用表分级

目前支持6级,即工程费用在4 ~ 6级,前面必须有3级,第一级是专业,例如建筑工程、机电工程……第2级是工程部位,第3级是部位往下细分,第4级是继续细分
水利行业:

电力行业:

3 数据表设计

对于费用表,1 ~ 5级分了3个表,是否必要??第一级和第二级分别各为一个表,3 ~ 5为一个表,因为可能是3级,也可能是4级也可能是5级,不确定。
工程量单价在第4 ~ 6级。
经过对比,还是放一个表比较合理,查询比较方便。
但是对于树状数据的递归查询,似乎没办法做到分页查询?

// 项目表
type EstimateProject struct {
    gorm.Model
    Number  string `json:"number"`
    Name    string `json:"name"`
    Profile string `json:"profile"`
    Grade   string `json:"grade"`
    Period  int    `json:"period"`
    UserID  int64
    // User    User `json:"user" gorm:"foreignKey:UserID;references:Id;"` // 这个写法错误,所以无法建表
}

// 项目——阶段——价格水平
type EstimateProjPhase struct {
    gorm.Model
    EstimateProjectID uint    `json:"estimateprojectid"`
    PhaseName         string  `json:"phasename"`        // 项目阶段
    Information       string  `json:"information"`      // 价格水平年
    TotalInvestment   float64 `json:"totalinvestment"`  // 总投资
    StaticInvestment  float64 `json:"staticinvestment"` // 静态投资
}

// 作废!项目——阶段——工程专业部分professional
type EstimateProfessional struct {
    gorm.Model
    EstimateProjPhaseID uint   `json:"estimateprojphaseid"`
    Component           string `json:"component"`
    Total               float64 `json:"total"`
}

// 作废!工程专业部分——工程二级Secondary
type EstimateSecondary struct {
    gorm.Model
    EstimateProfessionalID uint   `json:"estimateprofessionalid"`
    Number                 string `json:"number"`
    Component              string `json:"component"`
    Total                  float64 `json:"total"`
}

// 作废!工程二级——工程三~六级
type EstimateTertiary struct {
    gorm.Model
    EstimateSecondaryID uint   `json:"estimatesecondaryid"`
    ParentID            uint   `json:"parentid"`
    Number              string `json:"number"`
    Component           string `json:"component"`
    Total               float64 `json:"total"`
}

// 费用表
type EstimateCost struct {
    gorm.Model
    EstimateProjPhaseID uint   `json:"estimateprojphaseid"`
    ParentID            uint   `json:"parentid"`
    CostName           string  `json:"costname"`
    Unit               string  `json:"unit"`
    Quantity           float64 `json:"quantity"`
    UnitPrice          float64 `json:"unitprice"`
    Total              float64 `json:"total"`
}

4 解析工程费用表格

第一个功能是实现上传表格,解析表格
利用正则表达式判断级别,对于汉字,要用反引号[一-龟]来判断一二三四五……十一十二十三……,不要用双引号和[\u4e00-\u9fa5]来判断中文。因为双引号不支持\( \)这种括号,而反引号不支持\u4e00,真是奇葩,所以选择反引号和一-龟
^[一-龟]{1,2}$^指起始位置,$指末尾位置

if strings.Contains(sheetname, "建筑") ||
    strings.Contains(sheetname, "施工") ||
    strings.Contains(sheetname, "临时") ||
    strings.Contains(sheetname, "机电") ||
    strings.Contains(sheetname, "金结") ||
    strings.Contains(sheetname, "金属") {

    var partOne bool
    // logs.Info(partOne) // false
    number := row[0]
    costname := row[1]
    costname4 := SubString(costname, 0, 4)
    // logs.Info(costname4)
    //设定一个含有中文的字符串
    rex := regexp.MustCompile("^第.部分$")
    if rex.MatchString(string(number)) || rex.MatchString(string(costname4)) {
        partOne = true
    }
    if partOne && row[2] == "" && row[3] == "" {
    // 一级
    // number := row[0]
    // costname := row[1]
        total := row[5]
        totalfloat, err := strconv.ParseFloat(total, 64)
        if err != nil {
            logs.Error(err)
        }
        // professionalID, err = models.AddEstimateProfessional(estimatePhaseID, professional_component, totalfloat)
        costID, err := models.AddEstimateCost(estimatePhaseID, 0, number, costname, "", 0, 0, totalfloat)
        if err != nil {
            logs.Error(err)
        }
        parentID = costID
        // break \u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341
    } else if regexp.MustCompile(`^[一-龟]{1,2}$`).MatchString(string(row[0])) && row[2] == "" && row[3] == "" && row[4] == "" {
        // 二级,类似一 二 三
        number := row[0]
        secondary_component := row[1]
        secondaryID, err = models.AddEstimateSecondary(professionalID, number, secondary_component)
        if err != nil {
            logs.Error(err)
        }
    } else if regexp.MustCompile(`^\([一-龟]{1,2}\)$`).MatchString(string(row[0])) && row[2] == "" && row[3] == "" && row[4] == "" {
        // 三级,类似(一) (二)
        number := row[0]
        tertiary_component := row[1]
        tertiaryID, err = models.AddEstimateTertiary(secondaryID, parentID, number, tertiary_component)
        if err != nil {
            logs.Error(err)
        }
        parentID = tertiaryID
    } else if regexp.MustCompile(`^[1-9]\d*$`).MatchString(string(row[0])) && row[2] == "" && row[3] == "" && row[4] == "" {
        // 四级,类似1 2 3整数数字
        number := row[0]
        tertiary_component := row[1]
    fourthID, err = models.AddEstimateTertiary(tertiaryID, parentID, number, tertiary_component)
        if err != nil {
            logs.Error(err)
        }
        parentID = fourthID
    } else if regexp.MustCompile(`^\([1-9]\d*\)$`).MatchString(string(row[0])) && row[2] == "" && row[3] == "" && row[4] == "" {
        // 五级,类似(1)(2)带括号的整数数字
        number := row[0]
        tertiary_component := row[1]
        fifthID, err = models.AddEstimateTertiary(fourthID, parentID, number, tertiary_component)
        if err != nil {
            logs.Error(err)
        }
        parentID = fifthID
    } else if row[1] != "" && row[2] != "" && row[3] != "" && row[4] != "" && row[5] != "" {
        // cost表,相当于6级
     ......

5 解析通用工程单价表

6 查询

有了数据库,接下来就是查询了

6.1 项目列表

一个项目对应多个阶段

6.2 查询得出总概算表来

采用sqlite原生递归语句进行树状数据查询

// 查询某个部位的投资
func GetEstimateCost(estimateProjPhaseID uint, limit, offset int) (estimateCost []EstimateCost, err error) {
    db := _db
    var q string
    q = `
        with recursive
        tempcost as (
              select * from estimate_cost where estimate_proj_phase_id = ?
              union all
              select estimate_cost.* from tempcost join estimate_cost on tempcost.id = estimate_cost.parent_id
        )
        select * from tempcost;
        `
    err = db.Raw(q, estimateProjPhaseID).Scan(&estimateCost).Error
    return estimateCost, err
}

查出来的数据需要进行处理:父一级下面紧跟对应的子级……,不然原始查出来的数据是所有父一级在前面,所有子一级紧跟其后……如下图展示的这样:

解决方法是先将查询出来的数据根据parentid父子关系转换成树状json数据,返回给前端,前端用layui treetable来展示树状json数据很方便。如下图:

如何使得treetable展示的树状数据直接全部展开呢,要用done:function(){treetable.expandAll()……

参考上面table的说明文件,在treetable的render里加上done:function……

6.2 查询单价

6.2.1 通用单价法

6.2.2 类比法

作者:秦晓川  创建时间:2024-04-06 23:08
最后编辑:秦晓川  更新时间:2024-04-29 00:29