From 78962e45d7c2044de6d652fcc95de34e7698c9bd Mon Sep 17 00:00:00 2001 From: v6ole Date: Sun, 12 Jul 2026 20:42:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E5=8A=A8=E7=AB=AF=E5=95=86?= =?UTF-8?q?=E6=9C=BA=E8=B7=9F=E5=8D=95=E6=96=B0=E5=A2=9E=E8=B7=9F=E8=BF=9B?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=97=B6=E9=97=B4=E7=BA=BF+=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 编辑模式下表单底部显示跟进时间线 + 新增跟进入口 与PC端一致的体验:方式chip选择 + 日期 + 内容 Co-Authored-By: Claude --- .../src/views/mobile/MiniBusinessForm.vue | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/frontend/src/views/mobile/MiniBusinessForm.vue b/frontend/src/views/mobile/MiniBusinessForm.vue index 0264fb2..0fcbe54 100644 --- a/frontend/src/views/mobile/MiniBusinessForm.vue +++ b/frontend/src/views/mobile/MiniBusinessForm.vue @@ -39,6 +39,7 @@ onMounted(async () => { } form.value = { customer_id: d.customer_id, product_type: d.product_type, amount: d.amount, follow_up_detail: d.follow_up_detail || '', status: d.status, expected_revenue_date: d.expected_revenue_date, manager_id: d.manager_id } } catch (_) {} + loadLogs() } }) @@ -100,6 +101,45 @@ async function handleDelete() { router.push('/m/mini-biz') } catch (e: any) { if (e !== 'cancel') ElMessage.error('删除失败') } } + +// ── Follow-up logs ── +const logs = ref([]) +const logForm = ref({ log_date: '', method: '电话', content: '' }) +const logMethods = ['电话', '微信', '上门', '邮件', '其他'] +const logMethodIcons: Record = { '电话': '📞', '微信': '💬', '上门': '🏢', '邮件': '📧', '其他': '📋' } +const logMethodColors: Record = { '电话': '#5B7FA5', '微信': '#22c55e', '上门': '#4A6741', '邮件': '#C4934A', '其他': '#7B7568' } +const logLoading = ref(false) +const logSaving = ref(false) + +async function loadLogs() { + logLoading.value = true + try { + const res = await miniBusinessApi.getLogs(route.params.id as string) + logs.value = res.data || [] + } catch (_) { logs.value = [] } + finally { logLoading.value = false } +} + +async function handleCreateLog() { + if (!logForm.value.content.trim()) { ElMessage.warning('请输入跟进内容'); return } + logSaving.value = true + try { + await miniBusinessApi.createLog(route.params.id as string, logForm.value) + ElMessage.success('跟进记录已添加') + logForm.value = { log_date: new Date().toISOString().slice(0, 10), method: '电话', content: '' } + await loadLogs() + } catch (e: any) { ElMessage.error('添加失败: ' + (e.response?.data?.detail || e.message)) } + finally { logSaving.value = false } +} + +async function handleDeleteLog(logId: string) { + try { + await ElMessageBox.confirm('确定删除该跟进记录?', '确认', { type: 'warning' }) + await miniBusinessApi.deleteLog(logId) + ElMessage.success('已删除') + await loadLogs() + } catch (e: any) { if (e !== 'cancel') ElMessage.error('删除失败') } +} @@ -258,4 +329,31 @@ async function handleDelete() { .btn-loading { width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.3); border-top-color: #fff; border-radius: 50%; animation: spin 0.6s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .required-star { color: var(--vermilion); font-weight: 700; } + +/* ── Follow-up Log Section ── */ +.log-section { margin-top: 20px; border-top: 1px solid var(--warm-border); padding-top: 16px; } +.section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; } +.section-title { font-family: var(--font-heading); font-size: 18px; color: var(--ink); letter-spacing: 0.06em; white-space: nowrap; } +.section-line { flex: 1; height: 2px; background: var(--gold); } +.log-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; max-height: 260px; overflow-y: auto; } +.log-empty { text-align: center; color: var(--warm-gray); font-size: 13px; padding: 16px 0; } +.log-item { display: flex; gap: 8px; align-items: flex-start; padding: 10px; background: var(--surface); border: 1px solid var(--warm-border); } +.log-icon { font-size: 16px; flex-shrink: 0; margin-top: 2px; } +.log-body { flex: 1; min-width: 0; } +.log-header { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; } +.log-date { font-family: var(--font-mono); font-size: 12px; color: var(--ink); } +.log-author { font-size: 11px; color: var(--warm-gray); margin-left: auto; } +.log-content { font-size: 13px; color: var(--c-text); line-height: 1.5; } +.log-del { flex-shrink: 0; background: none; border: none; color: var(--warm-gray); cursor: pointer; font-size: 14px; padding: 2px; } +.log-del:hover { color: var(--vermilion); } +.log-chip { border-radius: 2px; white-space: nowrap; } +.log-add { border-top: 1px solid var(--warm-border); padding-top: 12px; } +.log-add-row { display: flex; gap: 6px; align-items: center; } +.log-chips { display: flex; gap: 3px; } +.log-chip-btn { padding: 4px 8px; border: 1px solid var(--warm-border); background: var(--surface); font-size: 11px; cursor: pointer; transition: all 0.2s; } +.log-chip-btn:hover { border-color: var(--ink); } +.log-chip-btn--active { font-weight: 600; } +.log-submit { width: 100%; margin-top: 8px; padding: 10px; background: var(--ink); color: #fff; border: none; font-family: var(--font-heading); font-size: 14px; letter-spacing: 0.06em; cursor: pointer; } +.log-submit:hover { background: var(--ink-light); } +.log-submit:disabled { opacity: 0.6; cursor: not-allowed; }