diff --git a/my-vue-app/src/api/secondTop.js b/my-vue-app/src/api/secondTop.js index 7c96c32..826cf78 100644 --- a/my-vue-app/src/api/secondTop.js +++ b/my-vue-app/src/api/secondTop.js @@ -87,7 +87,7 @@ export const cancelSwitchHistoryCampPeriod = (params) => { // 一键导出 api/v1/level_four/overview/export_customers export const exportCustomers = (params) => { - return https.post('/api/v1/level_four/overview/export_customers', params) + return https.post('/api/v1/level_four/overview/export_all_customers_under_sales', params) } diff --git a/my-vue-app/src/views/secondTop/components/ProblemRanking.vue b/my-vue-app/src/views/secondTop/components/ProblemRanking.vue index d950518..62a7759 100644 --- a/my-vue-app/src/views/secondTop/components/ProblemRanking.vue +++ b/my-vue-app/src/views/secondTop/components/ProblemRanking.vue @@ -90,12 +90,14 @@ async function exportData() { try { ElMessage.info('正在导出数据,请稍候...') console.log('导出参数:', params) - const res = await exportCustomers(params) + const res = await exportCustomers() if (res.code === 200 && res.data && res.data.length > 0) { + ElMessage.success('数据导出成功') // 处理数据,将复杂的嵌套对象展平 const exportData = res.data.map(customer => { const flatData = { '昵称': customer.nickname || '', + '客户姓名': customer.customer_name || '', '性别': customer.gender || '', '跟进人': customer.follow_up_name || '', '手机号': customer.phone || '', @@ -103,18 +105,104 @@ async function exportData() { '用户ID': customer.mantis_user_id || '', } - // 处理微信表单信息 - if (customer.wechat_form) { - flatData['家长姓名'] = customer.wechat_form.name || '' - flatData['孩子姓名'] = customer.wechat_form.child_name || '' - flatData['孩子性别'] = customer.wechat_form.child_gender || '' - flatData['职业'] = customer.wechat_form.occupation || '' - flatData['孩子教育阶段'] = customer.wechat_form.child_education || '' - flatData['与孩子关系'] = customer.wechat_form.child_relation || '' - flatData['联系电话'] = customer.wechat_form.mobile || '' - flatData['地区'] = customer.wechat_form.territory || '' - flatData['创建时间'] = customer.wechat_form.created_at ? new Date(customer.wechat_form.created_at).toLocaleString() : '' - flatData['更新时间'] = customer.wechat_form.updated_at ? new Date(customer.wechat_form.updated_at).toLocaleString() : '' + const parseFormData = (formData) => { + if (typeof formData === 'string') { + try { + return JSON.parse(formData) + } catch (e) { + return null + } + } + return formData || null + } + + const normalizeFormArray = (formData) => { + const data = parseFormData(formData) + console.log('解析后的表单数据:', data) + if (Array.isArray(data)) return data + if (data && Array.isArray(data.data)) return data.data + if (data && typeof data === 'object' && !data.answers) { + const numericKeys = Object.keys(data).filter(key => String(Number(key)) === key) + if (numericKeys.length > 0) { + return numericKeys + .sort((a, b) => Number(a) - Number(b)) + .map(key => data[key]) + .filter(Boolean) + } + } + if (data && data.answers) return [data] + return data ? [data] : [] + } + + const ensureUniqueKey = (key) => { + if (!flatData[key]) return key + let index = 2 + while (flatData[`${key}(${index})`]) { + index += 1 + } + return `${key}(${index})` + } + + const parsedFormData = parseFormData(customer.wechat_form) + const formArray = normalizeFormArray(parsedFormData) + if (formArray.length > 0) { + console.log('表单数组:', formArray) + const isAnswerList = formArray.every(item => item && item.question_label && Object.prototype.hasOwnProperty.call(item, 'answer')) + const isFormWithAnswers = formArray.every(item => item && Array.isArray(item.answers)) + console.log('是否为答案列表:', isAnswerList) + console.log('是否为表单含 answers:', isFormWithAnswers) + if (isAnswerList) { + let formAnswerCount = 0 + formArray.forEach((answerItem) => { + const label = String(answerItem.question_label || '').trim() + if (!label) return + const key = ensureUniqueKey(label) + flatData[key] = answerItem.answer ?? '' + formAnswerCount += 1 + }) + if (formAnswerCount === 0 && formArray.length > 0) { + const fallbackKey = ensureUniqueKey('表单答案') + flatData[fallbackKey] = formArray.map(item => `${item.question_label || ''}: ${item.answer || ''}`).join(' | ') + } + } else if (isFormWithAnswers) { + console.log('表单含 answers:', formArray) + formArray.forEach((formItem) => { + const formTitle = formItem.form_title || '表单' + if (Array.isArray(formItem.answers)) { + let formAnswerCount = 0 + formItem.answers.forEach((answerItem) => { + const label = String(answerItem.question_label || '').trim() + if (!label) return + const key = ensureUniqueKey(`${formTitle}-${label}`) + flatData[key] = answerItem.answer ?? '' + formAnswerCount += 1 + }) + if (formAnswerCount === 0 && formItem.answers.length > 0) { + const fallbackKey = ensureUniqueKey(`${formTitle}-表单答案`) + flatData[fallbackKey] = formItem.answers.map(item => `${item.question_label || ''}: ${item.answer || ''}`).join(' | ') + } + } + if (formItem.created_at) { + const key = ensureUniqueKey(`${formTitle}-创建时间`) + flatData[key] = new Date(formItem.created_at).toLocaleString() + } + if (formItem.updated_at) { + const key = ensureUniqueKey(`${formTitle}-更新时间`) + flatData[key] = new Date(formItem.updated_at).toLocaleString() + } + }) + } + } else if (parsedFormData && typeof parsedFormData === 'object') { + flatData['家长姓名'] = parsedFormData.name || '' + flatData['孩子姓名'] = parsedFormData.child_name || '' + flatData['孩子性别'] = parsedFormData.child_gender || '' + flatData['职业'] = parsedFormData.occupation || '' + flatData['孩子教育阶段'] = parsedFormData.child_education || '' + flatData['与孩子关系'] = parsedFormData.child_relation || '' + flatData['联系电话'] = parsedFormData.mobile || '' + flatData['地区'] = parsedFormData.territory || '' + flatData['创建时间'] = parsedFormData.created_at ? new Date(parsedFormData.created_at).toLocaleString() : '' + flatData['更新时间'] = parsedFormData.updated_at ? new Date(parsedFormData.updated_at).toLocaleString() : '' } // 处理到课情况 @@ -126,9 +214,12 @@ async function exportData() { } // 处理问卷调查信息 - if (customer.wechat_form && customer.wechat_form.additional_info) { - customer.wechat_form.additional_info.forEach((item) => { - flatData[item.topic || ''] = item.answer || '' + if (parsedFormData && parsedFormData.additional_info) { + parsedFormData.additional_info.forEach((item) => { + const key = ensureUniqueKey(item.topic || '') + if (key) { + flatData[key] = item.answer || '' + } }) } @@ -137,27 +228,18 @@ async function exportData() { // 创建工作簿 const wb = XLSX.utils.book_new() - const ws = XLSX.utils.json_to_sheet(exportData) + const allKeys = Array.from(new Set(exportData.flatMap(item => Object.keys(item)))) + const ws = XLSX.utils.json_to_sheet(exportData, { header: allKeys }) // 设置列宽 - const colWidths = [ - { wch: 10 }, // 昵称 - { wch: 6 }, // 性别 - { wch: 12 }, // 跟进人 - { wch: 15 }, // 手机号 - { wch: 10 }, // 是否入群 - { wch: 20 }, // 用户ID - { wch: 12 }, // 家长姓名 - { wch: 12 }, // 孩子姓名 - { wch: 8 }, // 孩子性别 - { wch: 12 }, // 职业 - { wch: 12 }, // 孩子教育阶段 - { wch: 15 }, // 与孩子关系 - { wch: 15 }, // 联系电话 - { wch: 20 }, // 地区 - { wch: 20 }, // 创建时间 - { wch: 20 }, // 更新时间 - ] + const colWidths = allKeys.map(key => { + const maxCellLength = exportData.reduce((max, row) => { + const value = row[key] + const length = value === null || value === undefined ? 0 : String(value).length + return Math.max(max, length) + }, 0) + return { wch: Math.min(50, Math.max(10, key.length, maxCellLength)) } + }) ws['!cols'] = colWidths // 添加工作表到工作簿 @@ -356,4 +438,4 @@ async function exportData() { color: #909399; font-size: 16px; } - \ No newline at end of file +