chore:能正常运行
This commit is contained in:
271
components/ai-chat-message/README.md
Normal file
271
components/ai-chat-message/README.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# AI智能客服组件
|
||||
|
||||
一个功能完整的AI智能客服对话组件,支持多种消息类型和交互功能。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ 支持对话上下文管理
|
||||
- ✅ 支持多种消息类型:文本、Markdown、文件、音频、视频、链接、商品卡片
|
||||
- ✅ 支持语音输入和录音
|
||||
- ✅ 支持图片、文件、位置等附件发送
|
||||
- ✅ 支持消息操作按钮(点赞、踩等)
|
||||
- ✅ 支持历史消息加载
|
||||
- ✅ 响应式设计,适配多端
|
||||
|
||||
## 安装使用
|
||||
|
||||
### 1. 引入组件
|
||||
|
||||
在 `pages.json` 中注册组件:
|
||||
|
||||
```json
|
||||
{
|
||||
"usingComponents": {
|
||||
"ai-chat-message": "/components/ai-chat-message/ai-chat-message"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 在页面中使用
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="container">
|
||||
<ai-chat-message
|
||||
ref="chat"
|
||||
:initial-messages="messages"
|
||||
@message-sent="onMessageSent"
|
||||
@ai-response="onAIResponse"
|
||||
@action-click="onActionClick" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
id: 1,
|
||||
role: 'ai',
|
||||
type: 'text',
|
||||
content: '您好!我是AI智能客服,有什么可以帮助您的吗?',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onMessageSent(message) {
|
||||
console.log('用户发送消息:', message)
|
||||
},
|
||||
onAIResponse(message) {
|
||||
console.log('AI回复消息:', message)
|
||||
},
|
||||
onActionClick({ action, message }) {
|
||||
console.log('操作点击:', action, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## Props 配置
|
||||
|
||||
| 参数 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| initialMessages | Array | [] | 初始消息列表 |
|
||||
| userAvatar | String | '/static/images/default-avatar.png' | 用户头像 |
|
||||
| aiAvatar | String | '/static/images/ai-avatar.png' | AI头像 |
|
||||
| showLoadMore | Boolean | true | 是否显示加载更多 |
|
||||
| maxMessages | Number | 100 | 最大消息数量 |
|
||||
|
||||
## Events 事件
|
||||
|
||||
| 事件名 | 参数 | 说明 |
|
||||
|--------|------|------|
|
||||
| message-sent | message | 用户发送消息 |
|
||||
| ai-response | message | AI回复消息 |
|
||||
| action-click | {action, message} | 操作按钮点击 |
|
||||
| history-loaded | messages | 历史消息加载完成 |
|
||||
| file-preview | message | 文件预览 |
|
||||
| audio-play | message | 音频播放 |
|
||||
| audio-pause | message | 音频暂停 |
|
||||
| video-play | message | 视频播放 |
|
||||
| video-pause | message | 视频暂停 |
|
||||
| link-open | message | 链接打开 |
|
||||
| product-view | message | 商品查看 |
|
||||
| input-change | value | 输入内容变化 |
|
||||
|
||||
## 消息类型格式
|
||||
|
||||
### 文本消息
|
||||
```javascript
|
||||
{
|
||||
id: 1,
|
||||
role: 'user', // 或 'ai'
|
||||
type: 'text',
|
||||
content: '消息内容',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### Markdown消息
|
||||
```javascript
|
||||
{
|
||||
id: 2,
|
||||
role: 'ai',
|
||||
type: 'markdown',
|
||||
content: '# 标题\n**粗体** *斜体* `代码`',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### 文件消息
|
||||
```javascript
|
||||
{
|
||||
id: 3,
|
||||
role: 'ai',
|
||||
type: 'file',
|
||||
fileName: '文档.pdf',
|
||||
fileSize: 1024000,
|
||||
url: '文件地址',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### 音频消息
|
||||
```javascript
|
||||
{
|
||||
id: 4,
|
||||
role: 'ai',
|
||||
type: 'audio',
|
||||
title: '语音消息',
|
||||
duration: 60, // 秒
|
||||
url: '音频地址',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### 视频消息
|
||||
```javascript
|
||||
{
|
||||
id: 5,
|
||||
role: 'ai',
|
||||
type: 'video',
|
||||
title: '产品介绍',
|
||||
duration: 120, // 秒
|
||||
url: '视频地址',
|
||||
cover: '封面图',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### 链接消息
|
||||
```javascript
|
||||
{
|
||||
id: 6,
|
||||
role: 'ai',
|
||||
type: 'link',
|
||||
title: '帮助文档',
|
||||
description: '详细的使用说明',
|
||||
url: 'https://example.com',
|
||||
image: '缩略图',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
### 商品卡片
|
||||
```javascript
|
||||
{
|
||||
id: 7,
|
||||
role: 'ai',
|
||||
type: 'product',
|
||||
title: '商品名称',
|
||||
price: 299,
|
||||
description: '商品描述',
|
||||
image: '商品图片',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
通过 ref 调用组件方法:
|
||||
|
||||
```javascript
|
||||
// 添加消息
|
||||
this.$refs.chat.addMessage(message)
|
||||
|
||||
// 清空消息
|
||||
this.$refs.chat.clearMessages()
|
||||
|
||||
// 滚动到底部
|
||||
this.$refs.chat.scrollToBottom()
|
||||
```
|
||||
|
||||
## 样式定制
|
||||
|
||||
组件使用 SCSS 编写,可以通过 CSS 变量进行主题定制:
|
||||
|
||||
```css
|
||||
.ai-chat-container {
|
||||
--primary-color: #ff4544;
|
||||
--bg-color: #f8f8f8;
|
||||
--text-color: #333;
|
||||
}
|
||||
```
|
||||
|
||||
## 方法
|
||||
|
||||
通过 ref 调用组件方法:
|
||||
|
||||
```javascript
|
||||
// 添加消息
|
||||
this.$refs.chat.addMessage(message)
|
||||
|
||||
// 清空消息
|
||||
this.$refs.chat.clearMessages()
|
||||
|
||||
// 滚动到底部
|
||||
this.$refs.chat.scrollToBottom()
|
||||
|
||||
// 开始语音输入
|
||||
this.$refs.chat.startVoiceInput()
|
||||
|
||||
// 停止语音输入
|
||||
this.$refs.chat.stopVoiceInput()
|
||||
```
|
||||
|
||||
## 样式定制
|
||||
|
||||
组件使用 SCSS 编写,可以通过 CSS 变量进行主题定制:
|
||||
|
||||
```css
|
||||
.ai-chat-container {
|
||||
--primary-color: #ff4544;
|
||||
--bg-color: #f8f8f8;
|
||||
--text-color: #333;
|
||||
--border-color: #eeeeee;
|
||||
--user-bg: #e6f7ff;
|
||||
--ai-bg: #f6f6f6;
|
||||
}
|
||||
```
|
||||
|
||||
## 图标字体
|
||||
|
||||
组件使用自定义图标字体,需要在页面中引入:
|
||||
|
||||
```html
|
||||
<style>
|
||||
@import url('/components/ai-chat-message/iconfont.css');
|
||||
</style>
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 组件已适配项目中已有的 `ns-loading` 组件
|
||||
2. 需要配置对应的图标字体文件
|
||||
3. 音频播放功能在 H5 和 APP 端支持较好
|
||||
4. 文件预览功能依赖平台能力
|
||||
5. 语音输入功能需要用户授权麦克风权限
|
||||
6
components/ai-chat-message/ai-chat-message.json
Normal file
6
components/ai-chat-message/ai-chat-message.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"ns-loading": "../ns-loading/ns-loading"
|
||||
}
|
||||
}
|
||||
2766
components/ai-chat-message/ai-chat-message.vue
Normal file
2766
components/ai-chat-message/ai-chat-message.vue
Normal file
File diff suppressed because it is too large
Load Diff
288
components/ai-chat-message/demo.vue
Normal file
288
components/ai-chat-message/demo.vue
Normal file
@@ -0,0 +1,288 @@
|
||||
<template>
|
||||
<view class="demo-container">
|
||||
<view class="demo-header">
|
||||
<text class="demo-title">AI智能客服组件演示</text>
|
||||
</view>
|
||||
|
||||
<ai-chat-message
|
||||
ref="chat"
|
||||
:initial-messages="demoMessages"
|
||||
user-avatar="/static/images/demo-user.png"
|
||||
ai-avatar="/static/images/demo-ai.png"
|
||||
@message-sent="onMessageSent"
|
||||
@ai-response="onAIResponse"
|
||||
@action-click="onActionClick"
|
||||
@file-preview="onFilePreview"
|
||||
@audio-play="onAudioPlay"
|
||||
@video-play="onVideoPlay"
|
||||
@link-open="onLinkOpen"
|
||||
@product-view="onProductView" />
|
||||
|
||||
<view class="demo-controls">
|
||||
<button class="control-btn" @click="addTextMessage">添加文本消息</button>
|
||||
<button class="control-btn" @click="addMarkdownMessage">添加Markdown</button>
|
||||
<button class="control-btn" @click="addFileMessage">添加文件</button>
|
||||
<button class="control-btn" @click="addAudioMessage">添加音频</button>
|
||||
<button class="control-btn" @click="addVideoMessage">添加视频</button>
|
||||
<button class="control-btn" @click="addLinkMessage">添加链接</button>
|
||||
<button class="control-btn" @click="addProductMessage">添加商品</button>
|
||||
<button class="control-btn" @click="clearMessages">清空消息</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
demoMessages: [
|
||||
{
|
||||
id: 1,
|
||||
role: 'ai',
|
||||
type: 'text',
|
||||
content: '您好!我是AI智能客服演示程序,我可以展示多种消息类型。请点击下方的按钮体验不同功能!',
|
||||
timestamp: Date.now() - 300000,
|
||||
actions: [
|
||||
{ id: 1, text: '开始体验', type: 'like' }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 添加文本消息
|
||||
addTextMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'text',
|
||||
content: '这是一个文本消息示例,支持**粗体**、*斜体*和`代码`格式。也可以包含换行符\n这是第二行内容。',
|
||||
timestamp: Date.now(),
|
||||
actions: [
|
||||
{ id: 1, text: '有帮助', type: 'like' },
|
||||
{ id: 2, text: '没帮助', type: 'dislike' }
|
||||
]
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加Markdown消息
|
||||
addMarkdownMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'markdown',
|
||||
content: `# Markdown文档示例
|
||||
|
||||
## 二级标题
|
||||
|
||||
这是一个支持**粗体**、*斜体*和\`代码\`的Markdown消息。
|
||||
|
||||
### 功能特性
|
||||
- ✅ 支持标题层级
|
||||
- ✅ 支持列表展示
|
||||
- ✅ 支持代码高亮
|
||||
- ✅ 支持链接跳转
|
||||
|
||||
[查看详细文档](https://example.com)\n\n**注意:** 这是一个演示内容,实际使用时可以集成真实的文档系统。`,
|
||||
timestamp: Date.now(),
|
||||
actions: [
|
||||
{ id: 1, text: '查看文档', type: 'like' }
|
||||
]
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加文件消息
|
||||
addFileMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'file',
|
||||
fileName: '产品介绍文档.pdf',
|
||||
fileSize: 2048000,
|
||||
url: 'https://example.com/document.pdf',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加音频消息
|
||||
addAudioMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'audio',
|
||||
title: '产品功能介绍',
|
||||
duration: 89,
|
||||
url: 'https://example.com/audio.mp3',
|
||||
timestamp: Date.now(),
|
||||
playing: false,
|
||||
currentTime: 0
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加视频消息
|
||||
addVideoMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'video',
|
||||
title: '产品演示视频',
|
||||
duration: 180,
|
||||
url: 'https://example.com/video.mp4',
|
||||
cover: '/static/images/video-cover.jpg',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加链接消息
|
||||
addLinkMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'link',
|
||||
title: '帮助中心',
|
||||
description: '详细的产品使用说明和常见问题解答',
|
||||
url: 'https://example.com/help',
|
||||
image: '/static/images/link-thumbnail.jpg',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 添加商品消息
|
||||
addProductMessage() {
|
||||
const message = {
|
||||
id: Date.now(),
|
||||
role: 'ai',
|
||||
type: 'product',
|
||||
title: '智能手表 X1',
|
||||
price: 1299,
|
||||
description: '全新一代智能手表,支持心率监测、运动追踪、消息提醒等功能',
|
||||
image: '/static/images/product-demo.jpg',
|
||||
timestamp: Date.now(),
|
||||
actions: [
|
||||
{ id: 1, text: '立即购买', type: 'like' },
|
||||
{ id: 2, text: '查看详情', type: 'dislike' }
|
||||
]
|
||||
}
|
||||
this.$refs.chat.messages.push(message)
|
||||
},
|
||||
|
||||
// 清空消息
|
||||
clearMessages() {
|
||||
this.$refs.chat.messages = [
|
||||
{
|
||||
id: 1,
|
||||
role: 'ai',
|
||||
type: 'text',
|
||||
content: '消息已清空,可以重新开始体验!',
|
||||
timestamp: Date.now()
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// 事件处理
|
||||
onMessageSent(message) {
|
||||
console.log('用户发送消息:', message)
|
||||
uni.showToast({
|
||||
title: '消息发送成功',
|
||||
icon: 'success'
|
||||
})
|
||||
},
|
||||
|
||||
onAIResponse(message) {
|
||||
console.log('AI回复消息:', message)
|
||||
},
|
||||
|
||||
onActionClick({ action, message }) {
|
||||
console.log('操作点击:', action, message)
|
||||
uni.showToast({
|
||||
title: `点击了: ${action.text}`,
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
onFilePreview(message) {
|
||||
console.log('文件预览:', message)
|
||||
uni.showToast({
|
||||
title: '正在打开文件...',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
onAudioPlay(message) {
|
||||
console.log('音频播放:', message)
|
||||
},
|
||||
|
||||
onVideoPlay(message) {
|
||||
console.log('视频播放:', message)
|
||||
},
|
||||
|
||||
onLinkOpen(message) {
|
||||
console.log('链接打开:', message)
|
||||
uni.showToast({
|
||||
title: '正在打开链接...',
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
|
||||
onProductView(message) {
|
||||
console.log('商品查看:', message)
|
||||
uni.showToast({
|
||||
title: '正在查看商品...',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.demo-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.demo-header {
|
||||
background-color: #ff4544;
|
||||
color: white;
|
||||
padding: 30rpx;
|
||||
text-align: center;
|
||||
|
||||
.demo-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.demo-controls {
|
||||
background-color: white;
|
||||
padding: 20rpx;
|
||||
border-top: 2rpx solid #eeeeee;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10rpx;
|
||||
|
||||
.control-btn {
|
||||
flex: 1;
|
||||
min-width: 150rpx;
|
||||
height: 60rpx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
border: none;
|
||||
|
||||
&:active {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,19 @@
|
||||
<template>
|
||||
<!-- 悬浮按钮 -->
|
||||
<view v-if="pageCount == 1 || need" class="fixed-box" :style="{ height: fixBtnShow ? '330rpx' : '120rpx' }">
|
||||
<!-- AI智能助手 -->
|
||||
<view class="btn-item" v-if="fixBtnShow && enableAIChat" @click="openAIChat"
|
||||
:style="{backgroundImage:'url('+(aiAgentimg?aiAgentimg:'')+')',backgroundSize:'100% 100%'}">
|
||||
<!-- 核心修改:添加🤖表情,保留原有判断逻辑 -->
|
||||
<text class="ai-icon" v-if="!aiAgentimg">🤖</text>
|
||||
<!-- 未读消息小红点 -->
|
||||
<view v-if="unreadCount > 0" class="unread-badge">
|
||||
<text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<!-- <view class="btn-item" v-if="fixBtnShow" @click="$util.redirectTo('/pages/index/index')"> -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 微信小程序默认客服按钮 -->
|
||||
@@ -9,7 +22,7 @@
|
||||
:style="{ backgroundImage: 'url(' + (kefuimg ? kefuimg : '') + ')', backgroundSize: '100% 100%' }">
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
</button>
|
||||
|
||||
|
||||
<!-- 自定义客服按钮 -->
|
||||
<button class="btn-item" v-if="fixBtnShow && !useOfficialService" hoverClass="none" @click="contactServicer"
|
||||
:style="{ backgroundImage: 'url(' + (kefuimg ? kefuimg : '') + ')', backgroundSize: '100% 100%' }">
|
||||
@@ -34,151 +47,216 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createCustomerService } from '@/common/js/customer-service.js';
|
||||
import {
|
||||
mapGetters,
|
||||
mapMutations
|
||||
} from 'vuex'
|
||||
import {
|
||||
createCustomerService
|
||||
} from '@/common/js/customer-service.js';
|
||||
|
||||
export default {
|
||||
name: 'hover-nav',
|
||||
props: {
|
||||
need: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
export default {
|
||||
name: 'hover-nav',
|
||||
props: {
|
||||
need: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageCount: 0,
|
||||
fixBtnShow: true,
|
||||
tel: '',
|
||||
kefuimg: '',
|
||||
phoneimg: '',
|
||||
customerService: null, // 客服服务实例
|
||||
buttonConfig: null // 按钮配置
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.kefuimg = this.$util.getDefaultImage().kefu
|
||||
this.phoneimg = this.$util.getDefaultImage().phone
|
||||
this.pageCount = getCurrentPages().length;
|
||||
data() {
|
||||
return {
|
||||
pageCount: 0,
|
||||
fixBtnShow: true,
|
||||
tel: '',
|
||||
kefuimg: '',
|
||||
phoneimg: '',
|
||||
customerService: null, // 客服服务实例
|
||||
buttonConfig: null // 按钮配置
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.kefuimg = this.$util.getDefaultImage().kefu
|
||||
this.phoneimg = this.$util.getDefaultImage().phone
|
||||
this.pageCount = getCurrentPages().length;
|
||||
|
||||
// 初始化客服服务
|
||||
this.customerService = createCustomerService(this);
|
||||
this.buttonConfig = this.customerService.getButtonConfig();
|
||||
// 初始化客服服务
|
||||
this.customerService = createCustomerService(this);
|
||||
this.buttonConfig = this.customerService.getButtonConfig();
|
||||
|
||||
var that = this
|
||||
uni.getStorage({
|
||||
key: 'shopInfo',
|
||||
success(e) {
|
||||
that.tel = e.data.mobile
|
||||
}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* 是否使用官方客服
|
||||
*/
|
||||
useOfficialService() {
|
||||
if (!this.buttonConfig) return true;
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// 如果是微信小程序,检查配置
|
||||
if (this.buttonConfig.type === 'weapp') {
|
||||
// 默认使用官方客服,除非明确设置为false
|
||||
return this.buttonConfig.useOfficial !== false;
|
||||
}
|
||||
// #endif
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//拨打电话
|
||||
call() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: this.tel + ''
|
||||
var that = this
|
||||
uni.getStorage({
|
||||
key: 'shopInfo',
|
||||
success(e) {
|
||||
that.tel = e.data.mobile
|
||||
}
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'globalAIKefuConfig',
|
||||
'aiUnreadCount'
|
||||
]),
|
||||
aiAgentimg() {
|
||||
return this.globalAIKefuConfig?.icon || this.$util.getDefaultImage().aiAgent || '' // AI智能助手的头像
|
||||
},
|
||||
unreadCount() {
|
||||
return this.aiUnreadCount
|
||||
},
|
||||
enableAIChat() {
|
||||
return this.globalAIKefuConfig?.enable || true // 是否开启AI智能助手
|
||||
},
|
||||
/**
|
||||
* 是否使用官方客服
|
||||
*/
|
||||
useOfficialService() {
|
||||
if (!this.buttonConfig) return true;
|
||||
|
||||
//处理客服点击事件
|
||||
contactServicer() {
|
||||
// 使用统一客服处理
|
||||
this.customerService.handleCustomerClick();
|
||||
// #ifdef MP-WEIXIN
|
||||
// 如果是微信小程序,检查配置
|
||||
if (this.buttonConfig.type === 'weapp') {
|
||||
// 默认使用官方客服,除非明确设置为false
|
||||
return this.buttonConfig.useOfficial !== false;
|
||||
}
|
||||
// #endif
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations([
|
||||
'setAiUnreadCount'
|
||||
]),
|
||||
|
||||
//拨打电话
|
||||
call() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: this.tel + ''
|
||||
})
|
||||
},
|
||||
|
||||
//处理客服点击事件
|
||||
contactServicer() {
|
||||
// 使用统一客服处理
|
||||
this.customerService.handleCustomerClick();
|
||||
},
|
||||
// 打开AI聊天弹窗
|
||||
openAIChat() {
|
||||
if (this.enableAIChat) {
|
||||
this.setAiUnreadCount(0);
|
||||
}
|
||||
|
||||
this.$util.redirectTo('/pages_tool/ai-chat/index')
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container-box {
|
||||
width: 100%;
|
||||
.container-box {
|
||||
width: 100%;
|
||||
|
||||
.item-wrap {
|
||||
border-radius: 10rpx;
|
||||
|
||||
.image-box {
|
||||
.item-wrap {
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 10rpx;
|
||||
will-change: transform;
|
||||
.image-box {
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 10rpx;
|
||||
will-change: transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//悬浮按钮
|
||||
.fixed-box {
|
||||
position: fixed;
|
||||
right: 0rpx;
|
||||
bottom: 200rpx;
|
||||
z-index: 10;
|
||||
// background: #fff;
|
||||
// box-shadow: 2rpx 2rpx 22rpx rgba(0, 0, 0, 0.3);
|
||||
border-radius: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100rpx;
|
||||
box-sizing: border-box;
|
||||
transition: 0.3s;
|
||||
overflow: hidden;
|
||||
|
||||
.btn-item {
|
||||
//悬浮按钮
|
||||
.fixed-box {
|
||||
position: fixed;
|
||||
right: 0rpx;
|
||||
bottom: 200rpx;
|
||||
z-index: 10;
|
||||
border-radius: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
margin: 14rpx 0;
|
||||
transition: 0.1s;
|
||||
background: #fff;
|
||||
border-radius: 50rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding: 0;
|
||||
width: 100rpx;
|
||||
box-sizing: border-box;
|
||||
transition: 0.3s;
|
||||
overflow: hidden;
|
||||
|
||||
text {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.btn-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center; /* 新增:让🤖表情垂直居中 */
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
margin: 14rpx 0;
|
||||
transition: 0.1s;
|
||||
background: #fff;
|
||||
border-radius: 50rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
text {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
view {
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&.show {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
&.show {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&.switch {}
|
||||
&.switch {}
|
||||
|
||||
&.icon-xiala {
|
||||
margin: 0;
|
||||
margin-top: 0.1rpx;
|
||||
&.icon-xiala {
|
||||
margin: 0;
|
||||
margin-top: 0.1rpx;
|
||||
}
|
||||
|
||||
// 未读消息小红点
|
||||
.unread-badge {
|
||||
position: absolute;
|
||||
top: -5rpx;
|
||||
right: -5rpx;
|
||||
background-color: #ff4544;
|
||||
color: white;
|
||||
border-radius: 20rpx;
|
||||
min-width: 30rpx;
|
||||
height: 30rpx;
|
||||
font-size: 10rpx;
|
||||
line-height: 30rpx;
|
||||
text-align: center;
|
||||
padding: 0 8rpx;
|
||||
z-index: 1;
|
||||
box-shadow: 0 2rpx 10rpx rgba(255, 69, 68, 0.3);
|
||||
|
||||
.badge-text {
|
||||
font-size: 8rpx;
|
||||
// #ifdef MP-WEIXIN
|
||||
font-size: 20rpx;
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
|
||||
// AI图标样式优化(让🤖表情居中显示)
|
||||
.ai-icon {
|
||||
font-size: 40rpx; // 调整🤖表情大小
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user