2026-08-03 16:24:25 +08:00

1335 lines
44 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="box">
<div>
<div v-if="shouldShowFloatingConsult" class="contener">
<transition name="slide">
<div v-show="windowsHidden" style="font-size: 14px">
<div class="floating-consult">
<a href="#" class="floating-consult-btn primary" @click.prevent="openAiConsult">
<div class="floating-consult-icon">
<img src="./img/ocai.jpg" alt="在线咨询">
<span class="consult-badge" />
</div>
<!-- <span class="floating-consult-text">在线咨询</span> -->
</a>
</div>
</div>
</transition>
</div>
<!-- 申请试用弹窗 -->
<el-dialog
title="申请试用产品"
:visible.sync="dialogVisible"
width="35%"
:before-close="handleClose"
custom-class="apply-use"
>
<el-form ref="form" :model="form" label-width="120px" :rules="rules" style="width: 80%">
<el-form-item label="姓名:" prop="customer">
<el-input v-model="form.customer" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="联系方式:" prop="phone">
<el-input v-model="form.phone" placeholder="请输入联系方式" />
</el-form-item>
<el-form-item label="公司:" prop="unit">
<el-input v-model="form.unit" placeholder="请输入公司名称" />
</el-form-item>
<el-form-item label="数量:">
<el-input v-model="form.product_num" disabled placeholder="请输入资源数量" />
</el-form-item>
<el-form-item label="需求型号:" prop="resources">
<!-- <el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4}" v-model="form.resources" placeholder="请输入资源需求"></el-input>-->
<el-checkbox-group v-model="form.resources" style="display: flex;flex-wrap: wrap;">
<el-checkbox label="H800" style="width: 50%;" />
<el-checkbox label="H100" style="width: 50%;" />
<el-checkbox label="A800" style="width: 50%;" />
<el-checkbox label="A100" style="width: 50%;" />
</el-checkbox-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button size="small" @click="handleClose"> </el-button>
<el-button size="small" type="primary" @click="onSubmit()"> </el-button>
</span>
</el-dialog>
<!-- 选择视频类型-->
<!-- v-if="isShowChangeChat"-->
<div v-if="isShowChangeChat " class="changeChat" style="">
<span style="margin-bottom: 5px;display: block">请选择聊天方式</span>
<el-checkbox-group v-model="checkType" :min="1" style="margin-bottom: 5px">
<el-checkbox label="文字" />
<el-checkbox label="视频" />
<el-checkbox label="音频" />
</el-checkbox-group>
<div style="display: flex;justify-content: flex-end">
<el-button size="mini" @click="closeWindow">关闭</el-button>
<el-button type="primary" size="mini" @click="goVedioPage">立即沟通</el-button>
</div>
</div>
</div>
</div>
</template>
<script>
import { contantAPI, applyAPI } from '../../api/floatingWindow/index'
import { getCustomerOfSaleUserId } from '@/api/customer/vedio'
import { getHomePath } from '@/views/setting/tools'
import { reqNewHomeConsult } from '@/api/newHome'
export default {
// 组件的逻辑代码
data() {
return {
socket: null,
checkType: ['文字'],
isShowChangeChat: false, // 控制选择沟通方式弹窗
loading: true,
currentDate: '2021-06-01',
isShowPicLoading: true, // 图片loading展示
isSend: true,
windowsHidden: true,
// 获取用户代理字P串
userAgent: window.navigator.userAgent,
// 判断是否为移动设备
isMobile: false,
url: window.location.href,
orgType: '',
isShow: false,
userid: sessionStorage.getItem('userId'),
src: null,
phone: null,
title: '',
dialogVisible: false,
form: {
customer: '',
phone: '',
unit: '',
product_num: '1',
resources: ['H800']
},
rules: {
customer: [
{ required: true, message: '请输入姓名', trigger: 'change' }
],
phone: [{ pattern: /^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/, message: '请输入有效的手机号' },
{ required: true, trigger: 'blur', message: '请输入手机号' }],
unit: [
{ required: true, message: '请输入单位', trigger: 'change' }
],
product: [
{ required: true, message: '请输入资源名称', trigger: 'change' }
],
resources: [
{ required: true, message: '请输入资源需求', trigger: 'blur' }
]
}
}
},
computed: {
shouldShowFloatingConsult() {
const isHomePage = [
'/homePage/index',
'/homePage/indexLast',
'/ncmatchHome/index'
].includes(this.$route.path)
return isHomePage || this.orgType === '2' || this.orgType === '3' || !this.userid
}
},
watch: {
'$route': { // $route可以用引号也可以不用引号
handler(to, from) {
this.orgType = sessionStorage.getItem('org_type') ? sessionStorage.getItem('org_type') : ''
this.userid = sessionStorage.getItem('userId') ? sessionStorage.getItem('userId') : ''
},
deep: true, // 深度监听
immediate: true // 第一次初始化渲染就可以监听到
}
},
created() {
this.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(this.userAgent)
},
mounted() {
// debugger
// console.log("路由展示~~~",location.href)
// console.log("路由展示~~~",this.$route)
},
methods: {
// 让模板中可以直接调用 getHomePath()
getHomePath,
openTip() {
this.$notify({
title: '提示',
message: '当前还未登录,请先登录~',
type: 'warning'
})
},
goVedioPage() {
if (!sessionStorage.getItem('userId')) {
console.log('未登录,请重新登录')
this.openTip()
} else {
const ploady = {
audioIsOn: 0,
vedioIsOn: 0,
chatIsOn: 0,
userId: this.userid,
toUserId: 0,
customerName: sessionStorage.getItem('username')
}
for (let i = 0; i < this.checkType.length; i++) {
if (this.checkType[i] === '文字') {
ploady.chatIsOn = 1
} else if (this.checkType[i] === '视频') {
ploady.vedioIsOn = 1
} else if (this.checkType[i] === '音频') {
ploady.audioIsOn = 1
}
}
getCustomerOfSaleUserId({ userid: this.userid }).then(res => {
const routeData = {
chatIsOn: ploady.chatIsOn,
vedioIsOn: ploady.vedioIsOn,
audioIsOn: ploady.audioIsOn,
value: 'customer'
}
if (res.status) {
this.$router.push({
path: '/customer/chat',
query: {
chatIsOn: ploady.chatIsOn,
vedioIsOn: ploady.vedioIsOn,
audioIsOn: ploady.audioIsOn,
room: res.data,
name: sessionStorage.getItem('username')
}
})
this.isShowChangeChat = false
// let webSocketUrl = 'wss://www.opencomputing.cn/dev/wss/pub/rtcc.ws'
const webSocketUrl = 'wss://www.opencomputing.cn/pub/rtcc.ws'
this.socket = new WebSocket(webSocketUrl)
const ploadyed = {
type: 'send',
from: sessionStorage.getItem('userId'),
uuid: res.data,
content: JSON.stringify(routeData)
}
// let ploadyed = {
// type: 'send',
// from: "user1",
// uuid: "asdsad",
// content: {}
// }
this.socket.onopen = (event) => {
console.log('客户创建成功了@@@@@')
console.log('发送的信息是', ploadyed)
this.socket.send(JSON.stringify(ploadyed))
}
this.socket.onmessage = (event) => {
console.log('接收到消息@@@@', event.data)
}
this.socket.onclose = (event) => {
console.log('WebSocket连接已关闭')
}
} else {
console.log('zouleels')
}
})
}
},
open2() {
this.isShowChangeChat = true
},
getYunbaoProducts() {
return [
{ id: 'bid', key: this.$t('yunbao.products.bid'), intro: 'E投标智能体是覆盖「招标解析→标书编制→合规审查→查重→知识沉淀」全链路的一站式投标AI解决方案帮企业将编标周期从数天压缩至小时级低级废标率降低100%。' },
{ id: 'tender', key: this.$t('yunbao.products.tender'), intro: 'E招标智能体AI辅助编制招标文件自动合规性审查让招标流程更高效、更透明、更合规。' },
{ id: 'evaluation', key: this.$t('yunbao.products.evaluation'), intro: 'E评标智能体AI辅助评标分析自动提取关键指标、横向对比评分、识别异常报价帮助评标专家高效、公正地完成评审工作。' },
{ id: 'loggingReview', key: this.$t('yunbao.products.loggingReview'), intro: '面向林业管理的行业智能体,可在线完成采伐申请材料的智能核验,自动比对采伐范围、树种、蓄积量等核心指标与合规要求,快速识别违规申请,助力林业资源可持续利用。' },
{ id: 'gasMonitor', key: this.$t('yunbao.products.gasMonitor'), intro: '能源领域工业智能体实时采集燃机运行的温度、压力、振动等多维度数据通过AI算法识别异常运行征兆提前预判潜在故障保障燃机稳定运行降低运维成本。' },
{ id: 'powerPrice', key: this.$t('yunbao.products.powerPrice'), intro: '面向能源行业的预测智能体,结合历史电价数据、供需变化、政策调整、天气影响等多维度变量,通过机器学习模型实现不同周期的电价精准预测,帮助电力企业优化收益管理。' },
{ id: 'comic', key: this.$t('yunbao.products.comic'), intro: '互联网内容创作智能体覆盖从剧本生成、分镜拆解、素材生成到视频合成的全流程制作。支持工业化批量生产帮助中小团队低成本快速产出AI漫画作品大幅降低创作门槛。' },
{ id: 'contract', key: this.$t('yunbao.products.contract'), intro: this.$t('casePages.contract.heroDesc') },
{ id: 'decision', key: this.$t('yunbao.products.decision'), intro: this.$t('casePages.decision.heroDesc') }
]
},
openAiConsult() {
this.resetYunbaoChatInstance()
this.installYunbaoChat()
window.YunbaoChat.init({
avatarUrl: require('./img/ocai.jpg'),
name: this.$t('yunbao.name'),
products: this.getYunbaoProducts()
})
window.YunbaoChat.open()
},
resetYunbaoChatInstance() {
const oldModal = document.getElementById('yunbaoModal')
const oldStyle = document.getElementById('yunbao-chat-css')
if (oldModal) oldModal.remove()
if (oldStyle) oldStyle.remove()
window.YunbaoChat = null
},
installYunbaoChat() {
if (window.YunbaoChat && document.getElementById('yunbaoModal')) return
if (window.YunbaoChat && !document.getElementById('yunbaoModal')) {
window.YunbaoChat = null
}
const vm = this
window.YunbaoChat = {
_inited: false,
_chatInited: false,
_selectedProduct: '',
_config: {},
init(config = {}) {
if (this._inited) return
this._inited = true
this._config = Object.assign({
avatarUrl: '',
name: vm.$t('yunbao.name'),
submitUrl: '',
products: vm.getYunbaoProducts(),
pages: {
contract: '/homePage/agentStore/contractCase',
decision: '/homePage/agentStore/decisionCase'
}
}, config)
this.injectCSS()
this.injectHTML()
this.bindBaseEvents()
},
open() {
const modal = document.getElementById('yunbaoModal')
if (!modal) return
modal.querySelectorAll('.yb-chat-avatar img,.yb-chat-msg-avatar img').forEach((img) => {
img.src = this._config.avatarUrl
})
modal.classList.add('active')
if (!this._chatInited) {
this._chatInited = true
this.initChat()
}
},
close() {
const modal = document.getElementById('yunbaoModal')
if (modal) modal.classList.remove('active')
},
injectCSS() {
if (document.getElementById('yunbao-chat-css')) return
const style = document.createElement('style')
style.id = 'yunbao-chat-css'
style.textContent = vm.getYunbaoChatCSS()
document.head.appendChild(style)
},
injectHTML() {
if (document.getElementById('yunbaoModal')) return
const div = document.createElement('div')
div.innerHTML = vm.getYunbaoChatHTML(this._config)
document.body.appendChild(div.firstElementChild)
},
bindBaseEvents() {
const modal = document.getElementById('yunbaoModal')
const closeBtn = document.getElementById('yunbaoCloseBtn')
if (modal) {
modal.addEventListener('click', (event) => {
if (event.target === modal) this.close()
})
}
if (closeBtn) closeBtn.addEventListener('click', () => this.close())
},
initChat() {
const body = document.getElementById('yunbaoChatBody')
if (!body) return
body.innerHTML = ''
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.welcome'), [
{ text: vm.$t('yunbao.browse'), action: 'browse' },
{ text: vm.$t('yunbao.direct'), action: 'direct' }
])
}, 200)
},
addBotMsg(html, options = [], displayType = '') {
const body = document.getElementById('yunbaoChatBody')
if (!body) return
const msg = document.createElement('div')
msg.className = 'yb-chat-msg'
const type = displayType || (options[0] && options[0].type) || ''
let optionHtml = ''
if (options.length) {
if (type === 'cards') {
optionHtml = `<div class="yb-chat-product-cards">${options.map(item => `
<div class="yb-chat-product-card" data-action="${item.action || ''}" data-param="${item.param || ''}" data-url="${item.url || ''}" data-text="${item.text || ''}">
<div class="yb-chat-product-card-title">${item.text}</div>
<div class="yb-chat-product-card-desc">${item.desc || ''}</div>
<span class="yb-chat-product-card-link">${vm.$t('yunbao.learnMore')}</span>
</div>
`).join('')}</div>`
} else if (type === 'tags') {
optionHtml = `<div class="yb-chat-tag-options">${options.map(item => `<button class="yb-chat-tag-btn" data-action="${item.action || ''}" data-param="${item.param || ''}" data-text="${item.text || ''}">${item.text}</button>`).join('')}</div>`
} else {
optionHtml = `<div class="yb-chat-options">${options.map(item => `<button class="${item.primary ? 'yb-chat-option-btn primary' : 'yb-chat-option-btn'}" data-action="${item.action || ''}" data-param="${item.param || ''}" data-text="${item.text || ''}">${item.text}</button>`).join('')}</div>`
}
}
msg.innerHTML = `
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="${this._config.name}"></div>
<div>
<div class="yb-chat-msg-bubble">${html}</div>
${optionHtml}
</div>
`
body.appendChild(msg)
body.scrollTop = body.scrollHeight
msg.querySelectorAll('[data-action]').forEach(btn => {
btn.addEventListener('click', () => this.handleAction(btn.getAttribute('data-action'), btn.getAttribute('data-param'), btn.getAttribute('data-text') || btn.innerText.trim(), btn.getAttribute('data-url')))
})
},
addUserMsg(text) {
const body = document.getElementById('yunbaoChatBody')
if (!body) return
const msg = document.createElement('div')
msg.className = 'yb-chat-msg yb-chat-msg-user'
msg.innerHTML = `<div class="yb-chat-msg-avatar yb-chat-user-avatar"><span>👤</span></div><div class="yb-chat-msg-bubble">${text}</div>`
body.appendChild(msg)
body.scrollTop = body.scrollHeight
},
handleAction(action, param, text, url) {
this.addUserMsg(text || param)
if (action === 'retrySubmit') {
setTimeout(() => this.submitForm(), 200)
return
}
if (action === 'browse') {
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.recommend'), [
{ text: vm.$t('yunbao.products.bid'), desc: vm.$t('yunbao.productDescs.bid'), action: 'goExternal', url: 'https://bid-ocai-v2.jinan.opencomputing.cn/', type: 'cards' },
{ text: vm.$t('yunbao.products.contract'), desc: vm.$t('yunbao.productDescs.contract'), action: 'goContract', type: 'cards' },
{ text: vm.$t('yunbao.products.decision'), desc: vm.$t('yunbao.productDescs.decision'), action: 'goInvest', type: 'cards' }
])
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.moreProducts'), this.getProductTags(), 'tags')
}, 1200)
}, 200)
return
}
if (action === 'direct') {
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.askProduct'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goContract') {
vm.$router.push(this._config.pages.contract || '/homePage/agentStore/contractCase').catch(() => {})
this.close()
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.openedContract'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goExternal') {
window.open(url, '_blank')
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.openedPage'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'goInvest') {
vm.$router.push(this._config.pages.decision || '/homePage/agentStore/decisionCase').catch(() => {})
this.close()
setTimeout(() => {
this.addBotMsg(vm.$t('yunbao.openedDecision'), this.getProductTags(), 'tags')
}, 200)
return
}
if (action === 'productIntro') {
this._selectedProduct = param
const intro = this.getProductIntro(param)
setTimeout(() => {
this.addBotMsg(intro)
setTimeout(() => this.addContactForm(), 800)
}, 200)
return
}
},
getProductTags() {
return this._config.products.map(item => ({
text: item.key,
action: 'productIntro',
param: item.id
}))
},
getProductIntro(key) {
const product = this._config.products.find(item => item.id === key || item.key === key)
return product ? product.intro : vm.$t('yunbao.productIntroDefault')
},
getProductName(key) {
const product = this._config.products.find(item => item.id === key || item.key === key)
return product ? product.key : key
},
addContactForm() {
const body = document.getElementById('yunbaoChatBody')
if (!body) return
const form = document.createElement('div')
form.className = 'yb-chat-msg'
form.innerHTML = `
<div class="yb-chat-msg-avatar"><img src="${this._config.avatarUrl}" alt="${this._config.name}"></div>
<div>
<div class="yb-chat-msg-bubble">
${vm.$t('yunbao.consultantNote')}
<div class="yb-chat-form">
<input type="text" class="yb-chat-form-input" id="yunbaoChatName" placeholder="${vm.$t('contactSales.namePlaceholder')}">
<input type="tel" class="yb-chat-form-input" id="yunbaoChatPhone" placeholder="${vm.$t('contactSales.phonePlaceholder')}">
<input type="text" class="yb-chat-form-input" id="yunbaoChatCompany" placeholder="${vm.$t('contactSales.companyPlaceholder')}">
<button class="yb-chat-form-submit" id="yunbaoChatSubmit">${vm.$t('yunbao.submit')}</button>
<div class="yb-chat-form-tip">${vm.$t('yunbao.infoNote')}</div>
</div>
</div>
</div>
`
body.appendChild(form)
body.scrollTop = body.scrollHeight
document.getElementById('yunbaoChatSubmit').addEventListener('click', () => this.submitForm())
},
async submitForm() {
const name = document.getElementById('yunbaoChatName').value.trim()
const phone = document.getElementById('yunbaoChatPhone').value.trim()
const company = document.getElementById('yunbaoChatCompany').value.trim()
const submitBtn = document.getElementById('yunbaoChatSubmit')
if (!name || !phone) {
this.addBotMsg(vm.$t('yunbao.nameRequired'))
return
}
if (!/^1[3-9]\d{9}$/.test(phone)) {
this.addBotMsg(vm.$t('yunbao.phoneInvalid'))
return
}
if (submitBtn && submitBtn.disabled) return
if (submitBtn) {
submitBtn.disabled = true
submitBtn.innerText = vm.$t('yunbao.submitting')
}
this.addUserMsg(vm.$t('yunbao.submitted'))
const productName = this.getProductName(this._selectedProduct)
const data = {
custom_type: '1',
name,
phone,
company,
email: '',
content: this._selectedProduct ? vm.$t('yunbao.consultingContent').replace('{product}', productName) : vm.$t('yunbao.defaultContent'),
source: '官网',
url_link: window.location.href
}
try {
const response = await reqNewHomeConsult(data)
if (response && response.status) {
this.addBotMsg(vm.$t('yunbao.success'))
return
}
this.addBotMsg((response && response.msg) || vm.$t('yunbao.submitFail'), [
{ text: vm.$t('yunbao.retry'), action: 'retrySubmit', primary: true }
])
} catch (error) {
this.addBotMsg(vm.$t('yunbao.networkFail'), [
{ text: vm.$t('yunbao.retry'), action: 'retrySubmit', primary: true }
])
} finally {
if (submitBtn) {
submitBtn.disabled = false
submitBtn.innerText = vm.$t('yunbao.submit')
}
}
}
}
},
getYunbaoChatHTML(config) {
return `
<div id="yunbaoModal" class="yb-assistant-modal-overlay">
<div class="yb-assistant-modal">
<div class="yb-assistant-modal-header">
<div class="yb-chat-avatar"><img src="${config.avatarUrl}" alt="${config.name}"></div>
<div class="yb-chat-header-info">
<div class="yb-chat-header-name">${config.name}</div>
<div class="yb-chat-header-status">${this.$t('yunbao.online')}</div>
</div>
<button class="yb-assistant-close-btn" id="yunbaoCloseBtn">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>
</button>
</div>
<div class="yb-chat-body" id="yunbaoChatBody"></div>
</div>
</div>
`
},
getYunbaoChatCSS() {
return `
.yb-assistant-modal-overlay{position:fixed;bottom:100px;right:24px;z-index:9999;display:none}
.yb-assistant-modal-overlay.active{display:block}
.yb-assistant-modal{background:rgba(255,255,255,0.85);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);border-radius:20px;width:400px;height:560px;display:flex;flex-direction:column;overflow:hidden;box-shadow:0 8px 32px rgba(59,130,246,0.08),0 0 0 1px rgba(255,255,255,0.6) inset;border:1px solid rgba(255,255,255,0.5);animation:ybChatSlideIn 0.35s cubic-bezier(0.34,1.56,0.64,1)}
@keyframes ybChatSlideIn{from{opacity:0;transform:translateY(20px) scale(0.95)}to{opacity:1;transform:translateY(0) scale(1)}}
@keyframes ybToastIn{from{opacity:0;transform:translateX(-50%) translateY(-10px)}to{opacity:1;transform:translateX(-50%) translateY(0)}}
@keyframes ybToastOut{from{opacity:1;transform:translateX(-50%) translateY(0)}to{opacity:0;transform:translateX(-50%) translateY(-10px)}}
.yb-assistant-modal-header{background:linear-gradient(135deg,rgba(240,247,255,0.9) 0%,rgba(255,255,255,0.7) 100%);backdrop-filter:blur(10px);padding:16px 20px;display:flex;align-items:center;gap:12px;flex-shrink:0;border-bottom:1px solid rgba(59,130,246,0.08)}
.yb-chat-avatar{width:48px;height:48px;border-radius:50%;overflow:visible;flex-shrink:0;display:flex;align-items:center;justify-content:center}
.yb-chat-avatar img{width:100px;height:60px;object-fit:contain;display:block}
.yb-chat-header-info{flex:1}
.yb-chat-header-name{font-size:15px;font-weight:600;color:#1e293b}
.yb-chat-header-status{font-size:12px;color:#64748b;display:flex;align-items:center;gap:4px}
.yb-chat-header-status:before{content:"";width:6px;height:6px;border-radius:50%;background:#22c55e;box-shadow:0 0 6px rgba(34,197,94,0.4)}
.yb-assistant-close-btn{width:32px;height:32px;background:rgba(0,0,0,0.04);border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all 0.2s;border:none}
.yb-assistant-close-btn:hover{background:rgba(0,0,0,0.08)}
.yb-assistant-close-btn svg{width:18px;height:18px;stroke:#64748b}
.yb-chat-body{flex:1;overflow-y:auto;padding:20px;display:flex;flex-direction:column;gap:16px;background:linear-gradient(180deg,rgba(240,247,255,0.3) 0%,rgba(255,255,255,0.1) 100%)}
.yb-chat-body::-webkit-scrollbar{width:4px}
.yb-chat-body::-webkit-scrollbar-thumb{background:rgba(59,130,246,0.15);border-radius:4px}
.yb-chat-msg{display:flex;gap:10px;animation:ybChatMsgIn 0.3s ease}
@keyframes ybChatMsgIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.yb-chat-msg-avatar{width:40px;height:40px;border-radius:50%;overflow:visible;flex-shrink:0;margin-top:2px;display:flex;align-items:center;justify-content:center}
.yb-chat-msg-avatar img{width:92px;height:40px;object-fit:contain;display:block}
.yb-chat-user-avatar{background:#e2e8f0;font-size:16px;overflow:hidden}
.yb-chat-user-avatar span{display:flex;align-items:center;justify-content:center;width:100%;height:100%}
.yb-chat-msg-bubble{background:#fff;border-radius:16px 16px 16px 4px;padding:12px 16px;font-size:14px;line-height:1.6;color:#334155;max-width:300px;box-shadow:0 1px 3px rgba(0,0,0,0.06)}
.yb-chat-msg-user{flex-direction:row-reverse}
.yb-chat-msg-user .yb-chat-msg-bubble{background:#1e293b;color:#fff;border-radius:16px 16px 4px 16px}
.yb-chat-options{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.yb-chat-option-btn{padding:8px 16px;border-radius:20px;border:1px solid rgba(59,130,246,0.2);background:rgba(255,255,255,0.8);backdrop-filter:blur(4px);font-size:13px;color:#3b82f6;cursor:pointer;transition:all 0.2s;white-space:nowrap}
.yb-chat-option-btn:hover{border-color:#3b82f6;background:rgba(59,130,246,0.06);box-shadow:0 2px 8px rgba(59,130,246,0.1)}
.yb-chat-option-btn.primary{background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-color:transparent;box-shadow:0 2px 8px rgba(59,130,246,0.25)}
.yb-chat-product-cards{display:flex;flex-direction:column;gap:10px;margin-top:10px}
.yb-chat-product-card{background:rgba(255,255,255,0.7);border:1px solid rgba(59,130,246,0.1);border-radius:12px;padding:10px 14px!important;height:92px!important;min-height:92px!important;max-height:92px!important;cursor:pointer;transition:all 0.2s;backdrop-filter:blur(4px);box-sizing:border-box;overflow:hidden;display:flex!important;flex-direction:column;justify-content:flex-start}
.yb-chat-product-card:hover{border-color:rgba(59,130,246,0.25);background:rgba(255,255,255,0.9);box-shadow:0 4px 16px rgba(59,130,246,0.08);transform:translateY(-1px)}
.yb-chat-product-card-title{font-size:14px;font-weight:600;color:#1e293b;margin-bottom:4px;line-height:1.3}
.yb-chat-product-card-desc{font-size:12px;color:#64748b;line-height:1.35;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.yb-chat-product-card-link{font-size:12px;color:#3b82f6;font-weight:500;display:inline-flex;align-items:center;gap:4px;line-height:1.2}
.yb-chat-tag-options{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.yb-chat-tag-btn{padding:6px 12px;border-radius:16px;border:1px solid rgba(59,130,246,0.15);background:rgba(255,255,255,0.7);font-size:12px;color:#3b82f6;cursor:pointer;transition:all 0.2s;backdrop-filter:blur(4px)}
.yb-chat-tag-btn:hover{border-color:#3b82f6;background:rgba(59,130,246,0.06);box-shadow:0 2px 8px rgba(59,130,246,0.1)}
.yb-chat-form{margin-top:10px;display:flex;flex-direction:column;gap:10px}
.yb-chat-form-input{width:100%;padding:10px 14px;border:1px solid rgba(59,130,246,0.15);border-radius:10px;font-size:13px;color:#1e293b;background:rgba(255,255,255,0.8);outline:none;transition:all 0.2s;box-sizing:border-box}
.yb-chat-form-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,0.08);background:#fff}
.yb-chat-form-input::placeholder{color:#94a3b8}
.yb-chat-form-submit{width:100%;padding:10px;background:#1a1a2e;color:#fff;border:none;border-radius:9999px;font-size:14px;font-weight:500;cursor:pointer;transition:all 0.2s;box-shadow:0 2px 8px rgba(26,26,46,0.2)}
.yb-chat-form-submit:hover{background:#0f0f1a;box-shadow:0 4px 12px rgba(26,26,46,0.3);transform:translateY(-1px)}
.yb-chat-form-submit:disabled{background:#cbd5e1;box-shadow:none;cursor:not-allowed}
.yb-chat-form-tip{font-size:11px;color:#94a3b8;text-align:center}
@media(max-width:480px){.yb-assistant-modal{width:calc(100vw - 32px);height:calc(100vh - 140px);right:0}.yb-assistant-modal-overlay{right:16px;bottom:90px}}
`
},
// 关闭弹窗
closeWindow() {
this.isShowChangeChat = false
},
onImageLoad() {
this.isShowPicLoading = false
console.log()
},
handleMouseEnter() { // 鼠标移入事件
this.isShow = true
if (this.isSend) {
this.contant()
}
// this.contant()
},
handleMouseLeave() { // 鼠标移出事件
this.isSend = true
this.src = ''
this.phone = ''
this.title = ''
this.isShow = false
this.isShowPicLoading = true
},
contant() { // 联系我们
const params = {
// userid: sessionStorage.getItem("userId")
}
if (this.url.indexOf('www') !== -1) {
params.domain = 'www'
}
contantAPI(params).then(res => {
this.isSend = false
this.isShowPicLoading = false
if (res.status) {
this.src = res.picture_url
this.phone = res.contactor_phone
} else {
this.$message({
message: res.msg,
type: 'error'
})
}
})
},
onSubmit() { // 点击确认申请试用
this.$refs.form.validate((valid) => {
if (valid) {
const pamars = {
customer: this.form.customer,
phone: this.form.phone,
unit: this.form.unit,
resources: this.form.resources,
userid: sessionStorage.getItem('userId')
}
applyAPI(pamars).then(res => {
if (res.status) {
this.dialogVisible = false
this.$message({
message: '成功申请试用',
type: 'success'
})
} else {
this.$message({
message: res.msg,
type: 'error'
})
}
})
}
})
},
tryUse() { // 申请试用
if (sessionStorage.getItem('userId')) {
this.dialogVisible = true
} else {
// window.open('https://www.opencomputing.cn/#/floatingBox')
this.$router.push('/floatingBox')
}
},
handleClose() {
this.$refs.form.resetFields()
this.dialogVisible = false
},
// 是否展示悬浮窗
isShowFloating() {
return false
}
}
}
</script>
<style lang="scss" scoped>
.box {
.contener {
.dialog {
width: 400px;
height: 150px;
background-color: #fff;
z-index: 100 !important;
position: fixed;
right: 80px;
bottom: 150px;
display: flex;
flex-direction: row;
border-radius: 5px 5px 5px 5px;
.phone {
display: flex;
flex-direction: column;
.sonOne {
font-size: 24px;
color: #1e92f8;
margin-bottom: 14px;
margin-top: 26px;
margin-left: 20px;
font-weight: 600;
}
.sonTwo {
font-size: 18px;
margin-bottom: 14px;
margin-left: 20px;
}
.sonThree {
font-size: 18px;
margin-left: 20px;
}
}
.img {
.nameCard {
font-size: 20px;
line-height: 150px;
}
img {
width: 90px;
height: 90px;
}
}
}
.floating-box {
/* 悬浮框的样式,例如背景色、边框、位置等 */
width: 80px;
height: 80px;
position: fixed;
bottom: 170px;
right: 0px;
background-color: #fff;
border: 1px solid #ccc;
padding: 10px;
z-index: 99 !important;
margin-bottom: 20px;
border-radius: 10px 0px 0px 10px;
background-color: #1890ff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
color: white;
font-size: 28px;
}
span {
font-size: 14px;
color: white;
}
/* 其他样式 */
}
.floating-box1 {
/* 悬浮框的样式,例如背景色、边框、位置等 */
cursor: pointer;
width: 80px;
height: 80px;
position: fixed;
bottom: 80px;
right: 0px;
background-color: #fff;
border: 1px solid #ccc;
padding: 10px;
z-index: 99 !important;
margin-bottom: 20px;
border-radius: 10px 0px 0px 10px;
background-color: #1890ff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
color: white;
font-size: 28px;
}
span {
font-size: 14px;
color: white;
}
/* 其他样式 */
}
}
.contenerMobile {
.dialog {
width: 200px;
height: 100px;
background-color: #fff;
z-index: 100 !important;
position: fixed;
right: 80px;
bottom: 150px;
display: flex;
flex-direction: row;
border-radius: 5px 5px 5px 5px;
.phone {
display: flex;
flex-direction: column;
.sonOne {
font-size: 14px;
color: #1e92f8;
margin-bottom: 14px;
margin-top: 16px;
margin-left: 10px;
font-weight: 600;
}
.sonTwo {
font-size: 12px;
margin-bottom: 14px;
margin-left: 10px;
}
.sonThree {
font-size: 12px;
margin-left: 10px;
}
}
.img {
padding-left: 20px;
padding-top: 20px;
.nameCard {
font-size: 20px;
line-height: 150px;
}
img {
width: 50px;
height: 50px;
}
}
}
.floating-box {
/* 悬浮框的样式,例如背景色、边框、位置等 */
width: 60px;
height: 60px;
position: fixed;
bottom: 170px;
right: 0px;
background-color: #fff;
border: 1px solid #ccc;
padding: 5px;
z-index: 99 !important;
margin-bottom: 20px;
border-radius: 10px 0px 0px 10px;
background-color: #1890ff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
color: white;
font-size: 20px;
}
span {
font-size: 8px;
color: white;
}
/* 其他样式 */
}
.floating-box1 {
/* 悬浮框的样式,例如背景色、边框、位置等 */
cursor: pointer;
width: 60px;
height: 60px;
position: fixed;
bottom: 80px;
right: 0px;
background-color: #fff;
border: 1px solid #ccc;
padding: 5px;
z-index: 99 !important;
margin-bottom: 20px;
border-radius: 10px 0px 0px 10px;
background-color: #1890ff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
color: white;
font-size: 20px;
}
span {
font-size: 8px;
color: white;
}
/* 其他样式 */
}
.floating-box2 {
/* 悬浮框的样式,例如背景色、边框、位置等 */
cursor: pointer;
width: 80px;
height: 80px;
position: fixed;
bottom: 80px;
right: 0px;
background-color: #fff;
border: 1px solid #ccc;
padding: 10px;
z-index: 99 !important;
margin-bottom: 20px;
border-radius: 10px 0px 0px 10px;
background-color: #1890ff;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
color: white;
font-size: 28px;
}
span {
font-size: 14px;
color: white;
}
}
}
}
.hiddenBtn:hover {
background-color: #1890ff !important;
i {
color: white !important;
}
}
.slide-enter-active {
animation: slide-in 0.8s;
}
.slide-leave-active {
animation: slide-out 0.8s;
}
@keyframes slide-in {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes slide-out {
from {
transform: translateX(0);
}
to {
transform: translateX(100%);
}
}
.new-floating {
img {
position: absolute;
top: -28px;
width: 40px;
height: 40px;
z-index: 99;
}
position: relative;
background: #fff;
border-radius: 4px;
width: 40px;
height: 100px;
z-index: 2;
position: fixed;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
top: 250px;
right: 10px;
//overflow: hidden;
padding: 10px 0;
background: rgba(255, 255, 255, 0.8);
box-shadow: 0px 0px 20px 0px rgba(185, 208, 210, 0.15);
border-radius: 50px 50px 50px 50px;
background: linear-gradient(180deg, #275AFF 0%, #2EBDFA 100%);
border-radius: 50px 50px 50px 50px;
}
.cloud-contact-us-i {
background-image: url(https://bce.bdstatic.com/portal-cloud-server/images/pendant-right.png);
background-position: -125px 0;
background-size: 300px 20px;
height: 20px;
width: 20px;
}
.cloud-contact-us {
align-items: center;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
display: flex;
justify-content: center;
color: white;
margin: 0;
padding: 0;
position: relative;
width: .38rem;
flex-direction: column;
&:hover {
.cloud-contact-us-i {
background-position: -100px 0
}
//.active {
// border: 5px solid red;
// background-color: white !important;
// color: blue !important;
//}
}
}
//.cloud-contact-us-i {
// background-position: -100px 0
//}
.cloud-contact-us.active {
background-color: #fff;
box-shadow: none
}
.cloud-contact-us:after {
background: rgba(34, 34, 34, .08);
bottom: 0;
content: "";
display: block;
height: 1px;
left: 10px;
position: absolute;
width: 22px;
}
.cart-entry-wrapper:after {
background: rgba(34, 34, 34, .08);
bottom: 34px;
content: "";
display: block;
height: 1px;
left: 10px;
position: absolute;
width: 22px;
}
.cart-entry {
background: #fff;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
cursor: pointer;
height: 40px;
padding: 10px;
position: relative;
width: 40px;
&:hover {
.cart-icon {
background-position: 0 0;
}
}
}
.cart-icon {
background-image: url(https://bce.bdstatic.com/portal-cloud-server/images/pendant-right.png);
background-position: -25px 0;
background-size: 300px 20px;
height: 20px;
width: 20px;
position: relative;
display: block;
}
.cart-entry-wrapper {
border-radius: 4px;
bottom: 190px !important;
right: 12px;
}
//侧边栏
.cloud-contact-us-spread-container {
position: fixed;
z-index: 999999 !important;
animation: spreadContrast .3s ease-out;
top: 250px;
right: 40px
}
.cloud-contact-us-spread {
width: 280px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px 0 rgba(34, 34, 34, .08);
height: 90px;
margin-right: 20px;
position: relative;
}
.cloud-contact-us-tel {
animation: spreadLineOpacity .3s ease-out forwards, spreadLine1 .3s ease-out .02s forwards;
opacity: 1;
top: 24px;
}
* {
list-style: none;
}
.cloud-contact-us-tit {
color: #222;
font-family: PingFangSC-Medium;
font-size: 14px;
font-weight: 500;
line-height: 24px;
}
.cloud-contact-us-con {
color: #2468f2;
}
.cloud-contact-us-icon {
background: url(https://bce.bdstatic.com/p3m/common-service/uploads/custom_6390d23.png) no-repeat;
background-size: 295px 20px;
float: left;
height: 20px;
margin-top: 2px;
width: 20px;
background-position: -100px 0;
}
.el-icon-video-camera {
padding: 5px 0;
&:hover {
color: blue;
cursor: pointer;
}
}
.changeChat {
width: 250px;
height: 100px;
position: fixed;
bottom: 0;
right: 10px;
animation: slideInRight 0.5s forwards;
background-color: white;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
padding: 10px;
z-index: 11;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.changeChat-fade-leave-active {
transition: opacity 0.5s;
}
.changeChat-fade-leave-to {
opacity: 0;
}
.floating-consult {
position: fixed;
right: 18px;
bottom: 128px;
z-index: 100;
}
.floating-consult-btn {
display: inline-flex;
align-items: center;
flex-direction: column;
text-decoration: none;
background: #ffffff;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.14);
transition: all 0.25s ease;
}
.floating-consult-btn:hover {
transform: translateY(-3px);
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.2);
}
.floating-consult-btn.primary {
width: 80px;
height: 80px;
padding: 12px 8px;
border-radius: 50%;
gap: 8px;
}
.floating-consult-icon {
position: relative;
width: 100%;
height: 100%;
}
.floating-consult-icon img {
width: 100%;
height: 60px;
// height: 100%;
object-fit: cover;
border-radius: 50%;
}
.consult-badge {
position: absolute;
top: -2px;
right: -2px;
width: 10px;
height: 10px;
border-radius: 50%;
border: 2px solid #fff;
background: #ef4444;
}
.floating-consult-text {
writing-mode: vertical-rl;
text-orientation: mixed;
font-size: 12px;
color: #1f2937;
letter-spacing: 2px;
}
</style>
<style>
.apply-use {
margin-top: 8vh !important;
width: 500px !important;
}
@media screen and (max-width: 760px) {
.apply-use {
width: 90% !important;
}
}
</style>