184 lines
8.2 KiB
JavaScript
184 lines
8.2 KiB
JavaScript
import PizZip from 'pizzip'
|
|
import Docxtemplater from 'docxtemplater'
|
|
import { saveAs } from 'file-saver'
|
|
import {
|
|
formatNumberValue,
|
|
formatThreeYearIncome,
|
|
formatAgeDistribution,
|
|
formatHistoricalEvidence,
|
|
formatPlatformAccounts,
|
|
formatPriceRange
|
|
} from '@/views/valuation/audit/utils'
|
|
|
|
export const generateReport = async (detailData) => {
|
|
try {
|
|
// Validate input
|
|
if (!detailData || typeof detailData !== 'object') {
|
|
throw new Error('无效的详情数据')
|
|
}
|
|
|
|
// Load the template
|
|
const response = await fetch('/report_template.docx')
|
|
if (!response.ok) {
|
|
throw new Error('Failed to load report template')
|
|
}
|
|
const content = await response.arrayBuffer()
|
|
|
|
const zip = new PizZip(content)
|
|
const doc = new Docxtemplater(zip, {
|
|
paragraphLoop: true,
|
|
linebreaks: true,
|
|
delimiters: { start: '${', end: '}' },
|
|
// 当字段不存在时,保持原始的 ${字段名} 格式,不替换
|
|
nullGetter: (part) => {
|
|
if (!part.module) {
|
|
return '${' + part.value + '}'
|
|
}
|
|
return ''
|
|
},
|
|
})
|
|
|
|
// Helper function to safely add field only if it exists
|
|
const addIfExists = (obj, key, value) => {
|
|
if (value !== undefined && value !== null) {
|
|
obj[key] = value
|
|
}
|
|
}
|
|
|
|
// Extract calculation data
|
|
const calcInput = detailData.calculation_input || {}
|
|
const calcResult = detailData.calculation_result || {}
|
|
const modelData = calcInput.model_data || {}
|
|
const ecoData = modelData.economic_data || {}
|
|
const cultData = modelData.cultural_data || {}
|
|
const riskData = modelData.risky_data || {}
|
|
const marketData = calcInput.market_data || {}
|
|
|
|
// Prepare data - only include fields that actually exist
|
|
const data = {
|
|
// Spread all existing detailData fields
|
|
...detailData,
|
|
|
|
// Date fields (always generated)
|
|
yyyy: new Date().getFullYear(),
|
|
mm: String(new Date().getMonth() + 1).padStart(2, '0'),
|
|
dd: String(new Date().getDate()).padStart(2, '0'),
|
|
yyyymmdd: `${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}`,
|
|
}
|
|
|
|
// Handle inheritor_age_count array - format each item
|
|
if (detailData.inheritor_age_count && Array.isArray(detailData.inheritor_age_count)) {
|
|
const ageData = formatAgeDistribution(detailData.inheritor_age_count)
|
|
// 提供格式化后的完整文本
|
|
data.inheritor_age_count_text = ageData.join('\n')
|
|
// 提供单独的数值,支持 ${inheritor_age_count[0]} 这样的用法
|
|
if (detailData.inheritor_age_count[0] !== undefined) {
|
|
data['inheritor_age_count[0]'] = detailData.inheritor_age_count[0]
|
|
}
|
|
if (detailData.inheritor_age_count[1] !== undefined) {
|
|
data['inheritor_age_count[1]'] = detailData.inheritor_age_count[1]
|
|
}
|
|
if (detailData.inheritor_age_count[2] !== undefined) {
|
|
data['inheritor_age_count[2]'] = detailData.inheritor_age_count[2]
|
|
}
|
|
}
|
|
|
|
// Handle historical_evidence object - format as text
|
|
if (detailData.historical_evidence && typeof detailData.historical_evidence === 'object') {
|
|
const evidenceData = formatHistoricalEvidence(detailData.historical_evidence)
|
|
// 提供格式化后的完整文本(换行分隔)
|
|
data.historical_evidence = evidenceData.join('\n')
|
|
}
|
|
|
|
// Handle platform_accounts object - format as text
|
|
if (detailData.platform_accounts && typeof detailData.platform_accounts === 'object') {
|
|
const accountsData = formatPlatformAccounts(detailData.platform_accounts)
|
|
// 提供格式化后的完整文本(换行分隔)
|
|
data.platform_accounts = accountsData.join('\n')
|
|
}
|
|
|
|
// Handle price_fluctuation array
|
|
if (detailData.price_fluctuation && Array.isArray(detailData.price_fluctuation)) {
|
|
const min = detailData.price_fluctuation[0]
|
|
const max = detailData.price_fluctuation[1]
|
|
|
|
// 提供单独的数值,支持 ${price_fluctuation[0]} 这样的用法
|
|
if (min !== undefined) {
|
|
data['price_fluctuation[0]'] = min
|
|
data.price_min = min
|
|
}
|
|
if (max !== undefined) {
|
|
data['price_fluctuation[1]'] = max
|
|
data.price_max = max
|
|
}
|
|
|
|
// 提供多种格式的范围文本
|
|
if (min !== undefined && max !== undefined) {
|
|
// 简单范围(数字-数字)
|
|
data.price_range = `${min}-${max}`
|
|
// 带"元"的范围
|
|
data.price_range_yuan = `${min}-${max}元`
|
|
// 带货币符号的范围
|
|
data.price_fluctuation_range = formatPriceRange(detailData.price_fluctuation)
|
|
// 精确匹配模板中的字段名(作为一个整体的字段名)
|
|
data['price_fluctuation[0]-price_fluctuation[1]'] = `${min}-${max}`
|
|
}
|
|
}
|
|
|
|
// Add calculation results if they exist
|
|
if (calcResult.model_value_b !== undefined) data.B = formatNumberValue(calcResult.model_value_b)
|
|
if (calcResult.economic_value_b1 !== undefined) data.B1 = formatNumberValue(calcResult.economic_value_b1)
|
|
if (calcResult.cultural_value_b2 !== undefined) data.B2 = formatNumberValue(calcResult.cultural_value_b2)
|
|
if (calcResult.risk_adjustment_b3 !== undefined) data.B3 = calcResult.risk_adjustment_b3
|
|
if (calcResult.market_value_c !== undefined) data.C = formatNumberValue(calcResult.market_value_c)
|
|
|
|
// Add DPR if exists
|
|
const dpr = detailData.drp_result?.dynamic_pledge_rate || detailData.dynamic_pledge_rate
|
|
if (dpr !== undefined) data.DPR = dpr
|
|
|
|
// Add economic data fields if they exist
|
|
if (ecoData.basic_value_b11 !== undefined) data.B11 = formatNumberValue(ecoData.basic_value_b11)
|
|
if (ecoData.financial_value !== undefined) data.F = formatNumberValue(ecoData.financial_value)
|
|
if (ecoData.legal_strength !== undefined) data.L = ecoData.legal_strength
|
|
if (ecoData.development_potential !== undefined) data.D = ecoData.development_potential
|
|
if (ecoData.traffic_factor_b12 !== undefined) data.B12 = ecoData.traffic_factor_b12
|
|
if (ecoData.search_index_s1 !== undefined) data.search_index_ratio = ecoData.search_index_s1
|
|
if (ecoData.social_media_spread_s3 !== undefined) data.S3 = ecoData.social_media_spread_s3
|
|
if (ecoData.policy_multiplier_b13 !== undefined) data.B13 = ecoData.policy_multiplier_b13
|
|
if (ecoData.policy_compatibility_score !== undefined) data.policy_fit_score = ecoData.policy_compatibility_score
|
|
|
|
// Add cultural data fields if they exist
|
|
if (cultData.living_inheritance_b21 !== undefined) data.B21 = cultData.living_inheritance_b21
|
|
if (cultData.inheritor_level_coefficient !== undefined) data.inheritor_level_score = cultData.inheritor_level_coefficient
|
|
if (cultData.teaching_frequency !== undefined) data.teaching_frequency_score = cultData.teaching_frequency
|
|
if (cultData.cross_border_depth !== undefined) data.cooperation_depth_score = cultData.cross_border_depth
|
|
if (cultData.pattern_entropy_b22 !== undefined) data.B22 = cultData.pattern_entropy_b22
|
|
if (cultData.structure_complexity !== undefined) data.SC = cultData.structure_complexity
|
|
if (cultData.normalized_entropy !== undefined) data.H = cultData.normalized_entropy
|
|
if (cultData.historical_inheritance !== undefined) data.HI = cultData.historical_inheritance
|
|
|
|
// Add risk data fields if they exist
|
|
if (riskData.risk_market !== undefined) data.risk_market = riskData.risk_market
|
|
if (riskData.risk_legal !== undefined) data.risk_legal = riskData.risk_legal
|
|
if (riskData.risk_inheritance !== undefined) data.risk_inheritance = riskData.risk_inheritance
|
|
|
|
// Add market data fields if they exist
|
|
if (marketData.market_bidding_c1 !== undefined) data.C1 = formatNumberValue(marketData.market_bidding_c1)
|
|
if (marketData.heat_coefficient_c2 !== undefined) data.C2 = marketData.heat_coefficient_c2
|
|
if (marketData.scarcity_multiplier_c3 !== undefined) data.C3 = marketData.scarcity_multiplier_c3
|
|
if (marketData.time_decay_c4 !== undefined) data.C4 = marketData.time_decay_c4
|
|
|
|
doc.render(data)
|
|
|
|
const out = doc.getZip().generate({
|
|
type: 'blob',
|
|
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
})
|
|
|
|
saveAs(out, `${detailData.asset_name || '评估报告'}.docx`)
|
|
} catch (error) {
|
|
console.error('Report generation failed:', error)
|
|
throw error
|
|
}
|
|
}
|