docs(plan): 复核残留修订——exportListToCsv真实签名落地代码块/调度测试改相对日期
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -2625,10 +2625,17 @@ async def sched_engine():
|
||||
|
||||
|
||||
async def test_analytics_tick_runs(sched_engine):
|
||||
# _analytics_tick 用真实「今天」算滚动窗——seed 的 day 必须相对当日,
|
||||
# 固定 20260904 会在三天后过期(评审残留#2 修正)
|
||||
import datetime as dt
|
||||
|
||||
from app.storage.summary import day_key
|
||||
|
||||
engine, maker = sched_engine
|
||||
today = day_key(int(dt.datetime.now().timestamp() * 1000))
|
||||
async with maker() as s:
|
||||
s.add(MsgDailyStats(channel="wechat", owner_account_id="wx1",
|
||||
peer_kind="friend", peer_id="t1", day=20260904,
|
||||
peer_kind="friend", peer_id="t1", day=today,
|
||||
send_cnt=1, recv_cnt=0, last_ts=1756950000000,
|
||||
last_is_send=True))
|
||||
s.add(SensitiveWord(word="私单"))
|
||||
@@ -3061,7 +3068,7 @@ onMounted(load)
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getChurn, type Channel, type ChurnRow } from '@/api/analytics'
|
||||
import { exportRowsCsv } from '@/utils/csvExport' // 路径以项目实际为准(grep csvExport)
|
||||
import { exportListToCsv } from '@/utils/csvExport'
|
||||
|
||||
const router = useRouter()
|
||||
const channel = ref<Channel>('wechat')
|
||||
@@ -3105,20 +3112,26 @@ function goChat(row: ChurnRow) {
|
||||
async function exportCsv() {
|
||||
exporting.value = true
|
||||
try {
|
||||
const all: ChurnRow[] = []
|
||||
for (let p = 1; ; p++) {
|
||||
const out = await getChurn({
|
||||
await exportListToCsv<ChurnRow>({
|
||||
fetchPage: (page, pageSize) => getChurn({
|
||||
channel: channel.value, type: kind.value, tier: tier.value,
|
||||
min_msgs: 5, page: p, page_size: 100,
|
||||
})
|
||||
all.push(...out.items)
|
||||
if (all.length >= out.total || out.items.length === 0) break
|
||||
}
|
||||
exportRowsCsv(all.map((r) => ({
|
||||
客户: r.nickname, 渠道: r.channel, 归属员工: r.owner_account_id ?? '',
|
||||
最后沟通: r.last_chat_time ? new Date(r.last_chat_time).toLocaleString('zh-CN', { hour12: false }) : '',
|
||||
历史消息量: r.hist_msgs, 活跃天数: r.active_days,
|
||||
})), `流失预警_${kind.value}_${channel.value}.csv`)
|
||||
min_msgs: 5, page, page_size: pageSize,
|
||||
}),
|
||||
columns: [
|
||||
{ key: 'nickname', label: '客户' },
|
||||
{ key: 'channel', label: '渠道' },
|
||||
{ key: 'owner_account_id', label: '归属员工' },
|
||||
{
|
||||
key: 'last_chat_time', label: '最后沟通',
|
||||
format: (r) => (r.last_chat_time
|
||||
? new Date(r.last_chat_time).toLocaleString('zh-CN', { hour12: false })
|
||||
: '从未沟通'),
|
||||
},
|
||||
{ key: 'hist_msgs', label: '历史消息量' },
|
||||
{ key: 'active_days', label: '活跃天数' },
|
||||
],
|
||||
filename: `流失预警_${kind.value}_${channel.value}`,
|
||||
}) // 工具自带翻页+BOM+10000 行 cap
|
||||
} finally {
|
||||
exporting.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user