Vue在线客服插件不装也能接

合从在线客服系统首页 / 文章列表 / 详情2026-10-26 18:00:00

作者:周屿|更新于 2026-10-26

公司官网是 Vue 写的。运营过来说一句,网站上加个在线客服吧。

做前端的,多半先去 npm 上搜「Vue在线客服插件」,想找个装上就能用的组件。搜出来的,大多是别人自己写的聊天组件。界面是有了,可消息谁来回、存在哪,还得自己再搭一套后台。

其实不用装插件,也不用自己搭后台。接上以后,客户在网页上点一下,就能打开聊天窗问。客服在客服系统里看到这条消息,直接回,客户在聊天窗里就能看到。

网页上打开的聊天窗:欢迎语、查订单等快捷按钮和输入框

前端要做的,就是往项目里贴一段代码,再在组件里调几下。下面用合从按顺序走一遍。

先拿到那段代码

代码在合从的工作台里拿。工作台,就是客服平时回消息的那个网页。

登录工作台,点「设置」,在「客户」下面找到「渠道管理」,点「接入新渠道」。

类型选「网页接入」,名字起一个自己认得的,比如「官网」,点「创建渠道」。建好以后,页面就停在「安装代码」,点「复制代码」。

渠道的安装代码页,红框标出复制代码按钮,再往下是安装状态卡片

复制出来的代码里,已经带好了这个渠道的编号,不用改。

没建过渠道的,网站贴一段代码就能接待那篇写得更细。

Vue 项目里,代码贴在 index.html

拿到代码,很多人先想到的是放进 App.vue,在 onMounted 里用 document.createElement 插进去,觉得这样更像 Vue 的写法。

不用这样。聊天窗是跟着整个页面走的,不跟着组件走。组件创建、销毁,它都在。放进组件里,组件重新挂载一次,script 就多插一次。

所以就贴在 index.html 里,跟普通网页一样。Vite 建的项目,index.html 在根目录。Vue CLI 建的,在 public/ 里。

贴在 </body> 前面,后面再跟一行占位函数:

<!-- index.html:Vite 建的项目在根目录,Vue CLI 建的在 public/ 里 -->
<body>
  <div id="app"></div>
  <script async
    src="https://assets.aihecong.com/sdk/hecong.js"
    data-channel-id="0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b">
  </script>
  <script>
    window.hecong = window.hecong || function (c) { (window.hecong.q = window.hecong.q || []).push(c) }
  </script>
</body>

data-channel-id 换成你复制出来的那个。占位函数照原样抄,后面组件里会用到。

贴完就能用了,不用写初始化代码。按钮颜色、文案、欢迎语,都在工作台里改。运营想换欢迎语,自己去改,不用你再发版。合从也没有 npm 包,就这一段 script。

要放进手机上的活动页,按钮挡住页面怎么办,H5 落地页上的客服按钮怎么在手机上调讲过。

点自己的按钮打开聊天窗

贴完,网页右下角就有聊天按钮了。可很多官网本来就有一个「咨询客服」按钮,在帮助中心、商品页这些地方。产品要的是,客户点这个按钮,打开的就是聊天窗。

在点击事件里这样写:

<template>
  <button @click="openChat">咨询客服</button>
</template>

<script setup>
function openChat() {
  window.hecong((hc) => hc.open())
}
</script>

有人会担心,script 是异步加载的,组件可能比它先跑。客户一进页面就点按钮,那时候还没有 window.hecong,会不会报错?

不会,前面那行占位函数就是管这个的。有了它,window.hecong 从一开始就在。早调的先排着队,等 script 加载好再执行。所以组件里什么时候调都行,换了路由以后再调也行。

自己的按钮能用了,右下角那个就多余了。到这个渠道的「启动器」里,找到「按钮来源」。

把它改成「使用自有按钮」,右下角的按钮就不出来了。

启动器设置里的按钮来源:合从聊天按钮、使用自有按钮,再往下是电脑、手机两个标签

改之前,先把自己的按钮发上线。不然中间这段时间,页面上一个能问的地方都没有。原来的按钮样式会留着,切回去就恢复。

把登录的客户带给客服

网站有登录的,客服最想知道的是这人是谁。不传的话,客服看到的就是一个匿名客户,是谁还得再问一遍。

传之前,先想好用什么当 id。合从是按 id 认人的,id 一样,就当成同一个客户。

很多人顺手就用数据库里的自增编号,1001、1002 这种。可这种数,别人随手改一个就能对上另一个客户。两个人传了同一个 id,后来的那位,会看到前一位的聊天记录。手机号、邮箱也一样,别人能猜到。

所以 id 要用别人猜不到的值,数据库里的 UUID 就可以。拿不到这种 id 的时候,就别传,按匿名客户接待,也别传一个固定值凑数。

id 想好了,Vue 3 里用 watchEffect 跟着登录状态走。客户登录了,就调 identify,把 id 和姓名传过去。客户退出登录,调一次 reset:

import { watchEffect } from 'vue'

