feat: integrate WhatsApp send into customer detail with AI reply generation

This commit is contained in:
TradeMate Dev
2026-05-17 09:52:26 +08:00
parent 74a971cd6e
commit f33d33f980
2 changed files with 128 additions and 1 deletions
+123 -1
View File
@@ -246,6 +246,19 @@
<view class="detail-footer"> <view class="detail-footer">
<button class="close-btn" @click="showDetailModal = false">关闭</button> <button class="close-btn" @click="showDetailModal = false">关闭</button>
</view> </view>
<view class="whatsapp-section" v-if="currentCustomer.whatsapp_id">
<view class="whatsapp-header">
<text class="whatsapp-title">📱 WhatsApp 快捷发送</text>
</view>
<view class="whatsapp-input-row">
<input class="whatsapp-input" v-model="whatsappText" placeholder="输入消息内容,或点击AI生成" />
<view class="whatsapp-actions">
<view class="wa-btn ai-btn" @click="generateWhatsAppReply">AI生成</view>
<view class="wa-btn send-btn" @click="sendWhatsApp">发送</view>
</view>
</view>
</view>
</view> </view>
</view> </view>
@@ -273,7 +286,7 @@
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
import { onShow } from '@dcloudio/uni-app' import { onShow } from '@dcloudio/uni-app'
import { customerApi, healthApi, silentPatternApi } from '@/utils/api.js' import { customerApi, healthApi, silentPatternApi, whatsappApi, translateApi } from '@/utils/api.js'
const filter = ref('all') const filter = ref('all')
const customers = ref([]) const customers = ref([])
@@ -287,6 +300,7 @@ const conversationCustomer = ref(null)
const conversation = ref([]) const conversation = ref([])
const healthOverview = ref(null) const healthOverview = ref(null)
const healthScores = ref({}) const healthScores = ref({})
const whatsappText = ref('')
const formData = ref({ const formData = ref({
name: '', name: '',
company: '', company: '',
@@ -488,6 +502,55 @@ const importCustomers = () => {
}) })
} }
const generateWhatsAppReply = async () => {
if (!currentCustomer.value?.whatsapp_id) return
const lastMsg = conversation.value.length > 0 ? conversation.value[conversation.value.length - 1].content : ''
if (!lastMsg) {
whatsappText.value = 'Hello, any update on this?'
return
}
try {
uni.showLoading({ title: 'AI生成中...' })
const res = await translateApi.getReply(lastMsg, 'professional', 1)
uni.hideLoading()
if (res.suggestions && res.suggestions[0]) {
whatsappText.value = res.suggestions[0].content || res.suggestions[0]
}
} catch {
uni.hideLoading()
whatsappText.value = 'Hello, any update on this?'
}
}
const sendWhatsApp = async () => {
if (!whatsappText.value || !currentCustomer.value?.whatsapp_id) {
uni.showToast({ title: '请输入消息内容', icon: 'none' })
return
}
try {
uni.showLoading({ title: '发送中...' })
await whatsappApi.send(currentCustomer.value.whatsapp_id, whatsappText.value)
uni.hideLoading()
uni.showToast({ title: '已发送', icon: 'success' })
const msg = whatsappText.value
whatsappText.value = ''
showConversation(currentCustomer.value)
} catch (err) {
uni.hideLoading()
const phone = currentCustomer.value.whatsapp_id.replace(/[^0-9]/g, '')
uni.showModal({
title: 'API发送失败',
content: '是否通过 WhatsApp 链接发送?',
success: (r) => {
if (r.confirm) {
uni.setClipboardData({ data: msg })
uni.setClipboardData({ data: `https://wa.me/${phone}?text=${encodeURIComponent(whatsappText.value || msg)}` })
}
},
})
}
}
const deleteCustomer = async (id) => { const deleteCustomer = async (id) => {
uni.showModal({ uni.showModal({
title: '确认删除', title: '确认删除',
@@ -1089,4 +1152,63 @@ const deleteCustomer = async (id) => {
color: #999; color: #999;
padding: 60rpx; padding: 60rpx;
} }
.whatsapp-section {
margin-top: 20rpx;
padding: 20rpx;
background: #f0f5ff;
border-radius: 12rpx;
}
.whatsapp-header {
margin-bottom: 12rpx;
}
.whatsapp-title {
font-size: 26rpx;
font-weight: 600;
color: #1890ff;
}
.whatsapp-input-row {
display: flex;
flex-direction: column;
gap: 12rpx;
}
.whatsapp-input {
width: 100%;
height: 72rpx;
background: #fff;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 26rpx;
border: 2rpx solid #d6e4ff;
}
.whatsapp-actions {
display: flex;
gap: 16rpx;
}
.wa-btn {
flex: 1;
height: 64rpx;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 26rpx;
}
.ai-btn {
background: #fff;
color: #1890ff;
border: 2rpx solid #1890ff;
}
.send-btn {
background: #25d366;
color: #fff;
}
</style> </style>
+5
View File
@@ -242,6 +242,11 @@ export const healthApi = {
customerHealth: (id) => request(`/customers/${id}/health`), customerHealth: (id) => request(`/customers/${id}/health`),
} }
export const whatsappApi = {
send: (to, text, templateName = null, templateParams = null, mediaUrl = null, mediaType = null) =>
request('/whatsapp/send', 'POST', { to, text, template_name: templateName, template_params: templateParams, media_url: mediaUrl, media_type: mediaType }),
}
export const customerApi = { export const customerApi = {
list: (page = 1, size = 20, status) => { list: (page = 1, size = 20, status) => {
let params = `page=${page}&size=${size}` let params = `page=${page}&size=${size}`