This commit is contained in:
wintsa 2026-03-24 10:20:33 +08:00
parent e4c6203a98
commit 8417f8d5cc
3 changed files with 283 additions and 168 deletions

View File

@ -3,12 +3,14 @@ import { computed, onActivated, onMounted, ref, watch } from 'vue'
import { Check, ChevronDown, Circle, CircleDot } from 'lucide-vue-next'
import {
getQuickCalcGroups,
getMajorDictEntries,
getServiceDictEntries,
getMajorDictItemById,
getServiceDictItemById,
industryTypeList
} from '@/sql'
import { parseNumberOrNull } from '@/lib/number'
import { useKvStore } from '@/pinia/kv'
import { loadConsultCategoryFactorMap, loadMajorFactorMap } from '@/lib/xmFactorDefaults'
import { getIndustryMajorEntry } from '@/lib/pricingScaleCalc'
import { getBenchmarkBudgetSplitByScale, getScaleBudgetFeeSplit } from '@/lib/pricingScaleFee'
import { QUICK_PROJECT_INFO_KEY } from '@/lib/workspace'
import { initializeProjectFactorStates } from '@/lib/projectWorkspace'
@ -47,42 +49,16 @@ type DictFactorItem = {
onlyCostScale?: boolean | null
}
type QuickCalcScaleMode = 'cost' | 'area'
const kvStore = useKvStore()
const serviceDictEntries = getServiceDictEntries()
const majorDictEntries = getMajorDictEntries()
const serviceDictIndex = new Map<string, DictFactorItem>(
serviceDictEntries.map(({ id, item }) => [
`${String(item?.code || '').trim()}::${String(item?.name || '').trim()}`,
{
id: String(id),
name: String(item?.name || ''),
code: String(item?.code || ''),
defCoe: typeof item?.defCoe === 'number' ? item.defCoe : null,
scale: item?.scale === true,
onlyCostScale: item?.onlyCostScale === true
}
])
)
const majorDictIndex = new Map<string, DictFactorItem>(
majorDictEntries.map(({ id, item }) => [
`${String(item?.code || '').trim()}::${String(item?.name || '').trim()}`,
{
id: String(id),
name: String(item?.name || ''),
code: String(item?.code || ''),
defCoe: typeof item?.defCoe === 'number' ? item.defCoe : null,
hasCost: item?.hasCost === true,
hasArea: item?.hasArea === true
}
])
)
const consultFactorMap = ref<Map<string, number | null>>(new Map())
const majorFactorMap = ref<Map<string, number | null>>(new Map())
const quickCalcGroups = getQuickCalcGroups()
const projectIndustry = ref('')
const selectedConsultLabel = ref('')
const selectedMajor = ref<{ groupKey: string; label: string } | null>(null)
const selectedConsultKey = ref('')
const selectedMajor = ref<{ groupKey: string; optionKey: string } | null>(null)
const investScale = ref('')
const landScale = ref('')
const workEnvFactor = ref('1')
@ -90,20 +66,42 @@ const industrySaving = ref(false)
let latestIndustryRequest = 0
const hasSelectedIndustry = computed(() => projectIndustry.value.trim() !== '')
const hasSelectedConsult = computed(() => selectedConsultLabel.value.trim() !== '')
const hasSelectedConsult = computed(() => selectedConsultKey.value.trim() !== '')
const mapDictItemToFactorItem = (id: string, item: Record<string, unknown> | undefined): DictFactorItem | null => {
if (!item) return null
return {
id,
name: String(item.name || ''),
code: String(item.code || ''),
defCoe: typeof item.defCoe === 'number' ? item.defCoe : null,
hasCost: item.hasCost === true,
hasArea: item.hasArea === true,
scale: item.scale === true,
onlyCostScale: item.onlyCostScale === true
}
}
const isDefined = <T,>(value: T | null | undefined): value is T => value != null
const resolveOptionId = (option: { id: string | Record<string, string> } | null) => {
if (!option) return ''
if (typeof option.id === 'string') return option.id
const industry = projectIndustry.value.trim()
return option.id[industry] || Object.values(option.id)[0] || ''
}
const shouldShowMajorOption = (
group: { key: string },
option: { label: string; code: string | Record<string, string> }
option: { id: string | Record<string, string> }
) => {
if (!hasSelectedConsult.value) return false
if (!consultSupportsScale.value) return false
const code = resolveOptionCode(option)
if (consultOnlySupportsCostScale.value) return false
const majorDictItem = getMajorDictItemById(resolveOptionId(option))
const code = String(majorDictItem?.code || '').trim()
if (!code) return false
const isLeafMajor = code.includes('-')
if (consultOnlySupportsCostScale.value) {
return group.key !== 'general' && !isLeafMajor
}
return isLeafMajor
}
@ -117,14 +115,15 @@ const visibleGroups = computed(() => {
return group.industryId === industry
})
.map(group => {
if (group.key === 'consult') return group
const filteredItems = group.items.filter(item => shouldShowMajorOption(group, item))
const visibleLabels = new Set(filteredItems.map(item => item.label))
const filteredItems = group.key === 'consult'
? group.items
: group.items.filter(item => shouldShowMajorOption(group, item))
const itemMap = new Map(filteredItems.map(item => [item.key, item]))
return {
...group,
items: filteredItems,
rows: group.rows
.map(row => row.filter(label => visibleLabels.has(label)))
.map(row => row.map(optionKey => itemMap.get(optionKey)).filter(isDefined))
.filter(row => row.length > 0)
}
})
@ -139,7 +138,7 @@ const industryLabel = computed(() => {
const selectedConsultOption = computed(() =>
quickCalcGroups
.find(item => item.key === 'consult')
?.items.find(item => item.label === selectedConsultLabel.value) || null
?.items.find(item => item.key === selectedConsultKey.value) || null
)
const selectedMajorGroup = computed(() =>
selectedMajor.value
@ -149,24 +148,32 @@ const selectedMajorGroup = computed(() =>
const selectedMajorOption = computed(() => {
if (!selectedMajor.value) return null
const group = visibleGroups.value.find(item => item.key === selectedMajor.value?.groupKey)
return group?.items.find(item => item.label === selectedMajor.value?.label) || null
return group?.items.find(item => item.key === selectedMajor.value?.optionKey) || null
})
const resolveOptionCode = (option: { code: string | Record<string, string> } | null) => {
if (!option) return ''
if (typeof option.code === 'string') return option.code
const industry = projectIndustry.value.trim()
return option.code[industry] || Object.values(option.code)[0] || ''
}
const selectedConsultCode = computed(() => resolveOptionCode(selectedConsultOption.value))
const selectedMajorCode = computed(() => resolveOptionCode(selectedMajorOption.value))
const selectedConsultId = computed(() => resolveOptionId(selectedConsultOption.value))
const selectedMajorId = computed(() => resolveOptionId(selectedMajorOption.value))
const selectedConsultCode = computed(() => String(selectedConsultDictItem.value?.code || ''))
const selectedConsultLabel = computed(() => selectedConsultOption.value?.label || '')
const selectedConsultDictItem = computed(() =>
serviceDictIndex.get(`${selectedConsultCode.value}::${selectedConsultLabel.value}`) || null
mapDictItemToFactorItem(selectedConsultId.value, getServiceDictItemById(selectedConsultId.value) as Record<string, unknown> | undefined)
)
const selectedMajorDictItem = computed(() => {
if (!selectedMajor.value) return null
return majorDictIndex.get(`${selectedMajorCode.value}::${selectedMajor.value.label}`) || null
return mapDictItemToFactorItem(selectedMajorId.value, getMajorDictItemById(selectedMajorId.value) as Record<string, unknown> | undefined)
})
const effectiveMajorDictItem = computed(() => {
if (selectedMajorDictItem.value) return selectedMajorDictItem.value
if (!consultOnlySupportsCostScale.value) return null
const industryMajorEntry = getIndustryMajorEntry(projectIndustry.value.trim())
if (!industryMajorEntry) return null
return {
id: String(industryMajorEntry.id),
name: String(industryMajorEntry.item?.name || ''),
code: String(industryMajorEntry.item?.code || ''),
defCoe: typeof industryMajorEntry.item?.defCoe === 'number' ? industryMajorEntry.item.defCoe : null,
hasCost: industryMajorEntry.item?.hasCost === true,
hasArea: industryMajorEntry.item?.hasArea === true
}
})
const consultCategoryFactor = computed(() => {
const serviceId = selectedConsultDictItem.value?.id
@ -174,34 +181,52 @@ const consultCategoryFactor = computed(() => {
return consultFactorMap.value.get(serviceId) ?? null
})
const defaultEngineeringMajorFactor = computed(() => {
const majorId = selectedMajorDictItem.value?.id
const majorId = effectiveMajorDictItem.value?.id
if (!majorId) return null
return majorFactorMap.value.get(majorId) ?? null
})
const engineeringMajorFactor = computed(() => defaultEngineeringMajorFactor.value)
const hasResolvedMajor = computed(() => effectiveMajorDictItem.value != null)
const majorSupportsCostScale = computed(() => effectiveMajorDictItem.value?.hasCost === true)
const majorSupportsLandScale = computed(() => effectiveMajorDictItem.value?.hasArea === true)
const preferLandScaleForDualMajor = computed(() => majorSupportsCostScale.value && majorSupportsLandScale.value)
const workEnvCoefficient = computed(() => {
const parsed = Number(workEnvFactor.value)
return Number.isFinite(parsed) ? parsed : null
})
const consultSupportsScale = computed(() => selectedConsultDictItem.value?.scale === true)
const consultOnlySupportsCostScale = computed(() => selectedConsultDictItem.value?.onlyCostScale === true)
const canUseInvestScale = computed(() => consultSupportsScale.value)
const canUseInvestScale = computed(() =>
consultSupportsScale.value &&
hasResolvedMajor.value &&
(
consultOnlySupportsCostScale.value ||
(majorSupportsCostScale.value && !preferLandScaleForDualMajor.value)
)
)
const canUseLandScale = computed(() =>
consultSupportsScale.value &&
!consultOnlySupportsCostScale.value
hasResolvedMajor.value &&
!consultOnlySupportsCostScale.value &&
majorSupportsLandScale.value
)
const investScalePlaceholder = computed(() => {
if (!selectedConsultLabel.value) return '请先选择咨询类别'
if (!consultSupportsScale.value) return '当前分类不适用规模法'
if (!hasResolvedMajor.value) return '请先选择工程专业'
if (preferLandScaleForDualMajor.value) return '当前专业按用地规模计价'
if (!consultOnlySupportsCostScale.value && !majorSupportsCostScale.value) return '当前专业不适用投资规模'
return '请输入'
})
const landScalePlaceholder = computed(() => {
if (!selectedConsultLabel.value) return '请先选择咨询类别'
if (!consultSupportsScale.value) return '当前分类不适用规模法'
if (!hasResolvedMajor.value) return '请先选择工程专业'
if (consultOnlySupportsCostScale.value) return '当前分类仅支持投资规模'
if (!majorSupportsLandScale.value) return '当前专业不适用用地规模'
return '请输入'
})
const activeScaleMode = computed<'cost' | 'area' | null>(() => {
const activeScaleMode = computed<QuickCalcScaleMode | null>(() => {
const hasInvestValue = investScale.value.trim() !== ''
const hasLandValue = landScale.value.trim() !== ''
@ -211,58 +236,97 @@ const activeScaleMode = computed<'cost' | 'area' | null>(() => {
if (canUseLandScale.value) return 'area'
return null
})
const benchmarkSplit = computed(() => {
const scaleBudgetPreview = computed(() => {
const mode = activeScaleMode.value
if (!mode) return null
return getBenchmarkBudgetSplitByScale(mode === 'cost' ? investScale.value : landScale.value, mode)
const scaleValue = parseNumberOrNull(
mode === 'cost' ? investScale.value : landScale.value,
{ sanitize: true, precision: 3 }
)
if (scaleValue == null) return null
console.log(mode)
const rawSplit = getBenchmarkBudgetSplitByScale(scaleValue, mode)
console.log(rawSplit)
if (!rawSplit) return null
const checkedSplit = {
...rawSplit,
basic: rawSplit.basic,
optional: rawSplit.optional,
total: rawSplit.total
}
const budgetFeeSplit = getScaleBudgetFeeSplit({
benchmarkBudgetBasic: checkedSplit.basic,
benchmarkBudgetOptional: checkedSplit.optional,
majorFactor: engineeringMajorFactor.value,
consultCategoryFactor: consultCategoryFactor.value,
workStageFactor: workEnvCoefficient.value
})
return {
mode,
scaleValue,
benchmarkBudgetBasic: checkedSplit.basic,
benchmarkBudgetOptional: checkedSplit.optional,
benchmarkBudget: checkedSplit.total,
basicFormula: rawSplit.basicFormula,
optionalFormula: rawSplit.optionalFormula,
budgetFeeBasic: budgetFeeSplit?.basic ?? null,
budgetFeeOptional: budgetFeeSplit?.optional ?? null,
budgetFeeTotal: budgetFeeSplit?.total ?? null
}
})
const formulaText = computed(() => {
const split = benchmarkSplit.value
if (!split) return '请先选择工程行业、咨询类别、工程专业,并输入对应规模'
const parts = [split.basicFormula, split.optionalFormula].filter(Boolean)
const preview = scaleBudgetPreview.value
if (!preview) return '请先选择输入对应规模'
const parts = [preview.basicFormula, preview.optionalFormula].filter(Boolean)
return parts.join(' + ') || '--'
})
const benchmarkAmountText = computed(() => {
const total = benchmarkSplit.value?.total
const total = scaleBudgetPreview.value?.benchmarkBudget
if (total == null) return '--'
return total.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
})
const computedBudgetAmount = computed(() => {
const split = benchmarkSplit.value
if (!split) return '--'
const total = getScaleBudgetFeeSplit({
benchmarkBudgetBasic: split.basic,
benchmarkBudgetOptional: split.optional,
majorFactor: engineeringMajorFactor.value,
consultCategoryFactor: consultCategoryFactor.value,
workStageFactor: workEnvCoefficient.value
})?.total
const total = scaleBudgetPreview.value?.budgetFeeTotal
if (total == null) return '--'
return total.toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
})
const applyScaleInput = (field: 'invest' | 'land') => {
const currentValue = field === 'invest' ? investScale.value : landScale.value
const next = parseNumberOrNull(currentValue, { sanitize: true, precision: 3 })
const normalized = next == null ? '' : String(next)
if (field === 'invest') {
investScale.value = normalized
return
}
landScale.value = normalized
}
const totalSelectedCount = computed(() => {
let count = 0
if (selectedConsultLabel.value) count += 1
if (selectedConsultKey.value) count += 1
if (selectedMajor.value) count += 1
return count
})
const isOptionSelected = (groupKey: string, label: string) => {
if (groupKey === 'consult') return selectedConsultLabel.value === label
return selectedMajor.value?.groupKey === groupKey && selectedMajor.value?.label === label
const isOptionSelected = (groupKey: string, optionKey: string) => {
if (groupKey === 'consult') return selectedConsultKey.value === optionKey
return selectedMajor.value?.groupKey === groupKey && selectedMajor.value?.optionKey === optionKey
}
const toggleItem = (groupKey: string, label: string) => {
const toggleItem = (groupKey: string, optionKey: string) => {
if (groupKey === 'consult') {
selectedConsultLabel.value = selectedConsultLabel.value === label ? '' : label
selectedConsultKey.value = selectedConsultKey.value === optionKey ? '' : optionKey
return
}
if (isOptionSelected(groupKey, label)) {
if (isOptionSelected(groupKey, optionKey)) {
selectedMajor.value = null
return
}
selectedMajor.value = { groupKey, label }
selectedMajor.value = { groupKey, optionKey }
}
const loadFactorDefaults = async () => {
@ -340,7 +404,7 @@ watch(
() => {
if (!selectedMajor.value) return
const group = visibleGroups.value.find(item => item.key === selectedMajor.value?.groupKey)
const stillVisible = group?.items.some(item => item.label === selectedMajor.value?.label) === true
const stillVisible = group?.items.some(item => item.key === selectedMajor.value?.optionKey) === true
if (!stillVisible) {
selectedMajor.value = null
}
@ -426,6 +490,10 @@ watch(canUseLandScale, enabled => {
当前咨询类别不适用规模法因此不显示专业分类
</div>
<div v-else-if="consultOnlySupportsCostScale" class="quick-calc-empty-state">
当前咨询类别按行业汇总计价工程专业系数已按所选行业自动带入不再显示内部互补专业行
</div>
<div class="quick-calc-catalog">
<article
v-for="group in visibleGroups"
@ -449,26 +517,26 @@ watch(canUseLandScale, enabled => {
class="quick-calc-selection-row"
>
<label
v-for="label in row"
:key="`${group.key}-${label}`"
v-for="option in row"
:key="`${group.key}-${option.key}`"
class="quick-calc-inline-option"
:class="{ 'is-selected': isOptionSelected(group.key, label) }"
:class="{ 'is-selected': isOptionSelected(group.key, option.key) }"
>
<input
:checked="isOptionSelected(group.key, label)"
:checked="isOptionSelected(group.key, option.key)"
type="radio"
:name="group.key === 'consult' ? 'quick-calc-consult-choice' : 'quick-calc-major-choice'"
class="quick-calc-option__input"
@change="toggleItem(group.key, label)"
@change="toggleItem(group.key, option.key)"
>
<span class="quick-calc-inline-option__icon" :class="{ 'is-selected': isOptionSelected(group.key, label) }">
<CircleDot v-if="isOptionSelected(group.key, label)" class="h-3.5 w-3.5" />
<span class="quick-calc-inline-option__icon" :class="{ 'is-selected': isOptionSelected(group.key, option.key) }">
<CircleDot v-if="isOptionSelected(group.key, option.key)" class="h-3.5 w-3.5" />
<Circle v-else class="h-3.5 w-3.5" />
</span>
<span
class="quick-calc-inline-option__text"
:class="{ 'is-selected': isOptionSelected(group.key, label) }"
>{{ label }}</span>
:class="{ 'is-selected': isOptionSelected(group.key, option.key) }"
>{{ option.label }}</span>
</label>
<div v-if="row.length === 0" class="quick-calc-selection-row__blank" />
@ -520,10 +588,13 @@ watch(canUseLandScale, enabled => {
<span class="quick-calc-field__label">投资规模万元</span>
<input
v-model="investScale"
type="text"
inputmode="decimal"
class="quick-calc-field__input"
:class="{ 'is-disabled': !canUseInvestScale }"
:disabled="!canUseInvestScale"
:placeholder="investScalePlaceholder"
@blur="applyScaleInput('invest')"
>
</label>
@ -531,10 +602,13 @@ watch(canUseLandScale, enabled => {
<span class="quick-calc-field__label">用地规模</span>
<input
v-model="landScale"
type="text"
inputmode="decimal"
class="quick-calc-field__input"
:class="{ 'is-disabled': !canUseLandScale }"
:disabled="!canUseLandScale"
:placeholder="landScalePlaceholder"
@blur="applyScaleInput('land')"
>
</label>
</div>
@ -898,18 +972,18 @@ watch(canUseLandScale, enabled => {
.quick-calc-group__rows {
display: grid;
grid-template-rows: repeat(3, minmax(46px, auto));
grid-auto-rows: minmax(46px, auto);
background:
linear-gradient(180deg, color-mix(in srgb, white 18%, transparent) 0%, transparent 100%);
}
.quick-calc-group__rows:has(.quick-calc-selection-row:only-child) {
grid-template-rows: minmax(46px, auto);
grid-auto-rows: minmax(46px, auto);
}
.quick-calc-group--general .quick-calc-group__rows,
.quick-calc-group--general .quick-calc-group__rows:has(.quick-calc-selection-row:only-child) {
grid-template-rows: minmax(38px, auto);
grid-auto-rows: minmax(38px, auto);
}
.quick-calc-selection-row {

View File

@ -12,6 +12,16 @@ export interface ScaleFeeSplitResult {
optionalFormula: string
}
/**
* +
*
*
* 1.
* 2. / /
* 3.
*
*
*/
export const getBenchmarkBudgetSplitByScale = (
value: unknown,
mode: ScaleMode
@ -40,6 +50,20 @@ export const getBenchmarkBudgetByScale = (value: unknown, mode: ScaleMode) => {
return splitResult ? splitResult.total : null
}
/**
* +
*
*
* 1. basic / optional
* 2.
* 3. / /
*
* `getBenchmarkBudgetSplitByScale`
* - `getBenchmarkBudgetSplitByScale`
* - `getScaleBudgetFeeSplit`
*
* `basicFormula / optionalFormula`
*/
export const getScaleBudgetFeeSplit = (params: {
benchmarkBudgetBasic: unknown
benchmarkBudgetOptional: unknown

View File

@ -675,8 +675,9 @@ export const getServiceDictItemById = (id: string | number): DictItem | undefine
}
export type QuickCalcOption = {
key: string
label: string
code: string | Record<string, string>
id: string | Record<string, string>
}
export type QuickCalcGroup = {
@ -691,25 +692,27 @@ export type QuickCalcGroup = {
const getQuickDictLabel = (item: DictItem | undefined, fallback = '') =>
String(item?.quickLabel || item?.name || fallback)
const createQuickOptionByServiceCode = (
code: string,
const createQuickOptionByServiceKey = (
key: string,
override?: Partial<QuickCalcOption> & { label?: string }
): QuickCalcOption => {
const entry = getServiceDictEntries().find(item => String(item.item?.code || '') === code)
const entry = getServiceDictEntries().find(item => String(item.id || '') === key)
return {
label: override?.label || getQuickDictLabel(entry?.item, code),
code: override?.code || code
key: override?.key || key,
label: override?.label || getQuickDictLabel(entry?.item, key),
id: override?.id || key
}
}
const createQuickOptionByMajorCode = (
code: string,
const createQuickOptionByMajorKey = (
key: string,
override?: Partial<QuickCalcOption> & { label?: string }
): QuickCalcOption => {
const entry = getMajorDictEntries().find(item => String(item.item?.code || '') === code)
const entry = getMajorDictEntries().find(item => String(item.id || '') === key)
return {
label: override?.label || getQuickDictLabel(entry?.item, code),
code: override?.code || code
key: override?.key || key,
label: override?.label || getQuickDictLabel(entry?.item, key),
id: override?.id || key
}
}
@ -719,28 +722,42 @@ export const getQuickCalcGroups = (): QuickCalcGroup[] => [
label: '咨询类别(常用)',
hint: '先选择咨询类别,再补规模和预算参数。',
items: [
createQuickOptionByServiceCode('D1'),
createQuickOptionByServiceCode('D2-1'),
createQuickOptionByServiceCode('D2-2-1', { code: { '0': 'D2-2-1', '1': 'D2-2-2', '2': 'D2-2-1' } }),
createQuickOptionByServiceCode('D3-1'),
createQuickOptionByServiceCode('D3-2'),
createQuickOptionByServiceCode('D3-3'),
createQuickOptionByServiceCode('D3-4'),
createQuickOptionByServiceCode('D3-5'),
createQuickOptionByServiceCode('D3-6-1', { code: { '0': 'D3-6-1', '1': 'D3-6-2', '2': 'D3-6-1' } }),
createQuickOptionByServiceCode('D3-7'),
createQuickOptionByServiceCode('D4-6'),
createQuickOptionByServiceCode('D4-7'),
createQuickOptionByServiceCode('D4-8'),
createQuickOptionByServiceCode('D4-9'),
createQuickOptionByServiceCode('D4-10'),
createQuickOptionByServiceCode('D4-11'),
createQuickOptionByServiceCode('D4-12')
createQuickOptionByServiceKey('0'),
createQuickOptionByServiceKey('2'),
createQuickOptionByServiceKey('3', {
key: 'D2-2',
id: {//行业不同显示的不同
'0': '3',
'1': '4',
'2': '3'
}
}),
createQuickOptionByServiceKey('6'),
createQuickOptionByServiceKey('7'),
createQuickOptionByServiceKey('8'),
createQuickOptionByServiceKey('9'),
createQuickOptionByServiceKey('10'),
createQuickOptionByServiceKey('11', {
key: 'D3-6',
id: {
'0': '11',
'1': '12',
'2': '11'
}
}),
createQuickOptionByServiceKey('13'),
createQuickOptionByServiceKey('20'),
createQuickOptionByServiceKey('21'),
createQuickOptionByServiceKey('22'),
createQuickOptionByServiceKey('23'),
createQuickOptionByServiceKey('24'),
createQuickOptionByServiceKey('25'),
createQuickOptionByServiceKey('26')
],
rows: [
['全过程造价咨询', '项目前期阶段造价咨询', '项目实施阶段造价咨询'],
['投资估算', '设计概算', '施工图预算', '招标工程量清单及清单预算(或最高投标限价)', '清理概算(仅限铁路)', '合同(工程)结算', '竣工决算'],
['造价鉴定', '工程成本测算', '工程成本核算', '计算工程量', '工程变更费用咨询', '调整估算', '调整概算']
['0', '2', 'D2-2'],
['6', '7', '8', '9', '10', 'D3-6', '13'],
['20', '21', '22', '23', '24', '25', '26']
]
},
{
@ -748,12 +765,12 @@ export const getQuickCalcGroups = (): QuickCalcGroup[] => [
label: '通用专业',
hint: '跨行业共用的补偿与其他费用专业。',
items: [
createQuickOptionByMajorCode('E1-1'),
createQuickOptionByMajorCode('E1-2'),
createQuickOptionByMajorCode('E1-3'),
createQuickOptionByMajorCode('E1-4')
createQuickOptionByMajorKey('1'),
createQuickOptionByMajorKey('2'),
createQuickOptionByMajorKey('3'),
createQuickOptionByMajorKey('4')
],
rows: [['征地(用海)补偿', '拆迁补偿', '迁改工程等费用', '工程建设其他费']]
rows: [['1', '2', '3', '4']]
},
{
key: 'road',
@ -761,22 +778,22 @@ export const getQuickCalcGroups = (): QuickCalcGroup[] => [
hint: '首页行业为公路工程时默认展示。',
industryId: '0',
items: [
createQuickOptionByMajorCode('E2'),
createQuickOptionByMajorCode('E2-1'),
createQuickOptionByMajorCode('E2-2'),
createQuickOptionByMajorCode('E2-3'),
createQuickOptionByMajorCode('E2-4'),
createQuickOptionByMajorCode('E2-5'),
createQuickOptionByMajorCode('E2-6'),
createQuickOptionByMajorCode('E2-7'),
createQuickOptionByMajorCode('E2-8'),
createQuickOptionByMajorCode('E2-9'),
createQuickOptionByMajorCode('E2-10')
createQuickOptionByMajorKey('7'),
createQuickOptionByMajorKey('8'),
createQuickOptionByMajorKey('9'),
createQuickOptionByMajorKey('10'),
createQuickOptionByMajorKey('11'),
createQuickOptionByMajorKey('12'),
createQuickOptionByMajorKey('13'),
createQuickOptionByMajorKey('14'),
createQuickOptionByMajorKey('15'),
createQuickOptionByMajorKey('16'),
createQuickOptionByMajorKey('17')
],
rows: [
['建设工程项目'],
['临时工程', '路基工程', '路面工程', '桥涵工程', '隧道工程', '交叉工程'],
['机电工程', '交通安全设施工程', '绿化及环境保护工程', '房建工程']
['7'],
['8', '9', '10', '11', '12', '13'],
['14', '15', '16', '17']
]
},
{
@ -785,21 +802,21 @@ export const getQuickCalcGroups = (): QuickCalcGroup[] => [
hint: '首页行业为铁路工程时默认展示。',
industryId: '1',
items: [
createQuickOptionByMajorCode('E3'),
createQuickOptionByMajorCode('E3-1'),
createQuickOptionByMajorCode('E3-2'),
createQuickOptionByMajorCode('E3-3'),
createQuickOptionByMajorCode('E3-4'),
createQuickOptionByMajorCode('E3-5'),
createQuickOptionByMajorCode('E3-6'),
createQuickOptionByMajorCode('E3-7'),
createQuickOptionByMajorCode('E3-8'),
createQuickOptionByMajorCode('E3-9')
createQuickOptionByMajorKey('18'),
createQuickOptionByMajorKey('19'),
createQuickOptionByMajorKey('20'),
createQuickOptionByMajorKey('21'),
createQuickOptionByMajorKey('22'),
createQuickOptionByMajorKey('23'),
createQuickOptionByMajorKey('24'),
createQuickOptionByMajorKey('25'),
createQuickOptionByMajorKey('26'),
createQuickOptionByMajorKey('27')
],
rows: [
['建设工程项目'],
['大型临时设施和过渡工程', '路基工程', '桥涵工程', '隧道及明洞工程', '轨道工程'],
['通信、信号、信息及灾害监测工程', '电力及电力牵引供电工程', '房建工程(房屋建筑及附属工程)', '装饰装修工程']
['18'],
['19', '20', '21', '22', '23'],
['24', '25', '26', '27']
]
},
{
@ -808,17 +825,17 @@ export const getQuickCalcGroups = (): QuickCalcGroup[] => [
hint: '首页行业为水运工程时默认展示。',
industryId: '2',
items: [
createQuickOptionByMajorCode('E4'),
createQuickOptionByMajorCode('E4-1'),
createQuickOptionByMajorCode('E4-2'),
createQuickOptionByMajorCode('E4-3'),
createQuickOptionByMajorCode('E4-4'),
createQuickOptionByMajorCode('E4-5', { label: '房建工程(房屋建筑及附属工程)' })
createQuickOptionByMajorKey('28'),
createQuickOptionByMajorKey('29'),
createQuickOptionByMajorKey('30'),
createQuickOptionByMajorKey('31'),
createQuickOptionByMajorKey('32'),
createQuickOptionByMajorKey('33', { label: '房建工程(房屋建筑及附属工程)' })
],
rows: [
['建设工程项目'],
['临时工程', '土建工程'],
['机电与金属结构工程', '设备工程', '房建工程(房屋建筑及附属工程)']
['28'],
['29', '30'],
['31', '32', '33']
]
}
]