diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..22909d0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +** +!dist/ +!dist/** +!Dockerfile.dist +!docker/ +!docker/dist-server/ +!docker/dist-server/** diff --git a/Dockerfile.dist b/Dockerfile.dist new file mode 100644 index 0000000..4236d28 --- /dev/null +++ b/Dockerfile.dist @@ -0,0 +1,18 @@ +FROM golang:1.24-alpine AS builder + +WORKDIR /src + +COPY docker/dist-server/ ./ + +RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/dist-server . + +FROM scratch + +WORKDIR /www + +COPY --from=builder /out/dist-server /dist-server +COPY dist/ /www/ + +EXPOSE 80 + +ENTRYPOINT ["/dist-server"] diff --git a/docker/dist-server/go.mod b/docker/dist-server/go.mod new file mode 100644 index 0000000..80bc90b --- /dev/null +++ b/docker/dist-server/go.mod @@ -0,0 +1,3 @@ +module dist-server + +go 1.24 diff --git a/docker/dist-server/main.go b/docker/dist-server/main.go new file mode 100644 index 0000000..adf127d --- /dev/null +++ b/docker/dist-server/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "log" + "net/http" + "os" + "path/filepath" + "strings" +) + +const ( + defaultPort = "80" + webRoot = "/www" + indexName = "index.html" +) + +func main() { + port := strings.TrimSpace(os.Getenv("PORT")) + if port == "" { + port = defaultPort + } + + server := &http.Server{ + Addr: ":" + port, + Handler: http.HandlerFunc(serve), + } + + log.Printf("dist server listening on :%s", port) + if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatal(err) + } +} + +func serve(w http.ResponseWriter, r *http.Request) { + requestPath := strings.TrimPrefix(filepath.Clean("/"+r.URL.Path), "/") + if requestPath == "." || requestPath == "" { + serveIndex(w, r) + return + } + + fullPath := filepath.Join(webRoot, filepath.FromSlash(requestPath)) + if info, err := os.Stat(fullPath); err == nil && !info.IsDir() { + applyAssetCacheHeaders(w, requestPath) + http.ServeFile(w, r, fullPath) + return + } + + serveIndex(w, r) +} + +func serveIndex(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + http.ServeFile(w, r, filepath.Join(webRoot, indexName)) +} + +func applyAssetCacheHeaders(w http.ResponseWriter, requestPath string) { + if strings.EqualFold(requestPath, indexName) { + w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + return + } + + if strings.HasPrefix(requestPath, "static/") { + w.Header().Set("Cache-Control", "public, max-age=31536000, immutable") + } +} diff --git a/index.html b/index.html index e76de1c..f13b71e 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,7 @@
- --> diff --git a/public/data.js b/public/data.js deleted file mode 100644 index 0b74662..0000000 --- a/public/data.js +++ /dev/null @@ -1,372 +0,0 @@ -let data1 = { - name: 'test001', - writer: '张三',// 编制人 - reviewer: '李四',// 复核人 - company: '测试公司',// 公司名称 - date: '2021-09-24',// 编制日期 - industry: 0,// 0为公路工程,1为铁路工程,2为水运工程 - fee: 10000, - scaleCost: 100000,// scale的cost的合计数 - overview: '项目概况××××', - desc: '在履行造价咨询服务时,宜根据咨询服务质量情况分级确定相应的处罚金额。其中考评得分在大于及等于85和小于90分时,处罚金额为预算费用的10%;其中考评得分在大于及等于80和小于85分时,处罚金额为预算费用的20%;其中考评得分在大于及等于75和小于80分时,处罚金额为预算费用的30%;其中考评得分在大于及等于70和小于75分时,处罚金额为预算费用的40%;其中考评得分小于70分时,处罚金额为预算费用的50%以上。', - scale: [// 规模信息 - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - serviceCoes: [// 项目咨询分类系数 - { - serviceid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - serviceid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - majorCoes: [// 项目工程专业系数 - { - majorid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - majorid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - contracts: [// 合同段信息 - { - name: 'A合同段', - serviceFee: 100000, - addtionalFee: 0, - reserveFee: 0, - fee: 10000, - quality: '造价咨询服务的综合评价应达到“较好”或综合评分90分', - duration: '自xxxx年xx月开始至xxxx年xx月结束,服务周期xx个月。', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - serviceCoes: [// 合同段咨询分类系数 - { - serviceid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - serviceid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - majorCoes: [// 合同段工程专业系数 - { - majorid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - majorid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - services: [ - { - id: 0, - fee: 250000,//小计 - finalFee: 250000,//确认金额 - process: 0,// 工作环节,0为编制,1为审核 - method1: { // 投资规模法 - cost: 100000, - basicFee: 200, - basicFee_basic: 200, - basicFee_optional: 0, - fee: 250000, //小计 - proAmount: 3, - det: [ - { - proNum: 1, - major: 0, - cost: 100000, - basicFee: 200, - basicFormula: '856,000+(1,000,000,000-500,000,000)×1‰', - basicFee_basic: 200, - optionalFormula: '171,200+(1,000,000,000-500,000,000)×0.2‰', - basicFee_optional: 0, - serviceCoe: 1.1, - majorCoe: 1.2, - processCoe: 1,// 工作环节系数(编审系数) - proportion: 0.5,// 工作占比 - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method2: { // 用地规模法 - area: 1200, - basicFee: 200, - basicFee_basic: 200, - basicFee_optional: 0, - fee: 250000, - proAmount: 3, - det: [ - { - proNum: 1, - major: 0, - area: 1200, - basicFee: 200, - basicFormula: '106,000+(1,200-1,000)×60', - basicFee_basic: 200, - optionalFormula: '21,200+(1,200-1,000)×12', - basicFee_optional: 0, - serviceCoe: 1.1, - majorCoe: 1.2, - processCoe: 1,// 工作环节系数(编审系数) - proportion: 0.5,// 工作占比 - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method3: { // 工作量法 - basicFee: 200, - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method4: { // 工时法 - person_num: 10, - work_day: 10, - fee: 250000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - tasks: [{ serviceid: 0, text: ['abc', 'efg'] }, - { serviceid: 2,text: ['abc', 'efg'] } //tasks不分组的时候传单对象[{text: ['abc', 'efg']}],分组的时候传分组的服务id[{ serviceid: 0, text: ['abc', 'efg'] },...] - ],// 工作内容 - }, - ], - addtional: {// 附加工作费 - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'C' }] }, - name: '附加工作', - fee: 10000, - det: [ - { - id: 0, - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'F' }] }, - name: '人员驻场服务及其他附加工作', - fee: 10000, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - tasks:[] - }, - { - id: 1, - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'X' }] }, - name: '咨询服务协调工作', - fee: 10000, - m0: { - coe: 0.03, - fee: 10000, - }, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - tasks:[] - }, - ] - }, - reserve: {// 预备费 - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'Y' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'B' }] }, - name: '预备费', - fee: 10000, - tasks:[], - m0: { - coe: 0.03, - fee: 10000, - }, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - } - }, - }, - ], -}; \ No newline at end of file diff --git a/public/基础参数及报表导出功能.js b/public/基础参数及报表导出功能.js deleted file mode 100644 index 32e56ce..0000000 --- a/public/基础参数及报表导出功能.js +++ /dev/null @@ -1,1918 +0,0 @@ -let majorList = { - 0: { code: 'E1', name: '交通运输工程通用专业', maxCoe: null, minCoe: null, defCoe: null, desc: '', isRoad: true, isRailway: true, isWaterway: true, order: 1, hasCost: false, hasArea: false }, - 1: { code: 'E1-1', name: '征地(用海)补偿', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于交通建设项目征地(用海)补偿的施工图预算、招标工程量清单及清单预算(或最高投标限价)、清理概算(仅限铁路工程)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: true, isWaterway: true, order: 2, hasCost: true, hasArea: true }, - 2: { code: 'E1-2', name: '拆迁补偿', maxCoe: null, minCoe: null, defCoe: 2.5, desc: '适用于交通建设项目拆迁补偿的施工图预算、招标工程量清单及清单预算(或最高投标限价)、清理概算(仅限铁路工程)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: true, isWaterway: true, order: 3, hasCost: true, hasArea: true }, - 3: { code: 'E1-3', name: '迁改工程', maxCoe: null, minCoe: null, defCoe: 2, desc: '适用于交通建设项目迁改工程的施工图预算、招标工程量清单及清单预算(或最高投标限价)、清理概算(仅限铁路工程)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: true, isWaterway: true, order: 4, hasCost: true, hasArea: false }, - 4: { code: 'E1-4', name: '工程建设其他费', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于交通建设项目的工程建设其他费的施工图预算、招标工程量清单及清单预算(或最高投标限价)、清理概算(仅限铁路工程)和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: true, isWaterway: true, order: 5, hasCost: true, hasArea: false }, - 5: { code: 'E1-5', name: '预备费', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, order: 6, hasCost: true, hasArea: false }, - 6: { code: 'E1-6', name: '建设期贷款利息', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, order: 7, hasCost: true, hasArea: false }, - 7: { code: 'E2', name: '公路工程专业', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于公路工程的全过程造价咨询、分阶段造价咨询、投资估算、初步设计概算、竣工决算和调整估算、调整概算(含征地拆迁和工程建设其他费)', isRoad: true, isRailway: false, isWaterway: false, order: 8, hasCost: false, hasArea: false }, - 8: { code: 'E2-1', name: '临时工程', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于临时工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 9, hasCost: true, hasArea: false }, - 9: { code: 'E2-2', name: '路基工程', maxCoe: null, minCoe: null, defCoe: 1.2, desc: '适用于路基工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 10, hasCost: true, hasArea: false }, - 10: { code: 'E2-3', name: '路面工程', maxCoe: null, minCoe: null, defCoe: 0.8, desc: '适用于路面工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 11, hasCost: true, hasArea: false }, - 11: { code: 'E2-4', name: '桥涵工程', maxCoe: null, minCoe: null, defCoe: 0.9, desc: '适用于桥梁涵洞工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 12, hasCost: true, hasArea: false }, - 12: { code: 'E2-5', name: '隧道工程', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于隧道工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 13, hasCost: true, hasArea: false }, - 13: { code: 'E2-6', name: '交叉工程', maxCoe: null, minCoe: null, defCoe: 1.1, desc: '适用于交叉工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 14, hasCost: true, hasArea: false }, - 14: { code: 'E2-7', name: '机电工程', maxCoe: null, minCoe: null, defCoe: 1.2, desc: '适用于机电工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 15, hasCost: true, hasArea: false }, - 15: { code: 'E2-8', name: '交通安全设施工程', maxCoe: null, minCoe: null, defCoe: 1.2, desc: '适用于交通安全设施工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 16, hasCost: true, hasArea: false }, - 16: { code: 'E2-9', name: '绿化及环境保护工程', maxCoe: null, minCoe: null, defCoe: 1.2, desc: '适用于绿化工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 17, hasCost: true, hasArea: false }, - 17: { code: 'E2-10', name: '房建工程', maxCoe: null, minCoe: null, defCoe: 2.5, desc: '适用于房建工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: true, isRailway: false, isWaterway: false, order: 18, hasCost: true, hasArea: false }, - 18: { code: 'E3', name: '铁路工程专业', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于铁路工程的投资估算、初步设计概算、清理概算、竣工决算和调整估算、调整概算(含征地拆迁和工程建设其他费)', isRoad: false, isRailway: true, isWaterway: false, order: 19, hasCost: false, hasArea: false }, - 19: { code: 'E3-1', name: '大型临时设施和过渡工程', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于大型临时设施和过渡工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 20, hasCost: true, hasArea: false }, - 20: { code: 'E3-2', name: '路基工程', maxCoe: null, minCoe: null, defCoe: 1.2, desc: '适用于路基工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 21, hasCost: true, hasArea: false }, - 21: { code: 'E3-3', name: '桥涵工程', maxCoe: null, minCoe: null, defCoe: 0.9, desc: '适用于桥涵工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 22, hasCost: true, hasArea: false }, - 22: { code: 'E3-4', name: '隧道及明洞工程', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于隧道及明洞工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算、竣工决算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 23, hasCost: true, hasArea: false }, - 23: { code: 'E3-5', name: '轨道工程', maxCoe: null, minCoe: null, defCoe: 0.3, desc: '适用于轨道工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 24, hasCost: true, hasArea: false }, - 24: { code: 'E3-6', name: '通信、信号、信息及灾害监测工程', maxCoe: null, minCoe: null, defCoe: 2, desc: '适用于通信、信号、信息及防灾监测工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 25, hasCost: true, hasArea: false }, - 25: { code: 'E3-7', name: '电力及电力牵引供电工程', maxCoe: null, minCoe: null, defCoe: 1.5, desc: '适用于电力及电力牵引供电工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 26, hasCost: true, hasArea: false }, - 26: { code: 'E3-8', name: '房建工程(房屋建筑及附属工程)', maxCoe: null, minCoe: null, defCoe: 2.5, desc: '适用于房屋建筑及附属工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 27, hasCost: true, hasArea: false }, - 27: { code: 'E3-9', name: '装饰装修工程', maxCoe: null, minCoe: null, defCoe: 2.7, desc: '适用于装饰装修工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: true, isWaterway: false, order: 28, hasCost: true, hasArea: false }, - 28: { code: 'E4', name: '水运工程专业', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于水运工程的投资估算、初步设计概算、竣工决算和调整估算、调整概算(含征地拆迁和工程建设其他费)', isRoad: false, isRailway: false, isWaterway: true, order: 29, hasCost: false, hasArea: false }, - 29: { code: 'E4-1', name: '临时工程', maxCoe: null, minCoe: null, defCoe: 1.1, desc: '适用于临时工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算、竣工决算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: false, isWaterway: true, order: 30, hasCost: true, hasArea: false }, - 30: { code: 'E4-2', name: '土建工程', maxCoe: null, minCoe: null, defCoe: 1, desc: '适用于土建工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算、竣工决算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: false, isWaterway: true, order: 31, hasCost: true, hasArea: false }, - 31: { code: 'E4-3', name: '机电与金属结构工程', maxCoe: null, minCoe: null, defCoe: 1.5, desc: '适用于机电与金属结构专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: false, isWaterway: true, order: 32, hasCost: true, hasArea: false }, - 32: { code: 'E4-4', name: '设备工程', maxCoe: null, minCoe: null, defCoe: 1.5, desc: '适用于设备工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: false, isWaterway: true, order: 33, hasCost: true, hasArea: false }, - 33: { code: 'E4-5', name: '附属房建工程(房屋建筑及附属工程)', maxCoe: null, minCoe: null, defCoe: 2.5, desc: '适用于房屋建筑与水运附属工程专业的施工图预算、招标工程量清单及清单预算(或最高投标限价)、合同(工程)结算和造价鉴定、计算工程量、工程变更费用咨询、工程成本测(核)算', isRoad: false, isRailway: false, isWaterway: true, order: 34, hasCost: true, hasArea: false }, -}; - -let serviceList = { - 0: { code: 'D1', name: '全过程造价咨询', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 1, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 1: { code: 'D2', name: '分阶段造价咨询', maxCoe: null, minCoe: null, defCoe: null, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 2, scale: null, onlyCostScale: null, amount: null, workDay: null }, - 2: { code: 'D2-1', name: '前期阶段造价咨询', maxCoe: null, minCoe: null, defCoe: 0.5, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 3, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 3: { code: 'D2-2-1', name: '实施阶段造价咨询(公路、水运)', maxCoe: null, minCoe: null, defCoe: 0.55, desc: '本系数适用于公路和水运工程。', isRoad: true, isRailway: false, isWaterway: true, mutiple: false, order: 4, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 4: { code: 'D2-2-2', name: '实施阶段造价咨询(铁路)', maxCoe: null, minCoe: null, defCoe: 0.6, desc: '本系数适用于铁路工程。', isRoad: false, isRailway: true, isWaterway: false, mutiple: false, order: 5, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 5: { code: 'D3', name: '基本造价咨询', maxCoe: null, minCoe: null, defCoe: null, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 6, scale: null, onlyCostScale: null, amount: null, workDay: null }, - 6: { code: 'D3-1', name: '投资估算', maxCoe: null, minCoe: null, defCoe: 0.1, desc: '委托同一咨询人同时负责D3-1和D3-2时,D3-1和D3-2的合计调整系数为0.25。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 7, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 7: { code: 'D3-2', name: '设计概算', maxCoe: null, minCoe: null, defCoe: 0.2, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 8, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 8: { code: 'D3-3', name: '施工图预算', maxCoe: null, minCoe: null, defCoe: 0.25, desc: '委托同一咨询人同时负责D3-3和D3-4时,D3-3和D3-4的合计调整系数为0.3。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 9, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 9: { code: 'D3-4', name: '招标工程量清单及清单预算(或最高投标限价)', maxCoe: null, minCoe: null, defCoe: 0.15, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 10, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 10: { code: 'D3-5', name: '清理概算(仅限铁路)', maxCoe: null, minCoe: null, defCoe: 0.2, desc: '本系数适用于铁路工程。', isRoad: false, isRailway: true, isWaterway: false, mutiple: false, order: 11, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 11: { code: 'D3-6-1', name: '合同(工程)结算', maxCoe: null, minCoe: null, defCoe: 0.3, desc: '本系数适用于公路和水运工程。', isRoad: true, isRailway: false, isWaterway: true, mutiple: false, order: 12, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 12: { code: 'D3-6-2', name: '合同(工程)结算', maxCoe: null, minCoe: null, defCoe: 0.2, desc: '本系数适用于铁路工程。', isRoad: false, isRailway: true, isWaterway: false, mutiple: false, order: 13, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 13: { code: 'D3-7', name: '竣工决算', maxCoe: null, minCoe: null, defCoe: 0.1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 14, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 14: { code: 'D4', name: '专项造价咨询', maxCoe: null, minCoe: null, defCoe: null, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 15, scale: null, onlyCostScale: null, amount: null, workDay: null }, - 15: { code: 'D4-1', name: '工程造价顾问', maxCoe: null, minCoe: null, defCoe: 1, desc: '本表系数适用于采用工作量计价法基准预算的调整系数。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 16, scale: false, onlyCostScale: null, amount: true, workDay: true }, - 16: { code: 'D4-2', name: '造价政策制(修)订', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 17, scale: false, onlyCostScale: null, amount: true, workDay: true }, - 17: { code: 'D4-3', name: '造价科学与技术研究', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 18, scale: false, onlyCostScale: null, amount: true, workDay: true }, - 18: { code: 'D4-4', name: '定额测定', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 19, scale: false, onlyCostScale: null, amount: true, workDay: true }, - 19: { code: 'D4-5', name: '造价信息咨询', maxCoe: null, minCoe: null, defCoe: 1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 20, scale: false, onlyCostScale: null, amount: true, workDay: true }, - 20: { code: 'D4-6', name: '造价鉴定', maxCoe: null, minCoe: null, defCoe: 0.5, desc: '本表系数适用于采用规模计价法基准预算的调整系数。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 21, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 21: { code: 'D4-7', name: '工程成本测算', maxCoe: null, minCoe: null, defCoe: 0.1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 22, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 22: { code: 'D4-8', name: '工程成本核算', maxCoe: null, minCoe: null, defCoe: 0.1, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 23, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 23: { code: 'D4-9', name: '计算工程量', maxCoe: null, minCoe: null, defCoe: 0.2, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 24, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 24: { code: 'D4-10', name: '工程变更费用咨询', maxCoe: null, minCoe: null, defCoe: 0.5, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 25, scale: true, onlyCostScale: false, amount: false, workDay: true }, - 25: { code: 'D4-11', name: '调整估算', maxCoe: 0.2, minCoe: 0.1, defCoe: 0.15, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 26, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 26: { code: 'D4-12', name: '调整概算', maxCoe: 0.3, minCoe: 0.15, defCoe: 0.225, desc: '本表系数适用于采用规模计价法基准预算的系数;依据其调整时期所在建设阶段和基础资料的不同,其系数取值不同。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 27, scale: true, onlyCostScale: true, amount: false, workDay: true }, - 27: { code: 'D4-13', name: '造价检查', maxCoe: null, minCoe: null, defCoe: null, desc: '可按照服务工日数量×服务工日人工单价×综合预算系数;也可按照服务工日数量×服务工日综合预算单价。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 28, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 28: { code: 'D4-14', name: '其他专项咨询', maxCoe: null, minCoe: null, defCoe: null, desc: '可参照相同或相似服务的系数。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 29, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 29: { code: 'D4-15-1', name: '造价数据测试验证(估算)', maxCoe: null, minCoe: null, defCoe: 0.04, desc: '委托同一咨询人同时负责D3-1和D3-2时,D3-1和D3-2的合计调整系数为0.25。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 30, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 30: { code: 'D4-15-2', name: '造价数据测试验证(概算)', maxCoe: null, minCoe: null, defCoe: 0.08, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 31, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 31: { code: 'D4-15-3', name: '造价数据测试验证(施工图预算)', maxCoe: null, minCoe: null, defCoe: 0.1, desc: '委托同一咨询人同时负责D3-3和D3-4时,D3-3和D3-4的合计调整系数为0.3。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 32, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 32: { code: 'D4-15-4', name: '造价数据测试验证(招标工程量清单及清单预算(或最高投标限价))', maxCoe: null, minCoe: null, defCoe: 0.06, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 33, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 33: { code: 'D4-15-5', name: '造价数据测试验证(清理概算(仅限铁路))', maxCoe: null, minCoe: null, defCoe: 0.08, desc: '本系数适用于铁路工程。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 34, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 34: { code: 'D4-15-6', name: '造价数据测试验证(合同(工程)结算)', maxCoe: null, minCoe: null, defCoe: 0.12, desc: '本系数适用于公路和水运工程。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 35, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 35: { code: 'D4-15-7', name: '造价数据测试验证(合同(工程)结算)', maxCoe: null, minCoe: null, defCoe: 0.08, desc: '本系数适用于铁路工程。', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 36, scale: false, onlyCostScale: null, amount: false, workDay: true }, - 36: { code: 'D4-15-8', name: '造价数据测试验证(竣工决算)', maxCoe: null, minCoe: null, defCoe: 0.04, desc: '', isRoad: true, isRailway: true, isWaterway: true, mutiple: false, order: 37, scale: false, onlyCostScale: null, amount: false, workDay: true }, -}; - -let taskList = { - 0: { serviceID: 15, code: 'C4-1', name: '工程造价日常顾问', basicParam: '服务月份数', required: true, unit: '万元/月', conversion: 10000, maxPrice: 0.5, minPrice: 0.3, defPrice: 0.4, desc: '' }, - 1: { serviceID: 15, code: 'C4-2', name: '工程造价专项顾问', basicParam: '服务项目的造价金额', required: true, unit: '%', conversion: 0.01, maxPrice: null, minPrice: null, defPrice: 0.01, desc: '适用于涉及造价费用类的顾问' }, - 2: { serviceID: 16, code: 'C5-1', name: '组织与调研工作', basicParam: '调研次数', required: true, unit: '万元/次', conversion: 10000, maxPrice: 2, minPrice: 1, defPrice: 1.5, desc: '' }, - 3: { serviceID: 16, code: 'C5-2-1', name: '文件编写工作', basicParam: '文件份数', required: true, unit: '万元/份', conversion: 10000, maxPrice: 5, minPrice: 3, defPrice: 4, desc: '主编' }, - 4: { serviceID: 16, code: 'C5-2-2', name: '文件编写工作', basicParam: '文件份数', required: true, unit: '万元/份', conversion: 10000, maxPrice: 3, minPrice: 1, defPrice: 2, desc: '参编' }, - 5: { serviceID: 16, code: 'C5-3-1', name: '评审工作', basicParam: '评审次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 20, minPrice: 8, defPrice: 14, desc: '大型评审' }, - 6: { serviceID: 16, code: 'C5-3-2', name: '评审工作', basicParam: '评审次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 10, minPrice: 5, defPrice: 7.5, desc: '中型评审' }, - 7: { serviceID: 16, code: 'C5-3-3', name: '评审工作', basicParam: '评审次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 6, minPrice: 3, defPrice: 4.5, desc: '小型评审' }, - 8: { serviceID: 17, code: 'C6-1', name: '组织与调研工作', basicParam: '调研次数', required: true, unit: '万元/次', conversion: 10000, maxPrice: 2, minPrice: 1, defPrice: 1.5, desc: '' }, - 9: { serviceID: 17, code: 'C6-2-1', name: '研究及编写报告', basicParam: '文件份数', required: true, unit: '万元/份', conversion: 10000, maxPrice: 50, minPrice: 20, defPrice: 35, desc: '国家级' }, - 10: { serviceID: 17, code: 'C6-2-2', name: '研究及编写报告', basicParam: '文件份数', required: true, unit: '万元/份', conversion: 10000, maxPrice: 20, minPrice: 10, defPrice: 15, desc: '省部级' }, - 11: { serviceID: 17, code: 'C6-2-3', name: '研究及编写报告', basicParam: '文件份数', required: true, unit: '万元/份', conversion: 10000, maxPrice: 10, minPrice: 5, defPrice: 7.5, desc: '其他级' }, - 12: { serviceID: 17, code: 'C6-3-1', name: '标准与技术性指导文件的编制', basicParam: '文件与标准的数量', required: true, unit: '万元/份', conversion: 10000, maxPrice: 80, minPrice: 50, defPrice: 65, desc: '复杂标准' }, - 13: { serviceID: 17, code: 'C6-3-2', name: '标准与技术性指导文件的编制', basicParam: '文件与标准的数量', required: true, unit: '万元/份', conversion: 10000, maxPrice: 50, minPrice: 20, defPrice: 35, desc: '较复杂标准' }, - 14: { serviceID: 17, code: 'C6-3-3', name: '标准与技术性指导文件的编制', basicParam: '文件与标准的数量', required: true, unit: '万元/份', conversion: 10000, maxPrice: 20, minPrice: 10, defPrice: 15, desc: '一般标准' }, - 15: { serviceID: 17, code: 'C6-3-4', name: '标准与技术性指导文件的编制', basicParam: '文件与标准的数量', required: true, unit: '万元/份', conversion: 10000, maxPrice: 10, minPrice: 5, defPrice: 7.5, desc: '简单标准' }, - 16: { serviceID: 17, code: 'C6-4-1', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 20, minPrice: 8, defPrice: 14, desc: '大型评审' }, - 17: { serviceID: 17, code: 'C6-4-2', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 10, minPrice: 5, defPrice: 7.5, desc: '中型评审' }, - 18: { serviceID: 17, code: 'C6-4-3', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 6, minPrice: 3, defPrice: 4.5, desc: '小型评审' }, - 19: { serviceID: 17, code: 'C6-5-1', name: '培训与宣贯工作', basicParam: '项目数量', required: false, unit: '万元/次', conversion: 10000, maxPrice: 3, minPrice: 1, defPrice: 2, desc: '培训与宣贯材料' }, - 20: { serviceID: 17, code: 'C6-5-2', name: '培训与宣贯工作', basicParam: '培训与宣贯次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 1, minPrice: 0.5, defPrice: 0.75, desc: '组织培训与宣贯' }, - 21: { serviceID: 18, code: 'C7-1', name: '组织与调研工作', basicParam: '调研次数', required: true, unit: '万元/次', conversion: 10000, maxPrice: 2, minPrice: 1, defPrice: 1.5, desc: '' }, - 22: { serviceID: 18, code: 'C7-2', name: '编制大纲', basicParam: '项目数量', required: true, unit: '万元/个', conversion: 10000, maxPrice: 3, minPrice: 2, defPrice: 2.5, desc: '包括技术与定额子目研究' }, - 23: { serviceID: 18, code: 'C7-3', name: '数据采集与测定', basicParam: '采集组数', required: true, unit: '万元/组', conversion: 10000, maxPrice: 0.8, minPrice: 0.2, defPrice: 0.5, desc: '现场采集方式时计' }, - 24: { serviceID: 18, code: 'C7-4-1', name: '数据整理与分析', basicParam: '定额子目条数', required: true, unit: '万元/条', conversion: 10000, maxPrice: 0.3, minPrice: 0.1, defPrice: 0.2, desc: '简单定额' }, - 25: { serviceID: 18, code: 'C7-4-2', name: '数据整理与分析', basicParam: '定额子目条数', required: true, unit: '万元/条', conversion: 10000, maxPrice: 3, minPrice: 0.3, defPrice: 1.65, desc: '复杂定额' }, - 26: { serviceID: 18, code: 'C7-5', name: '编写定额测定报告', basicParam: '项目数量', required: true, unit: '万元/份', conversion: 10000, maxPrice: 5, minPrice: 2, defPrice: 3.5, desc: '' }, - 27: { serviceID: 18, code: 'C7-6-1', name: '编制定额文本和释义', basicParam: '基本费用', required: true, unit: '万元/份', conversion: 10000, maxPrice: 1, minPrice: 0.5, defPrice: 0.75, desc: '20条定额子目内' }, - 28: { serviceID: 18, code: 'C7-6-2', name: '编制定额文本和释义', basicParam: '定额子目条数', required: true, unit: '万元/条', conversion: 10000, maxPrice: 0.2, minPrice: 0.1, defPrice: 0.15, desc: '超过20条每增加1条' }, - 29: { serviceID: 18, code: 'C7-7-1', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 20, minPrice: 8, defPrice: 14, desc: '大型评审' }, - 30: { serviceID: 18, code: 'C7-7-2', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 10, minPrice: 5, defPrice: 7.5, desc: '中型评审' }, - 31: { serviceID: 18, code: 'C7-7-3', name: '评审与验收工作', basicParam: '评审与验收次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 6, minPrice: 3, defPrice: 4.5, desc: '小型评审' }, - 32: { serviceID: 18, code: 'C7-8-1', name: '培训与宣贯工作', basicParam: '项目数量', required: false, unit: '万元/次', conversion: 10000, maxPrice: 3, minPrice: 1, defPrice: 2, desc: '培训与宣贯材料' }, - 33: { serviceID: 18, code: 'C7-8-2', name: '培训与宣贯工作', basicParam: '培训与宣贯次数', required: false, unit: '万元/次', conversion: 10000, maxPrice: 1, minPrice: 0.5, defPrice: 0.75, desc: '组织培训与宣贯' }, - 34: { serviceID: 19, code: 'C8-1', name: 'Q≤10条', basicParam: '价格信息数量', required: true, unit: '元/条', conversion: 1, maxPrice: null, minPrice: null, defPrice: 500, desc: '' }, - 35: { serviceID: 19, code: 'C8-2', name: '10条100条', basicParam: '价格信息数量', required: true, unit: '元/条', conversion: 1, maxPrice: null, minPrice: null, defPrice: 100, desc: '' }, -}; - -let expertList = { - 0: { code: 'C9-1-1', name: '技术员及其他', maxPrice: 800, minPrice: 600, defPrice: 700, manageCoe: 2.3 }, - 1: { code: 'C9-1-2', name: '助理工程师', maxPrice: 1000, minPrice: 800, defPrice: 900, manageCoe: 2.3 }, - 2: { code: 'C9-1-3', name: '中级工程师或二级造价工程师', maxPrice: 1500, minPrice: 1000, defPrice: 1250, manageCoe: 2.2 }, - 3: { code: 'C9-1-4', name: '高级工程师或一级造价工程师', maxPrice: 1800, minPrice: 1500, defPrice: 1650, manageCoe: 2.1 }, - 4: { code: 'C9-1-5', name: '正高级工程师或资深专家', maxPrice: 2500, minPrice: 2000, defPrice: 2250, manageCoe: 2 }, - 5: { code: 'C9-2-1', name: '二级造价工程师且具备中级工程师资格', maxPrice: 1500, minPrice: 1200, defPrice: 1350, manageCoe: 2.2 }, - 6: { code: 'C9-3-1', name: '一级造价工程师且具备中级工程师资格', maxPrice: 1800, minPrice: 1500, defPrice: 1650, manageCoe: 2.1 }, - 7: { code: 'C9-3-2', name: '一级造价工程师且具备高级工程师资格', maxPrice: 2000, minPrice: 1800, defPrice: 1900, manageCoe: 2.05 }, -}; - -let costScaleCal = [ - { code: 'C1-1', staLine: 0, endLine: 100, basic: { staPrice: 0, rate: 0.01 }, optional: { staPrice: 0, rate: 0.002 } }, - { code: 'C1-2', staLine: 100, endLine: 300, basic: { staPrice: 10000, rate: 0.008 }, optional: { staPrice: 2000, rate: 0.0016 } }, - { code: 'C1-3', staLine: 300, endLine: 500, basic: { staPrice: 26000, rate: 0.005 }, optional: { staPrice: 5200, rate: 0.001 } }, - { code: 'C1-4', staLine: 500, endLine: 1000, basic: { staPrice: 36000, rate: 0.004 }, optional: { staPrice: 7200, rate: 0.0008 } }, - { code: 'C1-5', staLine: 1000, endLine: 5000, basic: { staPrice: 56000, rate: 0.003 }, optional: { staPrice: 11200, rate: 0.0006 } }, - { code: 'C1-6', staLine: 5000, endLine: 10000, basic: { staPrice: 176000, rate: 0.002 }, optional: { staPrice: 35200, rate: 0.0004 } }, - { code: 'C1-7', staLine: 10000, endLine: 30000, basic: { staPrice: 276000, rate: 0.0016 }, optional: { staPrice: 55200, rate: 0.00032 } }, - { code: 'C1-8', staLine: 30000, endLine: 50000, basic: { staPrice: 596000, rate: 0.0013 }, optional: { staPrice: 119200, rate: 0.00026 } }, - { code: 'C1-9', staLine: 50000, endLine: 100000, basic: { staPrice: 856000, rate: 0.001 }, optional: { staPrice: 171200, rate: 0.0002 } }, - { code: 'C1-10', staLine: 100000, endLine: 150000, basic: { staPrice: 1356000, rate: 0.0009 }, optional: { staPrice: 271200, rate: 0.00018 } }, - { code: 'C1-11', staLine: 150000, endLine: 200000, basic: { staPrice: 1806000, rate: 0.0008 }, optional: { staPrice: 361200, rate: 0.00016 } }, - { code: 'C1-12', staLine: 200000, endLine: 300000, basic: { staPrice: 2206000, rate: 0.0007 }, optional: { staPrice: 441200, rate: 0.00014 } }, - { code: 'C1-13', staLine: 300000, endLine: 400000, basic: { staPrice: 2906000, rate: 0.0006 }, optional: { staPrice: 581200, rate: 0.00012 } }, - { code: 'C1-14', staLine: 400000, endLine: 600000, basic: { staPrice: 3506000, rate: 0.0005 }, optional: { staPrice: 701200, rate: 0.0001 } }, - { code: 'C1-15', staLine: 600000, endLine: 800000, basic: { staPrice: 4506000, rate: 0.0004 }, optional: { staPrice: 901200, rate: 0.00008 } }, - { code: 'C1-16', staLine: 800000, endLine: 1000000, basic: { staPrice: 5306000, rate: 0.0003 }, optional: { staPrice: 1061200, rate: 0.00006 } }, - { code: 'C1-17', staLine: 1000000, endLine: null, basic: { staPrice: 5906000, rate: 0.00025 }, optional: { staPrice: 1181200, rate: 0.00005 } }, -]; - -let areaScaleCal = [ - { code: 'C2-1', staLine: 0, endLine: 50, basic: { staPrice: 0, rate: 200 }, optional: { staPrice: 0, rate: 40 } }, - { code: 'C2-2', staLine: 50, endLine: 100, basic: { staPrice: 10000, rate: 160 }, optional: { staPrice: 2000, rate: 32 } }, - { code: 'C2-3', staLine: 100, endLine: 500, basic: { staPrice: 18000, rate: 120 }, optional: { staPrice: 3600, rate: 24 } }, - { code: 'C2-4', staLine: 500, endLine: 1000, basic: { staPrice: 66000, rate: 80 }, optional: { staPrice: 13200, rate: 16 } }, - { code: 'C2-5', staLine: 1000, endLine: 5000, basic: { staPrice: 106000, rate: 60 }, optional: { staPrice: 21200, rate: 12 } }, - { ref: 'C2-6', staLine: 5000, endLine: null, basic: { staPrice: 346000, rate: 20 }, optional: { staPrice: 69200, rate: 4 } }, -]; - -function getBasicFeeFromScale(scaleValue, scaleType) { - let sv = Number(scaleValue); - if (isNaN(sv)) return null; - if (sv <= 0) return null; - let targetRange; - let res; - switch (scaleType) { - case 'cost': - targetRange = costScaleCal.find(f => f.staLine < sv && (sv <= f.endLine || f.endLine === null)); - res = { - basic: Math.round((targetRange.basic.staPrice + (sv - targetRange.staLine) * 10000 * targetRange.basic.rate) * 100) / 100, - optional: Math.round((targetRange.optional.staPrice + (sv - targetRange.staLine) * 10000 * targetRange.optional.rate) * 100) / 100, - basicFormula: targetRange.basic.staPrice ? `${numberFormatter(targetRange.basic.staPrice, 0)}+(${numberFormatter(sv * 10000, 0)}-${numberFormatter(targetRange.staLine * 10000, 0)})×${Math.round(targetRange.basic.rate * 1000 * 100) / 100}‰` : `${numberFormatter(sv * 10000, 0)}×${Math.round(targetRange.basic.rate * 1000 * 100) / 100}‰`, - optionalFormula: targetRange.optional.staPrice ? `${numberFormatter(targetRange.optional.staPrice, 0)}+(${numberFormatter(sv * 10000, 0)}-${numberFormatter(targetRange.staLine * 10000, 0)})×${Math.round(targetRange.optional.rate * 1000 * 100) / 100}‰` : `${numberFormatter(sv * 10000, 0)}×${Math.round(targetRange.optional.rate * 1000 * 100) / 100}‰`, - }; - break; - case 'area': - targetRange = areaScaleCal.find(f => f.staLine < sv && (sv <= f.endLine || f.endLine === null)); - res = { - basic: Math.round((targetRange.basic.staPrice + (sv - targetRange.staLine) * targetRange.basic.rate) * 100) / 100, - optional: Math.round((targetRange.optional.staPrice + (sv - targetRange.staLine) * targetRange.optional.rate) * 100) / 100, - basicFormula: targetRange.basic.staPrice ? `${numberFormatter(targetRange.basic.staPrice, 0)}+(${numberFormatter(sv, 0)}-${numberFormatter(targetRange.staLine, 0)})×${targetRange.basic.rate}` : `${numberFormatter(sv, 0)}×${targetRange.basic.rate}`, - optionalFormula: targetRange.optional.staPrice ? `${numberFormatter(targetRange.optional.staPrice, 0)}+(${numberFormatter(sv, 0)}-${numberFormatter(targetRange.staLine, 0)})×${targetRange.optional.rate}` : `${numberFormatter(sv, 0)}×${targetRange.optional.rate}`, - }; - break; - } - return res; -} - - - -let data2 = { - name: 'test001', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - contracts: [ - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - }, - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method3: { // 工作量法 - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - ], - }, - }, - ], - }, - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - }, - ], - }, - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - }, - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method3: { // 工作量法 - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - ], - }, - }, - ], - }, - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - }, - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method3: { // 工作量法 - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - ], - }, - }, - ], - }, - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - }, - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method3: { // 工作量法 - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - ], - }, - }, - ], - }, - { - name: 'A合同段', - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - services: [ - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - }, - { - id: 0, - method1: { // 投资规模法 - fee: 250000, - det: [ - { - major: 0, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - cost: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method2: { // 用地规模法 - fee: 250000, - det: [ - { - major: 0, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - { - major: 1, - area: 100000, - basicFee: 200, - serviceCoe: 1.1, - majorCoe: 1.2, - fee: 100000, - desc: '', - }, - ], - }, - method3: { // 工作量法 - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - desc: '', - }, - ], - }, - }, - ], - }, - ], -}; - -async function exportFile(fileName, data) { - if (window.showSaveFilePicker) { - const handle = await window.showSaveFilePicker({ - suggestedName: fileName, - types: [{ - description: "Excel 文件", - accept: { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [".xlsx"] } - }] - }); - // ecCom.WeaLoadingGlobal.start({ - // tip: "下载中,结束前请勿打开文件...", - // }); - try { - const workbook = await generateTemplate(data); - const buffer = await workbook.xlsx.writeBuffer(); - const writable = await handle.createWritable(); - await writable.write(buffer); - await writable.close(); - // ecCom.WeaLoadingGlobal.destroy(); - // antd.notification['success']({ - // message: '下载成功!', - // }); - } catch (err) { - console.log('err:' + err); - // ecCom.WeaLoadingGlobal.destroy(); - // antd.notification['error']({ - // message: '下载失败!', - // }); - } - } else { - const workbook = await generateTemplate(data); - const buffer = await workbook.xlsx.writeBuffer(); - const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); - const url1 = window.URL.createObjectURL(blob); - const a = document.createElement('a'); - a.href = url1; - a.download = `${fileName}.xlsx`; - a.click(); - URL.revokeObjectURL(url1); - } -} - -async function generateTemplate(data) { - // 获取模板 - let templateExcel = 'template20260226001test010'; - let templateUrl = `/myExcelTemplate/${templateExcel}.xlsx`; - let buf = await (await fetch(templateUrl)).arrayBuffer(); - let workbook = new ExcelJS.Workbook(); - await workbook.xlsx.load(buf); - - // 生成表格 - let fm_sheet = workbook.getWorksheet('封面'); - let ml_sheet = workbook.getWorksheet('目录'); - let yz01_sheet = workbook.getWorksheet('预总01表'); - let f01_sheet = workbook.getWorksheet('辅01表'); - - let now = new Date(); - let year = now.getFullYear(); - let month = now.getMonth() + 1; - let day = now.getDate(); - - fm_sheet.getRow(2).getCell(1).value = data.name; - fm_sheet.getRow(11).getCell(4).value = `${year} 年 ${month} 月 ${day} 日`; - - let yz01Mod = (data.contracts.length + 1) % 4; - let yz01Num = (data.contracts.length + 1 - yz01Mod) / 4; - switch (yz01Mod) { - case 0: - yz01_sheet.spliceColumns(8, 15); - break; - case 1: - yz01_sheet.spliceColumns(8, 11); - break; - case 2: - yz01_sheet.spliceColumns(19, 4); - yz01_sheet.spliceColumns(8, 6); - break; - case 3: - yz01_sheet.spliceColumns(14, 9); - break; - } - if (yz01Num == 0) { - yz01_sheet.spliceColumns(1, 7); - } else { - if (yz01Num > 1) { - for (let i = 0; i < yz01Num - 1; i++) { - insertAndCopyColumn(7 * (i + 1) + 1, [1, 2, 3, 4, 5, 6, 7], yz01_sheet); - } - } - } - - let f01Mod = (data.contracts.length) % 3; - let f01Num = (data.contracts.length - f01Mod) / 3; - switch (f01Mod) { - case 0: - f01_sheet.spliceColumns(11, 14); - break; - case 1: - f01_sheet.spliceColumns(11, 8); - break; - case 2: - f01_sheet.spliceColumns(19, 6); - break; - } - if (f01Num == 0) { - f01_sheet.spliceColumns(1, 10); - } else { - if (f01Num > 1) { - for (let i = 0; i < f01Num - 1; i++) { - insertAndCopyColumn(10 * (i + 1) + 1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], f01_sheet); - } - } - for (let i = 0; i < f01Num; i++) { - f01_sheet.mergeCells(1, i * 10 + 1, 2, i * 10 + 1); - f01_sheet.mergeCells(1, i * 10 + 2, 2, i * 10 + 2); - f01_sheet.mergeCells(1, i * 10 + 3, 2, i * 10 + 3); - f01_sheet.mergeCells(1, i * 10 + 10, 2, i * 10 + 10); - f01_sheet.mergeCells(1, i * 10 + 4, 1, i * 10 + 5); - f01_sheet.getRow(1).getCell(i * 10 + 4).value = data.contracts[i * 3].name; - f01_sheet.mergeCells(1, i * 10 + 6, 1, i * 10 + 7); - f01_sheet.getRow(1).getCell(i * 10 + 6).value = data.contracts[i * 3 + 1].name; - f01_sheet.mergeCells(1, i * 10 + 8, 1, i * 10 + 9); - f01_sheet.getRow(1).getCell(i * 10 + 8).value = data.contracts[i * 3 + 2].name; - } - } - if (f01Mod > 0) { - f01_sheet.mergeCells(1, f01Num * 10 + 1, 2, f01Num * 10 + 1); - f01_sheet.mergeCells(1, f01Num * 10 + 2, 2, f01Num * 10 + 2); - f01_sheet.mergeCells(1, f01Num * 10 + 3, 2, f01Num * 10 + 3); - f01_sheet.mergeCells(1, f01Num * 10 + 2 * f01Mod + 4, 2, f01Num * 10 + 2 * f01Mod + 4); - f01_sheet.mergeCells(1, f01Num * 10 + 4, 1, f01Num * 10 + 5); - f01_sheet.getRow(1).getCell(f01Num * 10 + 4).value = data.contracts[f01Num * 3].name; - if (f01Mod == 2) { - f01_sheet.mergeCells(1, f01Num * 10 + 6, 1, f01Num * 10 + 7); - f01_sheet.getRow(1).getCell(f01Num * 10 + 6).value = data.contracts[f01Num * 3 + 1].name; - } - } - - let ml_slotRow = 13; - let ml_number = 1; - let allServices = []; - data.contracts.forEach((ci, index) => { - ci.method1 = []; - ci.method2 = []; - ci.method3 = []; - ci.method4 = []; - ci.services.forEach(si => { - if (si.method1) { - ci.method1.push(si.id); - } - if (si.method2) { - ci.method2.push(si.id); - } - if (si.method3) ci.method3.push(si.id); - if (si.method4) ci.method4.push(si.id); - }); - - let ml_sourceRows = [ml_sheet.getRow(6)]; - let sheet_1 = copyWorksheet(workbook, '预i-1表', `预${index + 1}-1表`); - sheet_1.headerFooter.oddHeader = sheet_1.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-1 表/g, `预 ${index + 1}-1 表`).replace(/第i合同/g, ci.name); - sheet_1.getRow(1).getCell(4).value = sheet_1.getRow(1).getCell(4).value.replace(/第i合同/g, ci.name); - let sheet_2; - let sheet_2_1; - let sheet_2_2; - let sheet_3; - let sheet_4; - let sheet_4_1; - if (ci.method1.length || ci.method2.length) { - ml_sourceRows.push(ml_sheet.getRow(7)); - sheet_2 = copyWorksheet(workbook, '预i-2表', `预${index + 1}-2表`); - sheet_2.headerFooter.oddHeader = sheet_2.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-2 表/g, `预 ${index + 1}-2 表`).replace(/第i合同/g, ci.name); - if (ci.method1.length) { - ml_sourceRows.push(ml_sheet.getRow(8)); - sheet_2_1 = copyWorksheet(workbook, '预i-2-1表', `预${index + 1}-2-1表`); - sheet_2_1.headerFooter.oddHeader = sheet_2_1.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-2-1 表/g, `预 ${index + 1}-2-1 表`).replace(/第i合同/g, ci.name); - } - if (ci.method2.length) { - ml_sourceRows.push(ml_sheet.getRow(9)); - sheet_2_2 = copyWorksheet(workbook, '预i-2-2表', `预${index + 1}-2-2表`); - sheet_2_2.headerFooter.oddHeader = sheet_2_2.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-2-2 表/g, `预 ${index + 1}-2-2 表`).replace(/第i合同/g, ci.name); - } - } - if (ci.method3.length) { - ml_sourceRows.push(ml_sheet.getRow(10)); - sheet_3 = copyWorksheet(workbook, '预i-3表', `预${index + 1}-3表`); - sheet_3.headerFooter.oddHeader = sheet_3.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-3 表/g, `预 ${index + 1}-3 表`).replace(/第i合同/g, ci.name); - } - if (ci.method4.length) { - ml_sourceRows.push(ml_sheet.getRow(11)); - ml_sourceRows.push(ml_sheet.getRow(12)); - sheet_4 = copyWorksheet(workbook, '预i-4表', `预${index + 1}-4表`); - sheet_4.headerFooter.oddHeader = sheet_4.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-4 表/g, `预 ${index + 1}-4 表`).replace(/第i合同/g, ci.name); - sheet_4_1 = copyWorksheet(workbook, '预i-4-1表', `预${index + 1}-4-1表`); - sheet_4_1.headerFooter.oddHeader = sheet_4_1.headerFooter.oddHeader.replace(/×××/g, ci.name).replace(/预 i-4-1 表/g, `预 ${index + 1}-4-1 表`).replace(/第i合同/g, ci.name); - let sumObj = ci.method4.reduce((a, b) => { - const m4 = ci.services.find(f => f.id == b).method4; - return { person_num: a.person_num + m4.person_num, work_day: a.work_day + m4.work_day, fee: a.fee + m4.fee }; - }, { person_num: 0, work_day: 0, fee: 0 }); - sheet_4.getRow(3).getCell(4).value = sumObj.person_num; - sheet_4.getRow(3).getCell(5).value = sumObj.work_day; - sheet_4.getRow(3).getCell(6).value = sumObj.fee; - sheet_4_1.getRow(4).getCell(4).value = '/'; - sheet_4_1.getRow(4).getCell(5).value = '/'; - sheet_4_1.getRow(4).getCell(6).value = '/'; - sheet_4_1.getRow(4).getCell(7).value = sumObj.person_num; - sheet_4_1.getRow(4).getCell(8).value = sumObj.work_day; - sheet_4_1.getRow(4).getCell(9).value = sumObj.fee - } - - cusInsertRowFunc(ml_slotRow, ml_sourceRows, ml_sheet, () => ml_slotRow++, (targetCell, sourceCell, colNumber) => { - if (colNumber == 1) { - targetCell.value = ml_number++; - } else if (colNumber == 2) { - targetCell.value = sourceCell.value.replaceAll('第i合同', ci.name); - } else if (colNumber == 3) { - targetCell.value = sourceCell.value.replaceAll('i', index + 1); - } else { - targetCell.value = sourceCell.value; - } - }); - - let num_2 = 1; - let num_2_1 = 1; - let num_2_2 = 1; - let num_3 = 1; - let num_4 = 1; - let num_4_1 = 1; - ci.services.forEach((sobj, sindex) => { - let allServicesX = allServices.find(s => s.id == sobj.id); - if (allServicesX) { - allServicesX.contracts[index] = sobj.fee; - } else { - allServices.push({ - id: sobj.id, - contracts: { - [index]: sobj.fee, - }, - }); - } - let serviceX = serviceList[sobj.id]; - cusInsertRowFunc(4 + sindex, [sheet_1.getRow(3)], sheet_1, (targetRow) => { - targetRow.getCell(1).value = sindex + 1; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = sobj.method1 ? sobj.method1.fee : ''; - targetRow.getCell(5).value = sobj.method2 ? sobj.method2.fee : ''; - targetRow.getCell(6).value = sobj.method3 ? sobj.method3.fee : ''; - targetRow.getCell(7).value = sobj.method4 ? sobj.method4.fee : ''; - targetRow.getCell(8).value = sobj.fee; - }); - if (sobj.method1 || sobj.method2) { - let det1 = sobj.method1 ? sobj.method1.det.map(m => m.major) : []; - let det2 = sobj.method2 ? sobj.method2.det.map(m => m.major) : []; - let allDet = [...(new Set([...det1, ...det2]))].sort((a, b) => a - b).map(m => { - return { - major: m, - mth1: det1.includes(m) ? sobj.method1.det[det1.indexOf(m)] : null, - mth2: det2.includes(m) ? sobj.method2.det[det2.indexOf(m)] : null, - }; - }); - - cusInsertRowFunc(4 + num_2, [sheet_2.getRow(4)], sheet_2, (targetRow) => { - targetRow.getCell(1).value = num_2++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = '/'; - targetRow.getCell(5).value = '/'; - if (sobj.method1) { - targetRow.getCell(6).value = sobj.method1.basicFee; - targetRow.getCell(7).value = sobj.method1.fee; - cusInsertRowFunc(4 + num_2_1, [sheet_2_1.getRow(4)], sheet_2_1, (targetRow) => { - targetRow.getCell(1).value = num_2_1++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = sobj.method1.cost; - targetRow.getCell(5).value = '/'; - targetRow.getCell(6).value = sobj.method1.basicFee_basic; - targetRow.getCell(7).value = '/'; - targetRow.getCell(8).value = sobj.method1.basicFee_optional; - targetRow.getCell(9).value = sobj.method1.basicFee; - }); - } - if (sobj.method2) { - targetRow.getCell(8).value = sobj.method2.basicFee; - targetRow.getCell(9).value = sobj.method2.fee; - cusInsertRowFunc(4 + num_2_2, [sheet_2_2.getRow(4)], sheet_2_2, (targetRow) => { - targetRow.getCell(1).value = num_2_2++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = sobj.method2.area; - targetRow.getCell(5).value = '/'; - targetRow.getCell(6).value = sobj.method2.basicFee_basic; - targetRow.getCell(7).value = '/'; - targetRow.getCell(8).value = sobj.method2.basicFee_optional; - targetRow.getCell(9).value = sobj.method2.basicFee; - }); - } - }); - allDet.forEach((m, mindex) => { - let majorX = majorList[m.major]; - cusInsertRowFunc(4 + num_2, [sheet_2.getRow(4)], sheet_2, (targetRow) => { - targetRow.getCell(1).value = num_2++; - targetRow.getCell(2).value = serviceX.ref + '-' + (mindex + 1); - targetRow.getCell(3).value = majorX.name; - if (m.mth1) { - targetRow.getCell(4).value = m.mth1.serviceCoe; - targetRow.getCell(5).value = m.mth1.majorCoe; - targetRow.getCell(6).value = m.mth1.basicFee; - targetRow.getCell(7).value = m.mth1.fee; - targetRow.getCell(8).value = 0; - targetRow.getCell(9).value = 0; - cusInsertRowFunc(4 + num_2_1, [sheet_2_1.getRow(4)], sheet_2_1, (targetRow) => { - targetRow.getCell(1).value = num_2_1++; - targetRow.getCell(2).value = serviceX.ref + '-' + (mindex + 1); - targetRow.getCell(3).value = majorX.name; - targetRow.getCell(4).value = m.mth1.cost; - targetRow.getCell(5).value = m.mth1.basicFormula; - targetRow.getCell(6).value = m.mth1.basicFee_basic; - targetRow.getCell(7).value = m.mth1.optionalFormula; - targetRow.getCell(8).value = m.mth1.basicFee_optional; - targetRow.getCell(9).value = m.mth1.basicFee; - }); - } else { - targetRow.getCell(4).value = m.mth2.serviceCoe; - targetRow.getCell(5).value = m.mth2.majorCoe; - targetRow.getCell(6).value = 0; - targetRow.getCell(7).value = 0; - targetRow.getCell(8).value = m.mth2.basicFee; - targetRow.getCell(9).value = m.mth2.fee; - cusInsertRowFunc(4 + num_2_2, [sheet_2_2.getRow(4)], sheet_2_2, (targetRow) => { - targetRow.getCell(1).value = num_2_2++; - targetRow.getCell(2).value = serviceX.ref + '-' + (mindex + 1); - targetRow.getCell(3).value = majorX.name; - targetRow.getCell(4).value = m.mth2.area; - targetRow.getCell(5).value = m.mth2.basicFormula; - targetRow.getCell(6).value = m.mth2.basicFee_basic; - targetRow.getCell(7).value = m.mth2.optionalFormula; - targetRow.getCell(8).value = m.mth2.basicFee_optional; - targetRow.getCell(9).value = m.mth2.basicFee; - }); - } - }); - }); - } - if (sobj.method3) { - cusInsertRowFunc(3 + num_3, [sheet_3.getRow(3)], sheet_3, (targetRow) => { - targetRow.getCell(1).value = num_3++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = '/'; - targetRow.getCell(5).value = '/'; - targetRow.getCell(6).value = '/'; - targetRow.getCell(7).value = sobj.method3.basicFee; - targetRow.getCell(8).value = '/'; - targetRow.getCell(9).value = sobj.method3.fee; - }); - sobj.method3.det.forEach((tobj, tindex) => { - const taskX = taskList[tobj.task]; - cusInsertRowFunc(3 + num_3, [sheet_3.getRow(3)], sheet_3, (targetRow) => { - targetRow.getCell(1).value = num_3++; - targetRow.getCell(2).value = taskX.ref; - targetRow.getCell(3).value = taskX.name + (taskX.desc ? `(${taskX.desc})` : ''); - targetRow.getCell(4).value = taskX.basicParam; - targetRow.getCell(5).value = tobj.price; - targetRow.getCell(6).value = tobj.amount; - targetRow.getCell(7).value = tobj.basicFee; - targetRow.getCell(8).value = tobj.serviceCoe; - targetRow.getCell(9).value = tobj.fee; - }); - }); - } - if (sobj.method4) { - cusInsertRowFunc(4 + num_4, [sheet_4.getRow(4)], sheet_4, (targetRow) => { - targetRow.getCell(1).value = num_4++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = sobj.method4.person_num; - targetRow.getCell(5).value = sobj.method4.work_day; - targetRow.getCell(6).value = sobj.method4.fee; - }); - cusInsertRowFunc(5 + num_4_1, [sheet_4_1.getRow(5)], sheet_4_1, (targetRow) => { - targetRow.getCell(1).value = num_4_1++; - targetRow.getCell(2).value = serviceX.ref; - targetRow.getCell(3).value = serviceX.name; - targetRow.getCell(4).value = '/'; - targetRow.getCell(5).value = '/'; - targetRow.getCell(6).value = '/'; - targetRow.getCell(7).value = sobj.method4.person_num; - targetRow.getCell(8).value = sobj.method4.work_day; - targetRow.getCell(9).value = sobj.method4.fee; - }); - sobj.method4.det.forEach((eobj, eindex) => { - const expertX = expertList[eobj.expert]; - cusInsertRowFunc(5 + num_4_1, [sheet_4_1.getRow(5)], sheet_4_1, (targetRow) => { - targetRow.getCell(1).value = num_4_1++; - targetRow.getCell(2).value = expertX.ref; - targetRow.getCell(3).value = expertX.name; - targetRow.getCell(4).value = `${expertX.minPrice}~${expertX.maxPrice}`; - targetRow.getCell(5).value = `${Math.round(expertX.minPrice * expertX.manageCoe)}~${Math.round(expertX.maxPrice * expertX.manageCoe)}`; - targetRow.getCell(6).value = eobj.price; - targetRow.getCell(7).value = eobj.person_num; - targetRow.getCell(8).value = eobj.work_day; - targetRow.getCell(9).value = eobj.fee; - targetRow.getCell(10).value = eobj.desc; - }); - }); - } - }); - }); - - allServices.sort((a, b) => a.id - b.id); - allServices.forEach((s, sindex) => { - const serviceX = serviceList[s.id]; - cusInsertRowFunc(3 + sindex, [yz01_sheet.getRow(2)], yz01_sheet, (targetRow) => { - let siSum = 0; - for (let i = 0; i < yz01Num; i++) { - targetRow.getCell(i * 7 + 1).value = sindex + 1; - targetRow.getCell(i * 7 + 2).value = serviceX.ref; - targetRow.getCell(i * 7 + 3).value = serviceX.name; - targetRow.getCell(i * 7 + 4).value = s.contracts[i * 4]; - targetRow.getCell(i * 7 + 5).value = s.contracts[i * 4 + 1]; - targetRow.getCell(i * 7 + 6).value = s.contracts[i * 4 + 2]; - siSum = siSum + (Number(s.contracts[i * 4]) || 0 + Number(s.contracts[i * 4 + 1]) || 0 + Number(s.contracts[i * 4 + 2]) || 0); - if (i == yz01Num - 1 && yz01Mod == 0) { - targetRow.getCell(i * 7 + 7).value = numberFormatter(siSum, 2); - } else { - targetRow.getCell(i * 7 + 7).value = s.contracts[i * 4 + 3]; - siSum = siSum + (Number(s.contracts[i * 4 + 3]) || 0); - } - } - if (yz01Mod) { - targetRow.getCell(yz01Num * 7 + 1).value = sindex + 1; - targetRow.getCell(yz01Num * 7 + 2).value = serviceX.ref; - targetRow.getCell(yz01Num * 7 + 3).value = serviceX.name; - if (yz01Mod == 1) { - targetRow.getCell(yz01Num * 7 + 4).value = numberFormatter(siSum, 2); - } else if (yz01Mod == 2) { - targetRow.getCell(yz01Num * 7 + 4).value = s.contracts[yz01Num * 4]; - siSum = siSum + (Number(s.contracts[yz01Num * 4]) || 0); - targetRow.getCell(yz01Num * 7 + 5).value = numberFormatter(siSum, 2); - } else { - targetRow.getCell(yz01Num * 7 + 4).value = s.contracts[yz01Num * 4]; - targetRow.getCell(yz01Num * 7 + 5).value = s.contracts[yz01Num * 4 + 1]; - siSum = siSum + (Number(s.contracts[yz01Num * 4]) || 0 + Number(s.contracts[yz01Num * 4 + 1]) || 0); - targetRow.getCell(yz01Num * 7 + 6).value = numberFormatter(siSum, 2); - } - } - }); - }); - - ml_sheet.spliceRows(6, 6); - ml_sheet.spliceRows(6, 1); - - // 合并说明 - if (yz01Num) { - for (let i = 0; i < yz01Num; i++) { - yz01_sheet.getRow(1).getCell(i * 7 + 4).value = `${data.contracts[i * 4].name}预算\n(元)`; - yz01_sheet.getRow(1).getCell(i * 7 + 4).value = `${data.contracts[i * 4 + 1].name}预算\n(元)`; - yz01_sheet.getRow(1).getCell(i * 7 + 4).value = `${data.contracts[i * 4 + 2].name}预算\n(元)`; - if (i == yz01Num - 1 && yz01Mod == 0) { - yz01_sheet.getRow(1).getCell(i * 7 + 4).value = `预算小计\n(元)`; - } else { - yz01_sheet.getRow(1).getCell(i * 7 + 4).value = `${data.contracts[i * 4 + 3].name}预算\n(元)`; - } - yz01_sheet.mergeCells(6, i * 7 + 2, 6, i * 7 + 7); - } - } - if (yz01Mod) { - for (let i = 0; i < yz01Mod; i++) { - if (i == yz01Mod - 1) { - yz01_sheet.getRow(1).getCell(yz01Num * 7 + 4 + i).value = `预算小计\n(元)`; - } else { - yz01_sheet.getRow(1).getCell(yz01Num * 7 + 4 + i).value = `${data.contracts[yz01Num * 4 + i].name}预算\n(元)`; - } - } - yz01_sheet.mergeCells(6, yz01Num * 7 + 2, 6, yz01Num * 7 + 3 + yz01Mod); - } - ml_sheet.mergeCells(ml_slotRow - 7, 1, ml_slotRow - 7, 4); - - workbook.removeWorksheet('预i-1表'); - workbook.removeWorksheet('预i-2表'); - workbook.removeWorksheet('预i-2-1表'); - workbook.removeWorksheet('预i-2-2表'); - workbook.removeWorksheet('预i-3表'); - workbook.removeWorksheet('预i-4表'); - workbook.removeWorksheet('预i-4-1表'); - workbook.getWorksheet('辅01表').orderNo = ml_number + 2 + 10; - workbook.getWorksheet('辅02表').orderNo = ml_number + 3 + 10; - workbook.getWorksheet('辅03表').orderNo = ml_number + 4 + 10; - - workbook._worksheets.forEach(sheet => { - if (sheet) { - if (sheet.headerFooter.oddHeader) sheet.headerFooter.oddHeader = sheet.headerFooter.oddHeader.replace(/&([CLR])&/g, '&$1&"宋体"&'); - if (sheet.headerFooter.oddFooter) sheet.headerFooter.oddFooter = sheet.headerFooter.oddFooter.replace(/&([CLR])&/g, '&$1&"宋体"&'); - } - }); - - window.workbook = workbook; - - return workbook; -} - -function cusInsertRowFunc(insertRowNum, sourceRows, worksheet, RowFun, cellFun) { - // 插入行 - let newRows = []; - for (let i = 0; i < sourceRows.length; i++) { - newRows.push([]); - } - worksheet.insertRows(insertRowNum, newRows); - - for (let i = 0; i < sourceRows.length; i++) { - const sourceRow = sourceRows[i]; - const targetRowNum = insertRowNum + i; - const targetRow = worksheet.getRow(targetRowNum); - targetRow.height = undefined; - sourceRow.eachCell({ includeEmpty: true }, (cell, colNumber) => { - const targetCell = targetRow.getCell(colNumber); - // targetCell.value = cell.value; // 复制内容 - // 复制样式 - if (cell.style) { - targetCell.style = { ...cell.style }; - } - - if (cellFun) { - cellFun(targetCell, cell, colNumber, targetRow, sourceRow); - } - }); - if (RowFun) { - RowFun(targetRow, sourceRow, i); - } - } -} - -function copyWorksheet(workbook, sourceName, targetName) { - const source = workbook.getWorksheet(sourceName); - if (!source) throw new Error("Source sheet not found"); - - const target = workbook.addWorksheet(targetName, { - properties: { ...source.properties }, - pageSetup: { ...source.pageSetup }, - views: source.views ? JSON.parse(JSON.stringify(source.views)) : [], - }); - - /* 复制页眉页脚(关键补充) */ - if (source.headerFooter) { - target.headerFooter = JSON.parse( - JSON.stringify(source.headerFooter) - ); - } - - /* 复制合并单元格 */ - Object.keys(source._merges).forEach(range => { - let rangeModel = source._merges[range].model; - target.mergeCells(rangeModel.top, rangeModel.left, rangeModel.bottom, rangeModel.right); - }); - - /* 复制列(宽度、样式) */ - source.columns.forEach((col, i) => { - const targetCol = target.getColumn(i + 1); - targetCol.width = col.width; - targetCol.style = JSON.parse(JSON.stringify(col.style || {})); - }); - - /* 复制行 & 单元格 */ - source.eachRow({ includeEmpty: true }, (row, rowNumber) => { - const targetRow = target.getRow(rowNumber); - targetRow.height = undefined; - - row.eachCell({ includeEmpty: true }, (cell, colNumber) => { - const targetCell = targetRow.getCell(colNumber); - - // value(富文本/公式安全) - targetCell.value = cloneCellValue(cell.value); - - // style(必须深拷贝) - targetCell.style = JSON.parse(JSON.stringify(cell.style || {})); - }); - }); - - return target; -} - -function insertAndCopyColumn(insertAt, cols, ws) { - let insertAti = insertAt; - cols.forEach((col, index) => { - // 在 insertAti 位置插入空列 - ws.spliceColumns(insertAti, 0, []); - - // 插入后,col 可能需要偏移 - const srcColIndex = col >= insertAti ? col + 1 + index : col; - - // 复制列 - copyColumn(insertAti, srcColIndex, ws); - - insertAti++; - }); -} - -function copyColumn(toCol, fromCol, ws) { - const srcCol = ws.getColumn(fromCol); - const dstCol = ws.getColumn(toCol); - - // 列级属性 - dstCol.width = srcCol.width; - dstCol.hidden = srcCol.hidden; - dstCol.style = JSON.parse(JSON.stringify(srcCol.style || {})); - - // 单元格 - srcCol.eachCell({ includeEmpty: true }, (cell, rowNumber) => { - const dstCell = ws.getRow(rowNumber).getCell(toCol); - dstCell.value = cloneCellValue(cell.value); - dstCell.style = JSON.parse(JSON.stringify(cell.style || {})); - }); -} - -function cloneCellValue(value) { - if (value == null) return value; - - if (typeof value === "object") { - return JSON.parse(JSON.stringify(value)); - } - return value; -} - -function numberFormatter(num, decimalNum) { - if (num == null || String(num).trim().length == 0) return null; - let varArr = String(num).split("."); - let big = Number(varArr[0]).toLocaleString(); - if (decimalNum > 0) { - let decimal = varArr.length > 1 ? varArr[1] + '000000' : '000000'; - decimal = decimal.slice(0, decimalNum); - return big + '.' + decimal; - } else { - return big; - } -} - - - -let data1 = { - name: 'test001', - writer: '张三',// 编制人 - reviewer: '李四',// 复核人 - company: '测试公司',// 公司名称 - date: '2021-09-24',// 编制日期 - industry: 0,// 0为公路工程,1为铁路工程,2为水运工程 - fee: 10000, - scaleCost: 100000,// scale的cost的合计数 - scale: [// 规模信息 - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - serviceCoes: [// 项目咨询分类系数 - { - serviceid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - serviceid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - majorCoes: [// 项目工程专业系数 - { - majorid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - majorid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - contracts: [// 合同段信息 - { - name: 'A合同段', - serviceFee: 100000, - addtionalFee: 0, - reserveFee: 0, - fee: 10000, - scale: [ - { - major: 0, - cost: 100000, - area: 200, - }, - { - major: 1, - cost: 100000, - area: 200, - }, - ], - serviceCoes: [// 合同段咨询分类系数 - { - serviceid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - serviceid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - majorCoes: [// 合同段工程专业系数 - { - majorid: 0, - coe: 1.1, - remark: '',// 用户输入的说明 - }, - { - majorid: 1, - coe: 1.2, - remark: '',// 用户输入的说明 - }, - ], - services: [ - { - id: 0, - fee: 100000, - process: 0,// 工作环节,0为编制,1为审核 - method1: { // 投资规模法 - cost: 100000, - basicFee: 200, - basicFee_basic: 200, - basicFee_optional: 0, - fee: 250000, - proAmount: 3, - det: [ - { - proNum: 1, - major: 0, - cost: 100000, - basicFee: 200, - basicFormula: '856,000+(1,000,000,000-500,000,000)×1‰', - basicFee_basic: 200, - optionalFormula: '171,200+(1,000,000,000-500,000,000)×0.2‰', - basicFee_optional: 0, - serviceCoe: 1.1, - majorCoe: 1.2, - processCoe: 1,// 工作环节系数(编审系数) - proportion: 0.5,// 工作占比 - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method2: { // 用地规模法 - area: 1200, - basicFee: 200, - basicFee_basic: 200, - basicFee_optional: 0, - fee: 250000, - proAmount: 3, - det: [ - { - proNum: 1, - major: 0, - area: 1200, - basicFee: 200, - basicFormula: '106,000+(1,200-1,000)×60', - basicFee_basic: 200, - optionalFormula: '21,200+(1,200-1,000)×12', - basicFee_optional: 0, - serviceCoe: 1.1, - majorCoe: 1.2, - processCoe: 1,// 工作环节系数(编审系数) - proportion: 0.5,// 工作占比 - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method3: { // 工作量法 - basicFee: 200, - fee: 250000, - det: [ - { - task: 0, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - task: 1, - price: 100000, - amount: 10, - basicFee: 200, - serviceCoe: 1.1, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - method4: { // 工时法 - person_num: 10, - work_day: 10, - fee: 250000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - }, - ], - addtional: {// 附加工作费 - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'C' }] }, - name: '附加工作', - fee: 10000, - det: [ - { - id: 0, - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'F' }] }, - name: '人员驻场服务及其他附加工作', - fee: 10000, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - }, - { - id: 1, - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'C' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'X' }] }, - name: '咨询服务协调工作', - fee: 10000, - m0: { - coe: 0.03, - fee: 10000, - }, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - }, - ] - }, - reserve: {// 预备费 - code: { richText: [{ font: { charset: 134, color: { theme: 1 }, italic: true, name: '宋体', size: 10 }, text: 'Y' }, { font: { charset: 134, color: { theme: 1 }, italic: true, name: 'Calibri', size: 10, vertAlign: 'subscript' }, text: 'B' }] }, - name: '预备费', - fee: 10000, - m0: { - coe: 0.03, - fee: 10000, - }, - m4: { - person_num: 10, - work_day: 3, - fee: 10000, - det: [ - { - expert: 0, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - expert: 1, - price: 100000, - person_num: 10, - work_day: 3, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - }, - m5: { - fee: 10000, - det: [ - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - { - name: '×××项', - unit: '项', - amount: 10, - price: 100000, - fee: 100000, - remark: '',// 用户输入的说明 - }, - ], - } - }, - }, - ], -}; diff --git a/public/标准文件转代码Data.xlsx b/public/标准文件转代码Data.xlsx deleted file mode 100644 index c642477..0000000 Binary files a/public/标准文件转代码Data.xlsx and /dev/null differ diff --git a/public/造价咨询服务计费报表模板.xlsx b/public/造价咨询服务计费报表模板.xlsx deleted file mode 100644 index ae61d98..0000000 Binary files a/public/造价咨询服务计费报表模板.xlsx and /dev/null differ diff --git a/scripts/package-dist-image.ps1 b/scripts/package-dist-image.ps1 new file mode 100644 index 0000000..f808926 --- /dev/null +++ b/scripts/package-dist-image.ps1 @@ -0,0 +1,45 @@ +param( + [string]$ImageName = "jgjs2026-dist", + [string]$Tag = "latest" +) + +$ErrorActionPreference = "Stop" + +$projectRoot = Split-Path -Parent $PSScriptRoot +$distPath = Join-Path $projectRoot "dist" +$dockerfilePath = Join-Path $projectRoot "Dockerfile.dist" +$serverSourcePath = Join-Path $projectRoot "docker\\dist-server" +$buildContext = Join-Path ([System.IO.Path]::GetTempPath()) ("jgjs2026-dist-docker-" + [System.Guid]::NewGuid().ToString("N")) + +if (-not (Test-Path $distPath)) { + throw "dist directory not found. Run npm run build first." +} + +if (-not (Test-Path $dockerfilePath)) { + throw "Dockerfile.dist not found." +} + +if (-not (Test-Path $serverSourcePath)) { + throw "docker/dist-server not found." +} + +New-Item -ItemType Directory -Path $buildContext | Out-Null +New-Item -ItemType Directory -Path (Join-Path $buildContext "docker") | Out-Null + +try { + Copy-Item $dockerfilePath (Join-Path $buildContext "Dockerfile.dist") + Copy-Item $serverSourcePath (Join-Path $buildContext "docker\\dist-server") -Recurse + Copy-Item $distPath (Join-Path $buildContext "dist") -Recurse + + Write-Host "Building Docker image ${ImageName}:${Tag} from minimal dist context..." + docker build -f (Join-Path $buildContext "Dockerfile.dist") -t "${ImageName}:${Tag}" $buildContext +} +finally { + if (Test-Path $buildContext) { + Remove-Item $buildContext -Recurse -Force + } +} + +Write-Host "Done." +Write-Host "Run with:" +Write-Host "docker run --rm -p 8080:80 ${ImageName}:${Tag}" diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo index 896c85b..901a85e 100644 --- a/tsconfig.tsbuildinfo +++ b/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/main.ts","./src/sql.ts","./src/components/ui/button/index.ts","./src/components/ui/card/index.ts","./src/components/ui/scroll-area/index.ts","./src/components/ui/tooltip/index.ts","./src/features/ht/contracts.ts","./src/features/ht/importexport.ts","./src/features/ht/types.ts","./src/features/tab/importexport.ts","./src/features/tab/types.ts","./src/i18n/dictionary-en.ts","./src/i18n/index.ts","./src/i18n/locales/en-us.ts","./src/i18n/locales/zh-cn.ts","./src/lib/aggridreadonlyautoheight.ts","./src/lib/aggridresetheader.ts","./src/lib/contractsegment.ts","./src/lib/decimal.ts","./src/lib/diyaggridoptions.ts","./src/lib/number.ts","./src/lib/numberformat.ts","./src/lib/pricinghourlycalc.ts","./src/lib/pricingmethodtotals.ts","./src/lib/pricingpersistcontrol.ts","./src/lib/pricingpinnedrows.ts","./src/lib/pricingscalecalc.ts","./src/lib/pricingscalecolumns.ts","./src/lib/pricingscaledetail.ts","./src/lib/pricingscaledict.ts","./src/lib/pricingscalefee.ts","./src/lib/pricingscalegrid.ts","./src/lib/pricingscalelink.ts","./src/lib/pricingscalepanedata.ts","./src/lib/pricingscalepanelifecycle.ts","./src/lib/pricingscaleproject.ts","./src/lib/pricingscalerowmap.ts","./src/lib/pricingworkloadcalc.ts","./src/lib/projectevents.ts","./src/lib/projectregistry.ts","./src/lib/projectsessionlock.ts","./src/lib/projectworkspace.ts","./src/lib/reportexportbuilders.ts","./src/lib/utils.ts","./src/lib/workspace.ts","./src/lib/xmfactordefaults.ts","./src/lib/zwarchive.ts","./src/lib/zxfwpricingsync.ts","./src/pinia/kv.ts","./src/pinia/tab.ts","./src/pinia/uiprefs.ts","./src/pinia/zxfwpricing.ts","./src/pinia/zxfwpricinghtfee.ts","./src/pinia/zxfwpricingkeys.ts","./src/pinia/plugin/indexdb.ts","./src/pinia/plugin/types.d.ts","./src/types/pricing.ts","./src/app.vue","./src/components/ui/button/button.vue","./src/components/ui/card/card.vue","./src/components/ui/card/cardaction.vue","./src/components/ui/card/cardcontent.vue","./src/components/ui/card/carddescription.vue","./src/components/ui/card/cardfooter.vue","./src/components/ui/card/cardheader.vue","./src/components/ui/card/cardtitle.vue","./src/components/ui/scroll-area/scrollarea.vue","./src/components/ui/scroll-area/scrollbar.vue","./src/components/ui/tooltip/tooltipcontent.vue","./src/features/ht/components/ht.vue","./src/features/ht/components/htadditionalworkfee.vue","./src/features/ht/components/htbaseinfo.vue","./src/features/ht/components/htconsultcategoryfactor.vue","./src/features/ht/components/htcontractsummary.vue","./src/features/ht/components/htfeeratemethodform.vue","./src/features/ht/components/htmajorfactor.vue","./src/features/ht/components/htreservefee.vue","./src/features/ht/components/htcard.vue","./src/features/ht/components/htinfo.vue","./src/features/ht/components/zxfw.vue","./src/features/pricing/components/hourlypricingpane.vue","./src/features/pricing/components/investmentscalepricingpane.vue","./src/features/pricing/components/landscalepricingpane.vue","./src/features/pricing/components/workloadpricingpane.vue","./src/features/shared/components/hourlyfeegrid.vue","./src/features/shared/components/htfeegrid.vue","./src/features/shared/components/htfeemethodgrid.vue","./src/features/shared/components/methodunavailablenotice.vue","./src/features/shared/components/servicecheckboxselector.vue","./src/features/shared/components/workcontentgrid.vue","./src/features/shared/components/xmfactorgrid.vue","./src/features/shared/components/xmcommonaggrid.vue","./src/features/workbench/components/homeentryview.vue","./src/features/workbench/components/htfeemethodtypelineview.vue","./src/features/workbench/components/quickcalcworkbenchview.vue","./src/features/workbench/components/zxfwview.vue","./src/features/xm/components/xmconsultcategoryfactor.vue","./src/features/xm/components/xmmajorfactor.vue","./src/features/xm/components/info.vue","./src/features/xm/components/xmcard.vue","./src/features/xm/components/xminfo.vue","./src/layout/tab.vue","./src/layout/typeline.vue"],"version":"5.9.3"} \ No newline at end of file +{"root":["./src/main.ts","./src/sql.ts","./src/components/ui/button/index.ts","./src/components/ui/card/index.ts","./src/components/ui/scroll-area/index.ts","./src/components/ui/tooltip/index.ts","./src/features/ht/contracts.ts","./src/features/ht/importexport.ts","./src/features/ht/types.ts","./src/features/tab/importexport.ts","./src/features/tab/types.ts","./src/i18n/dictionary-en.ts","./src/i18n/index.ts","./src/i18n/locales/en-us.ts","./src/i18n/locales/zh-cn.ts","./src/lib/aggridreadonlyautoheight.ts","./src/lib/aggridresetheader.ts","./src/lib/contractsegment.ts","./src/lib/decimal.ts","./src/lib/diyaggridoptions.ts","./src/lib/number.ts","./src/lib/numberformat.ts","./src/lib/pricinghourlycalc.ts","./src/lib/pricingmethodtotals.ts","./src/lib/pricingpersistcontrol.ts","./src/lib/pricingpinnedrows.ts","./src/lib/pricingscalecalc.ts","./src/lib/pricingscalecolumns.ts","./src/lib/pricingscaledetail.ts","./src/lib/pricingscaledict.ts","./src/lib/pricingscalefee.ts","./src/lib/pricingscalegrid.ts","./src/lib/pricingscalelink.ts","./src/lib/pricingscalepanedata.ts","./src/lib/pricingscalepanelifecycle.ts","./src/lib/pricingscaleproject.ts","./src/lib/pricingscalerowmap.ts","./src/lib/pricingworkloadcalc.ts","./src/lib/projectevents.ts","./src/lib/projectkvstore.ts","./src/lib/projectregistry.ts","./src/lib/projectsessionlock.ts","./src/lib/projectworkspace.ts","./src/lib/reportexportbuilders.ts","./src/lib/utils.ts","./src/lib/workspace.ts","./src/lib/xmfactordefaults.ts","./src/lib/zwarchive.ts","./src/lib/zxfwpricingsync.ts","./src/pinia/kv.ts","./src/pinia/tab.ts","./src/pinia/uiprefs.ts","./src/pinia/zxfwpricing.ts","./src/pinia/zxfwpricinghtfee.ts","./src/pinia/zxfwpricingkeys.ts","./src/pinia/plugin/indexdb.ts","./src/pinia/plugin/types.d.ts","./src/types/pricing.ts","./src/app.vue","./src/components/ui/button/button.vue","./src/components/ui/card/card.vue","./src/components/ui/card/cardaction.vue","./src/components/ui/card/cardcontent.vue","./src/components/ui/card/carddescription.vue","./src/components/ui/card/cardfooter.vue","./src/components/ui/card/cardheader.vue","./src/components/ui/card/cardtitle.vue","./src/components/ui/scroll-area/scrollarea.vue","./src/components/ui/scroll-area/scrollbar.vue","./src/components/ui/tooltip/tooltipcontent.vue","./src/features/ht/components/ht.vue","./src/features/ht/components/htadditionalworkfee.vue","./src/features/ht/components/htbaseinfo.vue","./src/features/ht/components/htconsultcategoryfactor.vue","./src/features/ht/components/htcontractsummary.vue","./src/features/ht/components/htfeeratemethodform.vue","./src/features/ht/components/htmajorfactor.vue","./src/features/ht/components/htreservefee.vue","./src/features/ht/components/htcard.vue","./src/features/ht/components/htinfo.vue","./src/features/ht/components/zxfw.vue","./src/features/pricing/components/hourlypricingpane.vue","./src/features/pricing/components/investmentscalepricingpane.vue","./src/features/pricing/components/landscalepricingpane.vue","./src/features/pricing/components/workloadpricingpane.vue","./src/features/shared/components/hourlyfeegrid.vue","./src/features/shared/components/htfeegrid.vue","./src/features/shared/components/htfeemethodgrid.vue","./src/features/shared/components/methodunavailablenotice.vue","./src/features/shared/components/servicecheckboxselector.vue","./src/features/shared/components/workcontentgrid.vue","./src/features/shared/components/xmfactorgrid.vue","./src/features/shared/components/xmcommonaggrid.vue","./src/features/workbench/components/homeentryview.vue","./src/features/workbench/components/htfeemethodtypelineview.vue","./src/features/workbench/components/quickcalcworkbenchview.vue","./src/features/workbench/components/zxfwview.vue","./src/features/xm/components/xmconsultcategoryfactor.vue","./src/features/xm/components/xmmajorfactor.vue","./src/features/xm/components/info.vue","./src/features/xm/components/xmcard.vue","./src/features/xm/components/xminfo.vue","./src/layout/tab.vue","./src/layout/typeline.vue"],"version":"5.9.3"} \ No newline at end of file