| | |
| | | return val !== null && val !== undefined && val !== ''; |
| | | } |
| | | |
| | | function hasConfiguredDuration(val: any) { |
| | | if (!hasDisplayValue(val)) return false; |
| | | const raw = String(val).trim(); |
| | | if (!raw) return false; |
| | | const num = Number(raw); |
| | | return !(Number.isFinite(num) && num === 0); |
| | | } |
| | | |
| | | function buildMileageFeeText(price: any, includedKm: any) { |
| | | const formattedPrice = formatMoney(price); |
| | | if (!formattedPrice) return ''; |
| | | const suffix = hasDisplayValue(includedKm) ? `(超出${includedKm}公里后)` : ''; |
| | | return `${formattedPrice}元/公里${suffix}`; |
| | | } |
| | | |
| | | function buildDurationFeeText(price: any, includedMin: any) { |
| | | const formattedPrice = formatMoney(price); |
| | | if (!formattedPrice) return ''; |
| | | const suffix = hasConfiguredDuration(includedMin) ? `(超出${includedMin}分钟后)` : ''; |
| | | return `${formattedPrice}元/分钟${suffix}`; |
| | | } |
| | | |
| | | function resolvePricingType(raw: any) { |
| | | const num = Number(raw); |
| | | return Number.isFinite(num) ? num : 0; |
| | | } |
| | | |
| | | function buildFixedPriceDescription(includedKm: any, includedMin: any) { |
| | | const hasIncludedKm = hasDisplayValue(includedKm); |
| | | const hasIncludedMin = hasConfiguredDuration(includedMin); |
| | | const packageParts: string[] = []; |
| | | if (hasDisplayValue(includedKm)) { |
| | | if (hasIncludedKm) { |
| | | packageParts.push(`${includedKm}公里里程`); |
| | | } |
| | | if (hasDisplayValue(includedMin)) { |
| | | if (hasIncludedMin) { |
| | | packageParts.push(`${includedMin}分钟用车时长`); |
| | | } |
| | | const packageText = packageParts.length > 0 ? `套餐内含${packageParts.join('、')}` : '套餐内含基础用车额度'; |
| | | return `本车型为一口价计费,${packageText};正常行程不改目的地/路线按预估价结算;里程或用车时长任一超出套餐额度、或中途改目的地/大幅变更路线,超出部分单独叠加计费。`; |
| | | const overageText = hasIncludedKm && hasIncludedMin |
| | | ? '里程或用车时长任一超出套餐额度、或中途改目的地/大幅变更路线,超出部分单独叠加计费。' |
| | | : hasIncludedKm |
| | | ? '超出套餐内里程额度、或中途改目的地/大幅变更路线,超出部分单独叠加计费。' |
| | | : hasIncludedMin |
| | | ? '超出套餐内用车时长额度、或中途改目的地/大幅变更路线,超出部分单独叠加计费。' |
| | | : '超出套餐额度、或中途改目的地/大幅变更路线,超出部分单独叠加计费。'; |
| | | return `本车型为一口价计费,${packageText};正常行程不改目的地/路线按预估价结算;${overageText}`; |
| | | } |
| | | |
| | | function buildStartDescription(includedKm: any, includedMin: any) { |
| | | const hasIncludedKm = hasDisplayValue(includedKm); |
| | | const hasIncludedMin = hasConfiguredDuration(includedMin); |
| | | const parts: string[] = []; |
| | | if (hasDisplayValue(includedKm)) { |
| | | if (hasIncludedKm) { |
| | | parts.push(`包含里程${includedKm}公里`); |
| | | } |
| | | if (hasDisplayValue(includedMin)) { |
| | | if (hasIncludedMin) { |
| | | parts.push(`包含时长${includedMin}分钟`); |
| | | } |
| | | if (parts.length === 0) { |
| | | return '起步价内包含一定的基础里程或时长,超出后将在起步价基础上累加计费。'; |
| | | } |
| | | return `${parts.join(',')},包含里程或包含时长(低速时长)任何一项超出时,将在起步价基础上累加计费。`; |
| | | if (hasIncludedKm && hasIncludedMin) { |
| | | return `${parts.join(',')},包含里程或包含时长(低速时长)任何一项超出时,将在起步价基础上累加计费。`; |
| | | } |
| | | if (hasIncludedKm) { |
| | | return `${parts.join(',')},超出包含里程后,将在起步价基础上累加计费。`; |
| | | } |
| | | return `${parts.join(',')},超出包含时长(低速时长)后,将在起步价基础上累加计费。`; |
| | | } |
| | | |
| | | function PricingRulesPage() { |
| | |
| | | const baseIncludedMinRaw = isFixedPriceMode |
| | | ? fixedIncludedMinRaw |
| | | : (startingFareList?.[0]?.num5 ?? basicPricing?.num3); |
| | | const startTitleMeta = [hasDisplayValue(baseIncludedKmRaw) ? `${baseIncludedKmRaw}公里` : '', hasDisplayValue(baseIncludedMinRaw) ? `${baseIncludedMinRaw}分钟` : ''] |
| | | const startTitleMeta = [hasDisplayValue(baseIncludedKmRaw) ? `${baseIncludedKmRaw}公里` : '', hasConfiguredDuration(baseIncludedMinRaw) ? `${baseIncludedMinRaw}分钟` : ''] |
| | | .filter(Boolean) |
| | | .join(','); |
| | | |
| | |
| | | ? [ |
| | | { label: '一口价', value: fixedPackagePrice ? `${fixedPackagePrice}元` : '' }, |
| | | { label: '包含里程', value: hasDisplayValue(fixedIncludedKmRaw) ? `${fixedIncludedKmRaw}公里` : '' }, |
| | | { label: '包含时长', value: hasDisplayValue(fixedIncludedMinRaw) ? `${fixedIncludedMinRaw}分钟` : '' } |
| | | { label: '包含时长', value: hasConfiguredDuration(fixedIncludedMinRaw) ? `${fixedIncludedMinRaw}分钟` : '' } |
| | | ].filter(item => item.value) |
| | | : []; |
| | | |
| | |
| | | : (startingFareRows.length > 0 || Boolean(holidayStartFarePrice)); |
| | | |
| | | const baseIncludedKm = hasDisplayValue(baseIncludedKmRaw) ? String(baseIncludedKmRaw) : '-'; |
| | | const baseIncludedMin = hasDisplayValue(baseIncludedMinRaw) ? String(baseIncludedMinRaw) : '-'; |
| | | |
| | | const holidayMileageFeePrice = formatMoney(basicPricing?.num30); |
| | | const holidayMileageFeeText = holidayMileageFeePrice |
| | | ? `${holidayMileageFeePrice}元/公里(超出${baseIncludedKm}公里后)` |
| | | : ''; |
| | | const holidayMileageFeeText = buildMileageFeeText(holidayMileageFeePrice, baseIncludedKmRaw); |
| | | |
| | | const holidayDurationFeePrice = formatMoney(basicPricing?.num31); |
| | | const holidayDurationFeeText = holidayDurationFeePrice |
| | | ? `${holidayDurationFeePrice}元/分钟(超出${baseIncludedMin}分钟后)` |
| | | : ''; |
| | | const holidayDurationFeeText = buildDurationFeeText(basicPricing?.num31, baseIncludedMinRaw); |
| | | |
| | | const hasAnyDurationFee = |
| | | shouldRenderDynamicSections && |
| | |
| | | const name = index === 0 ? '普通时段' : `普通时段${index + 1}`; |
| | | const range = item?.num1 && item?.num2 ? `${padTime(item.num1)}-${padTime(item.num2)}` : ''; |
| | | const includedKm = item?.num4 ?? baseIncludedKm; |
| | | const price = formatMoney(item?.num6); |
| | | if (!price) return null; |
| | | const fee = buildMileageFeeText(item?.num6, includedKm); |
| | | if (!fee) return null; |
| | | return { |
| | | name, |
| | | time: range, |
| | | fee: `${price}元/公里(超出${includedKm}公里后)` |
| | | fee |
| | | }; |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | { |
| | | name: '夜间时段', |
| | | time: nightRange, |
| | | fee: `${formatMoney(basicPricing.num16)}元/公里(超出${baseIncludedKm}公里后)` |
| | | fee: buildMileageFeeText(basicPricing.num16, baseIncludedKmRaw) |
| | | } |
| | | ] |
| | | : []), |
| | |
| | | { |
| | | name: '早高峰时段', |
| | | time: peakRange1, |
| | | fee: `${formatMoney(basicPricing.num24)}元/公里(超出${baseIncludedKm}公里后)` |
| | | fee: buildMileageFeeText(basicPricing.num24, baseIncludedKmRaw) |
| | | } |
| | | ] |
| | | : []), |
| | |
| | | { |
| | | name: '晚高峰时段', |
| | | time: peakRange2, |
| | | fee: `${formatMoney(basicPricing.num24)}元/公里(超出${baseIncludedKm}公里后)` |
| | | fee: buildMileageFeeText(basicPricing.num24, baseIncludedKmRaw) |
| | | } |
| | | ] |
| | | : []), |
| | |
| | | if (!hasAnyDurationFee) return null; |
| | | const name = index === 0 ? '普通时段' : `普通时段${index + 1}`; |
| | | const range = item?.num1 && item?.num2 ? `${padTime(item.num1)}-${padTime(item.num2)}` : ''; |
| | | const includedMin = item?.num5 ?? baseIncludedMin; |
| | | const price = hasDisplayValue(item?.num7) ? formatMoney(item?.num7) : '0.00'; |
| | | if (!price) return null; |
| | | const includedMin = hasConfiguredDuration(item?.num5) ? item?.num5 : baseIncludedMinRaw; |
| | | const fee = buildDurationFeeText(item?.num7, includedMin); |
| | | if (!fee) return null; |
| | | return { |
| | | name, |
| | | time: range, |
| | | fee: `${price}元/分钟(超出${includedMin}分钟后)` |
| | | fee |
| | | }; |
| | | }) |
| | | .filter(Boolean) |
| | |
| | | { |
| | | name: '夜间时段', |
| | | time: nightRange, |
| | | fee: `${formatMoney(basicPricing.num17)}元/分钟(超出${baseIncludedMin}分钟后)` |
| | | fee: buildDurationFeeText(basicPricing.num17, baseIncludedMinRaw) |
| | | } |
| | | ] |
| | | : []), |
| | |
| | | { |
| | | name: '早高峰时段', |
| | | time: peakRange1, |
| | | fee: `${formatMoney(basicPricing.num25)}元/分钟(超出${baseIncludedMin}分钟后)` |
| | | fee: buildDurationFeeText(basicPricing.num25, baseIncludedMinRaw) |
| | | } |
| | | ] |
| | | : []), |
| | |
| | | { |
| | | name: '晚高峰时段', |
| | | time: peakRange2, |
| | | fee: `${formatMoney(basicPricing.num25)}元/分钟(超出${baseIncludedMin}分钟后)` |
| | | fee: buildDurationFeeText(basicPricing.num25, baseIncludedMinRaw) |
| | | } |
| | | ] |
| | | : []), |