feat(ui): 所有列表页加CSV导出按钮(全量拉取+中文BOM兼容Excel)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
浅念
2026-08-15 10:31:21 +08:00
parent 9bec4dd7c8
commit edd6a27371
6 changed files with 327 additions and 11 deletions
+44
View File
@@ -2,12 +2,14 @@
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Download } from '@element-plus/icons-vue'
import { getCustomers } from '@/api'
import { downloadBlob } from '@/api/client'
import type { Channel, Customer } from '@/api/types'
import { useChannelStore } from '@/stores/channel'
import { useOrgStore } from '@/stores/org'
import { channelLabel, formatTime } from '@/utils/format'
import { exportListToCsv } from '@/utils/csvExport'
import { buildCustomerSections, fromTypeLabel, readField } from '@/utils/customerFields'
/**
@@ -205,6 +207,45 @@ async function confirmExport(): Promise<void> {
}
}
// ---- header 导出:当前 tab 渠道全量客户 CSV(含当前部门/员工筛选) ----
const exporting = ref(false)
async function exportCustomers(): Promise<void> {
const channel = activeTab.value // 'wechat' | 'whatsapp'
if (tabState[channel].total === 0) {
ElMessage.warning('当前列表为空,无数据可导出')
return
}
exporting.value = true
try {
const result = await exportListToCsv({
fetchPage: (page, pageSize) =>
getCustomers({
channel,
department_id: departmentId.value ?? undefined,
owner_account_id: ownerId.value ?? undefined,
page,
page_size: pageSize,
}),
columns: [
{ key: 'friend_nickname', label: '客户昵称' },
{ key: 'friend_id', label: '客户微信号' },
{ key: 'friend_remark', label: '备注名' },
{ key: 'real_name', label: '姓名' },
{ key: 'phone', label: '手机号' },
{ key: 'owner_account_id', label: '归属员工' },
{ key: 'last_chat_time', label: '最近沟通时间', format: (r) => (r.last_chat_time ? formatTime(r.last_chat_time) : '') },
],
filename: `${channel === 'wechat' ? '微信客户' : 'WA客户'}列表`,
})
ElMessage.success(`已导出 ${result.rows} 条`)
} catch (e) {
ElMessage.error(`导出失败:${(e as Error).message}`)
} finally {
exporting.value = false
}
}
/** 清除 owner_account_id query(保留其余 query)。 */
function clearOwnerFilter(): void {
const { owner_account_id: _drop, ...rest } = route.query
@@ -272,6 +313,9 @@ onMounted(() => {
</span>
</div>
<div class="yk-customers__filters">
<el-button size="small" :loading="exporting" @click="exportCustomers">
<el-icon><Download /></el-icon> 导出
</el-button>
<el-button
v-if="departmentId"
size="small"