// user 是项目里存登录用户的 ref,比如从 Pinia 里取
watchEffect(() => {
  if (!user.value) return
  window.hecong((hc) => {
    hc.identify({ id: user.value.uuid, profile: { name: user.value.name } })
  })
})

// 客户退出登录时
function onLogout() {
  window.hecong((hc) => hc.reset())
}

reset 不能省。营业厅、展厅平板这种好几个人用的机器,上一位退出了,下一位不登录,就会顶着上一位的身份进来,看到上一位的聊天记录。

传好以后,客服在工作台对话的右边,就能看到网站传来的姓名。

工作台对话右边的客户资料,姓名一栏显示网站传来的林嘉树,红框框住姓名

换路由时收个尾

Vue 做的是单页应用,换页面不刷新。组件没了,它在聊天窗上挂的东西还在。有两样要自己收。

自己加的监听

比如想统计客户打开了几次聊天窗,在组件里用 hc.on 监听。组件每挂载一次,就多注册一次。客户来回切几次页面,打开一次聊天窗,统计就记了好几遍。

hc.on 会返回一个退订函数,在 onBeforeUnmount 里调它:

import { onMounted, onBeforeUnmount } from 'vue'

let off
let cancelled = false

onMounted(() => {
  window.hecong((hc) => {
    if (cancelled) return
    off = hc.on('chat:open', () => {
      // 你的统计代码
    })
  })
})

onBeforeUnmount(() => {
  cancelled = true
  off?.()
})

cancelled 管的是另一种情况。客户切走得太快,script 还没加载好,组件就卸载了,这时候还没拿到 off。有了它,迟到的回调就不会再去注册。

带进输入框的商品

商品页常用 setPresend,把正在看的商品带进聊天窗的输入框。客户换到别的页面,它不会自动清。

结果客户到了订单页,点开聊天窗想问物流,输入框里还是上一件商品。

在商品页组件卸载的时候清掉,或者到了新页面再调一次:

onBeforeUnmount(() => {
  window.hecong((hc) => hc.setPresend(null))
})

聊天窗本身不用管,组件卸载了它照样在页面上。identify 也不用管。

TypeScript 报错

项目用 TypeScript 的话,写 window.hecong 会报错,说 Window 上没有这个属性。

合从没有类型声明包,在 src 下自己写一个 hecong.d.ts 就行。用到哪几个方法,就声明哪几个:

// src/hecong.d.ts
interface HecongApi {
  identify(args: { id: string; profile?: { name?: string } }): Promise<unknown>
  reset(): Promise<unknown>
  open(): void
  setPresend(input: { text?: string } | null): void
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  on(event: string, handler: (arg: any) => void): () => void
}

declare global {
  interface Window {
    hecong: (cb: (hc: HecongApi) => void) => void
  }
}

export {}

完整的写法在文档站的 React 与 Vue 接入示例里,可以整段复制。

本地跑一遍再提交

上线前,先在本地试。新建的渠道不限域名,npm run dev 起来,localhost 上就能调通。

打开页面,回到工作台的「安装代码」页,看下面的「安装状态」。有人打开页面几秒后,它会亮成「已安装」。

再点开聊天窗发一句话,回工作台看这条消息到了没有。

登录过的,顺便看一眼客服那边有没有姓名。注意,传过去的资料要等客户点开聊天窗才发出去。所以先登录、点开聊天窗,再去工作台看。

都对了,再提交代码。聊天窗长什么样、欢迎语说什么,交给运营去调,聊天窗口的样式和欢迎语怎么设置单独写过。

常见问题

Nuxt 项目怎么放?

Nuxt 没有固定的 index.html。聊天窗又要用 document 和 window,只能在浏览器里跑。

那就放在 app.vue 这种整个应用只跑一次的地方,在 onMounted 里插一次:

<!-- app.vue,别放进会随路由反复挂载的组件 -->
<script setup>
onMounted(() => {
  window.hecong = window.hecong || function (c) { (window.hecong.q = window.hecong.q || []).push(c) }
  const s = document.createElement('script')
  s.async = true
  s.src = 'https://assets.aihecong.com/sdk/hecong.js'
  s.dataset.channelId = '0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b'
  document.body.appendChild(s)
})
</script>

React 项目也是这样接吗?

是。React 和 Vue 用的是同一段 script,同样放在 index.html 里。组件里在 useEffect 里调 window.hecong,打开聊天窗、传客户身份的写法和上面一样。换路由时,同样要在清理函数里退订。

Vue 项目能接 AI 客服吗?

能。聊天窗还是这一个,代码不用改。

在工作台点「设置」,找到「渠道管理」,选中这个渠道。左边点「AI 机器人」,给它选一个机器人。

这样客户的消息就先由机器人接待,答不上来再转人工。

要后端配合吗?

不用。接上聊天窗、打开聊天窗、传登录的客户,都在前端代码里做。传客户时用的 id,和上面说的一样,得是别人猜不到的值。

轻松上手,简单好用

多渠道统一服务,提升营销转化,降低人工回复成本,客服团队协助更高效