feat: 添加AI智能客服(弹窗+嵌入式聊天页面,对接扣子API)
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<view v-if="visible" class="ai-chat-panel">
|
||||
<!-- 头部 -->
|
||||
<view class="chat-header">
|
||||
<text>🤖 金久信 AI 智能客服</text>
|
||||
<text class="close" @click="visible = false">×</text>
|
||||
</view>
|
||||
<!-- 消息列表 -->
|
||||
<scroll-view scroll-y class="msg-list" :scroll-into-view="scrollId" scroll-with-animation>
|
||||
<!-- 欢迎消息(仅在没有对话时显示) -->
|
||||
<view v-if="messages.length === 0" class="msg-item assistant" id="msg-welcome">
|
||||
<view class="bubble">
|
||||
您好!我是金久信签约宝AI智能客服,可以帮您解答金久信签约宝使用过程中注册、操作、适用场景等问题。请问有什么可以帮您?
|
||||
<view class="quick-btns">
|
||||
<view class="quick-btn" @click="chatQuickSend('注册准备资料事项')">注册准备资料事项</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('关键字无法识别')">关键字无法识别</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('如何下询价单')">金久信签约宝法律效力</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('电子签约不适用场景')">电子签约不适用场景</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 对话消息 -->
|
||||
<view v-for="(msg, i) in messages" :key="i" :id="'msg' + i" :class="['msg-item', msg.role]">
|
||||
<view class="bubble" v-html="msg.content"></view>
|
||||
</view>
|
||||
<view v-if="loading" class="msg-item assistant" id="msg-loading">
|
||||
<view class="bubble typing">思考中...</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 输入框 -->
|
||||
<view class="input-bar">
|
||||
<input v-model="inputText" @confirm="send" placeholder="输入您的问题..." />
|
||||
<button @click="send">发送</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ai-chat",
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
inputText: '',
|
||||
messages: [],
|
||||
loading: false,
|
||||
conversationId: null,
|
||||
scrollId: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
this.visible = !this.visible;
|
||||
if (this.visible) {
|
||||
this.$nextTick(() => this.scrollToBottom());
|
||||
}
|
||||
},
|
||||
quickSend(text) {
|
||||
this.inputText = text;
|
||||
this.send();
|
||||
},
|
||||
async send() {
|
||||
const msg = this.inputText.trim();
|
||||
if (!msg || this.loading) return;
|
||||
this.inputText = '';
|
||||
this.messages.push({
|
||||
role: 'user',
|
||||
content: msg
|
||||
});
|
||||
this.loading = true;
|
||||
this.scrollToBottom();
|
||||
|
||||
try {
|
||||
const res = await this.vk.callFunction({
|
||||
url: 'client/ai/pub/chat',
|
||||
data: { message: msg, bot_id: '7683509749475819554' }
|
||||
});
|
||||
if (res.data.conversation_id) this.conversationId = res.data.conversation_id;
|
||||
this.messages.push({
|
||||
role: 'assistant',
|
||||
content: res.data.answer
|
||||
});
|
||||
} catch (e) {
|
||||
this.messages.push({
|
||||
role: 'assistant',
|
||||
content: '网络异常,请稍后重试'
|
||||
});
|
||||
}
|
||||
this.loading = false;
|
||||
this.scrollToBottom();
|
||||
},
|
||||
scrollToBottom() {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (this.messages.length === 0) {
|
||||
this.scrollId = 'msg-welcome';
|
||||
} else if (this.loading) {
|
||||
this.scrollId = 'msg-loading';
|
||||
} else {
|
||||
this.scrollId = 'msg' + (this.messages.length - 1);
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ai-chat-panel {
|
||||
position: fixed;
|
||||
bottom: 90px;
|
||||
right: 50px;
|
||||
width: 380px;
|
||||
height: 520px;
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.2);
|
||||
z-index: 99999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.chat-header {
|
||||
padding: 12px 16px;
|
||||
background: linear-gradient(135deg, #a92924, #d4574e);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.chat-header .close {
|
||||
cursor: pointer;
|
||||
font-size: 22px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.chat-header .close:hover { opacity: 1; }
|
||||
.msg-list {
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
background: #f7f8fa;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.msg-item { margin-bottom: 10px; display: flex; }
|
||||
.msg-item.user { justify-content: flex-end; }
|
||||
.msg-item.assistant { justify-content: flex-start; }
|
||||
.msg-item .bubble {
|
||||
max-width: 75%;
|
||||
padding: 10px 14px;
|
||||
border-radius: 12px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
word-break: break-word;
|
||||
}
|
||||
.msg-item.user .bubble {
|
||||
background: #a92924;
|
||||
color: #fff;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.msg-item.assistant .bubble {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
border: 1px solid #eee;
|
||||
border-top-left-radius: 4px;
|
||||
}
|
||||
.msg-item.assistant .bubble.typing { color: #999; }
|
||||
.quick-btns {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.quick-btn {
|
||||
padding: 5px 12px;
|
||||
border-radius: 14px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #a92924;
|
||||
color: #a92924;
|
||||
background: #fff;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.quick-btn:hover {
|
||||
background: #a92924;
|
||||
color: #fff;
|
||||
}
|
||||
.input-bar {
|
||||
padding: 10px 12px;
|
||||
border-top: 1px solid #eee;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
.input-bar input {
|
||||
flex: 1;
|
||||
height: 36px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 0 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.input-bar input:focus { border-color: #a92924; outline: none; }
|
||||
.input-bar button {
|
||||
padding: 0 16px;
|
||||
height: 36px;
|
||||
background: #a92924;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.input-bar button:hover { background: #982520; }
|
||||
</style>
|
||||
@@ -22,13 +22,11 @@
|
||||
<!-- </a>-->
|
||||
<!-- </li>-->
|
||||
<li class="side-steel-kefu">
|
||||
<a rel="nofollow"
|
||||
href="http://wpa.qq.com/msgrd?v=3&uin=949419497&site=qq&menu=yes"
|
||||
target="_blank">
|
||||
<a rel="nofollow" href="javascript:;" @click="$refs.aiChat.toggle()">
|
||||
<div class="item">
|
||||
<i class="wag-icon"><img src="@/static/images/cl4.png"></i>
|
||||
</div>
|
||||
<span>在线客服</span>
|
||||
<span>AI 客服</span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- <li class="side-steel-counter">-->
|
||||
@@ -66,6 +64,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ai-chat ref="aiChat" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
+375
-109
@@ -60,7 +60,23 @@
|
||||
</view>
|
||||
<text class="ml-20">认证信息变更</text>
|
||||
</view>
|
||||
<div class="menu-group-title">AI 智能服务</div>
|
||||
<el-menu @select="menuSelect" :default-active="menuIndex" class="el-menu-vertical-demo">
|
||||
<el-menu-item index="3">
|
||||
<span class="icon">🤖</span> AI 客服
|
||||
</el-menu-item>
|
||||
<el-menu-item index="4">
|
||||
<span class="icon">📋</span> 合同审查
|
||||
</el-menu-item>
|
||||
<el-menu-item index="5">
|
||||
<span class="icon">📈</span> 我的报告
|
||||
</el-menu-item>
|
||||
<el-menu-item index="6">
|
||||
<span class="icon">💎</span> 积分管理
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="18">
|
||||
<view class="flex flex-col justify-start items-start" v-if="isSignLog">
|
||||
<view class="trade-method">
|
||||
@@ -146,7 +162,8 @@
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view class="contract-list" v-if="!isSign && !isSignIntro && !isSignLog && !isSignFlow && !isSignTips">
|
||||
<view class="contract-list"
|
||||
v-if="!isSign && !isSignIntro && !isSignLog && !isSignFlow && !isSignTips">
|
||||
<view class="trade-method">
|
||||
<!-- <view @click="changeTradeMethod(null)" class="trade-method-item"-->
|
||||
<!-- :class="{active: (formData.tradeMethod === null && formData.type === null)}">全部-->
|
||||
@@ -195,30 +212,24 @@
|
||||
</el-tag>
|
||||
<template v-if="item.sheet">
|
||||
<view class="ml-20">
|
||||
<el-tag size="mini" v-if="item.sheet.tradeMethod === 0" type="primary"
|
||||
>自主交易
|
||||
<el-tag size="mini" v-if="item.sheet.tradeMethod === 0" type="primary">自主交易
|
||||
</el-tag>
|
||||
<el-tag size="mini" v-if="item.sheet.tradeMethod === 1" type="success"
|
||||
>金久信公证
|
||||
<el-tag size="mini" v-if="item.sheet.tradeMethod === 1" type="success">金久信公证
|
||||
</el-tag>
|
||||
</view>
|
||||
<view class="ml-20">
|
||||
<el-tag size="mini" effect="plain" v-if="item.sheet.signMethod === 0"
|
||||
type="success"
|
||||
>标准合同
|
||||
type="success">标准合同
|
||||
</el-tag>
|
||||
<el-tag size="mini" effect="plain" v-if="item.sheet.signMethod === 2"
|
||||
type="primary"
|
||||
>双方协商合同
|
||||
type="primary">双方协商合同
|
||||
</el-tag>
|
||||
<el-tag size="mini" effect="plain" v-if="item.sheet.signMethod === 1"
|
||||
type="warning"
|
||||
>线下合同
|
||||
type="warning">线下合同
|
||||
</el-tag>
|
||||
</view>
|
||||
</template>
|
||||
<el-tag size="mini" v-if="item.contract.tradeMethod === 1" type="success"
|
||||
>金久信公证
|
||||
<el-tag size="mini" v-if="item.contract.tradeMethod === 1" type="success">金久信公证
|
||||
</el-tag>
|
||||
<view class="contract-product" v-if="item.contract.status > 0">
|
||||
{{ item.contract.docTitle }}
|
||||
@@ -271,14 +282,16 @@
|
||||
dayjs(item.contract.signEndDate).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}
|
||||
</view>
|
||||
<view v-if="item.contract.type === 'sign' && item.contract.payUser && item.contract.payUser.user">
|
||||
<view
|
||||
v-if="item.contract.type === 'sign' && item.contract.payUser && item.contract.payUser.user">
|
||||
费用承担方:{{
|
||||
item.contract.payUser.user.accountType === 2 ?
|
||||
item.contract.payUser.user.company.companyName : item.contract.payUser.user.person.personName
|
||||
}}
|
||||
</view>
|
||||
<template v-if="parseInt(item.contract.status) > 0">
|
||||
<view v-for="(party, partyIndex) in item.contract.partyList.filter(p => p.role !== 'third')"
|
||||
<view
|
||||
v-for="(party, partyIndex) in item.contract.partyList.filter(p => p.role !== 'third')"
|
||||
:key="`p_${partyIndex}`">
|
||||
<template v-if="party.userId === item.contract.userId">
|
||||
发起方签订完成时间:{{
|
||||
@@ -296,7 +309,8 @@
|
||||
}}
|
||||
</template>
|
||||
</view>
|
||||
<view v-for="(party, partyIndex) in item.contract.partyList.filter(p => p.role === 'third')"
|
||||
<view
|
||||
v-for="(party, partyIndex) in item.contract.partyList.filter(p => p.role === 'third')"
|
||||
:key="`t_${partyIndex}`">
|
||||
第{{ numToChForThird[partyIndex] }}方签订完成时间:{{
|
||||
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
@@ -312,9 +326,8 @@
|
||||
v-if="item.contract.status === 0 && item.contract.userId === vk.getVuex('$user.userInfo._id')"
|
||||
@click="createContract(item.contract)" size="mini" type="primary">创建合同
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item.contract.isMine"
|
||||
@click="delContract(item.contract)" size="mini" type="text">
|
||||
<el-button v-if="item.contract.isMine" @click="delContract(item.contract)"
|
||||
size="mini" type="text">
|
||||
删除合同
|
||||
</el-button>
|
||||
<template v-if="parseInt(item.contract.status) === 1">
|
||||
@@ -324,18 +337,14 @@
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-if="parseInt(item.contract.status) === 2">
|
||||
<el-button
|
||||
@click="viewContract(item.contract)"
|
||||
size="mini" plain>
|
||||
<el-button @click="viewContract(item.contract)" size="mini" plain>
|
||||
{{ parseInt(item.contract.signType) === 1 ? '查看单据' : '查看合同' }}
|
||||
</el-button>
|
||||
<el-button @click="downloadContract(item.contract.transactionId)"
|
||||
type="primary"
|
||||
<el-button @click="downloadContract(item.contract.transactionId)" type="primary"
|
||||
size="mini" plain>
|
||||
{{ parseInt(item.contract.signType) === 1 ? '下载单据' : '下载合同' }}
|
||||
</el-button>
|
||||
<el-button @click="payDownloadContract(item.contract)"
|
||||
size="mini" plain>
|
||||
<el-button @click="payDownloadContract(item.contract)" size="mini" plain>
|
||||
{{
|
||||
parseInt(item.contract.signType) === 1 ? '下载单据(付费司法调证)' : '下载合同(付费司法调证)'
|
||||
}}
|
||||
@@ -350,10 +359,8 @@
|
||||
(item.order && item.order.orderStatus === 4) ? '订单已结束' : ([5, 6].includes(item.order.orderStatus) ? '订单已终止' : (item.role === 'buyer' ? '去付款' : '去请款'))
|
||||
}}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item.contract.otherFile && item.contract.otherFile.length > 0"
|
||||
@click="openDownload(item.contract.otherFile)" plain
|
||||
size="mini"
|
||||
<el-button v-if="item.contract.otherFile && item.contract.otherFile.length > 0"
|
||||
@click="openDownload(item.contract.otherFile)" plain size="mini"
|
||||
type="info">查看附件
|
||||
</el-button>
|
||||
</view>
|
||||
@@ -365,8 +372,8 @@
|
||||
<view class="">
|
||||
<el-button @click.native="changeContract(item.contract)"
|
||||
v-if="((item.sheet && item.sheet.signMethod === 2) || item.contract.type === 'sign' || item.contract.type === 'self-support') && item.contract.status === 1
|
||||
&& item.contract.userId === vk.getVuex('$user.userInfo._id') && item.contract.signCount === 0"
|
||||
size="mini" type="primary">修改合同内容
|
||||
&& item.contract.userId === vk.getVuex('$user.userInfo._id') && item.contract.signCount === 0" size="mini"
|
||||
type="primary">修改合同内容
|
||||
</el-button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -384,21 +391,20 @@
|
||||
</view>
|
||||
<view class="text-main mt-10">温馨提示:尊敬的用户如果您的剩余金久信签约宝次数为0次,请先进行购买,再进行签约。</view>
|
||||
<vk-data-form ref="form2" v-model="form2.data" :action="form2.props.action"
|
||||
:columns="form2.props.columns"
|
||||
:rules="form2.props.rules" :form-type="form2.props.formType"
|
||||
:loading.sync="form2.props.loading" :show-cancel="false"
|
||||
:auto-close="true" label-width="140px" @success="onFormSuccess">
|
||||
:columns="form2.props.columns" :rules="form2.props.rules" :form-type="form2.props.formType"
|
||||
:loading.sync="form2.props.loading" :show-cancel="false" :auto-close="true"
|
||||
label-width="140px" @success="onFormSuccess">
|
||||
<template v-slot:download>
|
||||
<el-button size="mini" type="text" @click="downloadContractTemplate">点击下载
|
||||
</el-button>
|
||||
</template>
|
||||
<template v-slot:contractFile>
|
||||
<vk-data-upload v-model="form2.data.contractFile" :cloudPathRemoveChinese="false" list-type="text"
|
||||
accept=".pdf" :on-success="uploadSuccess" ref="uploader" :before-upload="beforeUpload"
|
||||
:show-file-list="false">
|
||||
<vk-data-upload v-model="form2.data.contractFile" :cloudPathRemoveChinese="false"
|
||||
list-type="text" accept=".pdf" :on-success="uploadSuccess" ref="uploader"
|
||||
:before-upload="beforeUpload" :show-file-list="false">
|
||||
</vk-data-upload>
|
||||
<view class="text-main text-24 my-15 pointer" @click="openPreview(form2.data.contractFile)"
|
||||
v-if="form2.data.contractFile">预览:
|
||||
<view class="text-main text-24 my-15 pointer"
|
||||
@click="openPreview(form2.data.contractFile)" v-if="form2.data.contractFile">预览:
|
||||
{{ form2.data.contractFile[form2.data.contractFile.length - 1].split('-').pop() }}
|
||||
</view>
|
||||
<view class="tips text-24 text-gray">
|
||||
@@ -406,11 +412,8 @@
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:signEndDate>
|
||||
<el-date-picker
|
||||
:popper-class="'currentDatePickerClass'"
|
||||
v-model="form2.data.signEndDate"
|
||||
type="datetime"
|
||||
placeholder="选择签署截止日期">
|
||||
<el-date-picker :popper-class="'currentDatePickerClass'"
|
||||
v-model="form2.data.signEndDate" type="datetime" placeholder="选择签署截止日期">
|
||||
</el-date-picker>
|
||||
</template>
|
||||
<template v-slot:tips>
|
||||
@@ -424,8 +427,7 @@
|
||||
class="flex justify-start items-center mb-10 ">
|
||||
<span>第{{ numToChForThird[index] }}方</span>
|
||||
<div class="mx-15">
|
||||
<el-input v-model="form2.data.thirdList[index].phone"
|
||||
placeholder="请输入第三方手机号"/>
|
||||
<el-input v-model="form2.data.thirdList[index].phone" placeholder="请输入第三方手机号" />
|
||||
</div>
|
||||
<div>
|
||||
<el-input v-model="form2.data.thirdList[index].signKeyword"
|
||||
@@ -434,8 +436,7 @@
|
||||
<div class="flex justify-start items-center">
|
||||
<i class="el-icon-circle-plus pointer text-main text-50 ml-35"
|
||||
@click="addThird" />
|
||||
<i class="el-icon-remove pointer text-50 ml-35"
|
||||
@click="removeThird(index)"/>
|
||||
<i class="el-icon-remove pointer text-50 ml-35" @click="removeThird(index)" />
|
||||
<i title="上移" class="el-icon-arrow-up pointer text-50 ml-35" v-if="index > 0"
|
||||
@click="thirdMoveUp(index)" />
|
||||
<i title="下移" class="el-icon-arrow-down pointer text-50 ml-35"
|
||||
@@ -448,7 +449,8 @@
|
||||
</template>
|
||||
<template v-slot:footer="{ loading }">
|
||||
<view style="text-align: center;">
|
||||
<el-button :loading="loading" type="primary" @click="form2.props.action">提交</el-button>
|
||||
<el-button :loading="loading" type="primary"
|
||||
@click="form2.props.action">提交</el-button>
|
||||
</view>
|
||||
</template>
|
||||
</vk-data-form>
|
||||
@@ -462,6 +464,39 @@
|
||||
<view v-if="isSignTips" class="bg-white p-20">
|
||||
<div v-html="signTips"></div>
|
||||
</view>
|
||||
<!-- AI 客服(嵌入式) -->
|
||||
<view v-if="menuIndex === '3'" class="ai-chat-embed">
|
||||
<view class="chat-header-bar">
|
||||
<text class="chat-title">🤖 金久信签约宝 AI 智能客服</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="chat-msg-list" :scroll-into-view="chatScrollId" scroll-with-animation>
|
||||
<view v-if="chatMessages.length === 0" class="chat-row left" id="chat-welcome">
|
||||
<view class="chat-avatar">🤖</view>
|
||||
<view class="chat-bubble">
|
||||
您好!我是金久信签约宝AI智能客服,可以帮您解答金久信签约宝使用过程中注册、操作、适用场景等问题。请问有什么可以帮您?
|
||||
<view class="quick-btns">
|
||||
<view class="quick-btn" @click="chatQuickSend('注册准备资料事项')">注册准备资料事项</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('关键字无法识别')">关键字无法识别</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('如何下询价单')">金久信签约宝法律效力</view>
|
||||
<view class="quick-btn" @click="chatQuickSend('电子签约不适用场景')">电子签约不适用场景</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for="(msg, i) in chatMessages" :key="i" :id="'chat-msg' + i"
|
||||
:class="['chat-row', msg.role === 'user' ? 'right' : 'left']">
|
||||
<view v-if="msg.role !== 'user'" class="chat-avatar">🤖</view>
|
||||
<view class="chat-bubble" v-html="msg.content"></view>
|
||||
</view>
|
||||
<view v-if="chatLoading" class="chat-row left" id="chat-loading">
|
||||
<view class="chat-avatar">🤖</view>
|
||||
<view class="chat-bubble typing">思考中...</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="chat-input-bar">
|
||||
<input v-model="chatInput" @confirm="chatSend" placeholder="输入您的问题..." />
|
||||
<view class="chat-send-btn" @click="chatSend">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -470,9 +505,8 @@
|
||||
|
||||
<el-dialog :visible.sync="form1.props.show" width="70%">
|
||||
<vk-data-form ref="form1" v-model="form1.data" :action="form1.props.action" :columns="form1.props.columns"
|
||||
:rules="form1.props.rules" :form-type="form1.props.formType"
|
||||
:loading.sync="form1.props.loading" :show-cancel="false"
|
||||
:auto-close="true" label-width="140px" @success="onFormSuccess">
|
||||
:rules="form1.props.rules" :form-type="form1.props.formType" :loading.sync="form1.props.loading"
|
||||
:show-cancel="false" :auto-close="true" label-width="140px" @success="onFormSuccess">
|
||||
<template v-slot:contractFile>
|
||||
<vk-data-upload v-model="form1.data.contractFile" :cloudPathRemoveChinese="false" list-type="text"
|
||||
accept=".pdf" :on-success="uploadSuccess1" ref="uploader1" :before-upload="beforeUpload"
|
||||
@@ -494,23 +528,18 @@
|
||||
class="flex justify-start items-center mb-10 ">
|
||||
<span>第{{ numToChForThird[index] }}方</span>
|
||||
<div class="mx-15">
|
||||
<el-input v-model="form1.data.thirdList[index].phone"
|
||||
placeholder="请输入第三方手机号"/>
|
||||
<el-input v-model="form1.data.thirdList[index].phone" placeholder="请输入第三方手机号" />
|
||||
</div>
|
||||
<div>
|
||||
<el-input v-model="form1.data.thirdList[index].signKeyword"
|
||||
placeholder="请输入第三方签章关键字"/>
|
||||
<el-input v-model="form1.data.thirdList[index].signKeyword" placeholder="请输入第三方签章关键字" />
|
||||
</div>
|
||||
<div class="flex justify-start items-center">
|
||||
<i class="el-icon-circle-plus pointer text-main text-50 ml-35"
|
||||
@click="addThird1"/>
|
||||
<i class="el-icon-remove pointer text-50 ml-35"
|
||||
@click="removeThird1(index)"/>
|
||||
<i class="el-icon-circle-plus pointer text-main text-50 ml-35" @click="addThird1" />
|
||||
<i class="el-icon-remove pointer text-50 ml-35" @click="removeThird1(index)" />
|
||||
<i title="上移" class="el-icon-arrow-up pointer text-50 ml-35" v-if="index > 0"
|
||||
@click="thirdMoveUp1(index)" />
|
||||
<i title="下移" class="el-icon-arrow-down pointer text-50 ml-35"
|
||||
@click="thirdMoveDown1(index)"
|
||||
v-if="index < form1.data.thirdList.length - 1"/>
|
||||
@click="thirdMoveDown1(index)" v-if="index < form1.data.thirdList.length - 1" />
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-25 text-gray mt-20">如无第三方签约可忽略,签章关键字使用方法同下。</p>
|
||||
@@ -529,8 +558,7 @@
|
||||
<div class="flex justify-center items-center">
|
||||
<div class="p-20 rounded m-20 shadow flex flex-col justify-center items-center flex-1 pointer"
|
||||
:class="[selectedQyb === item._id ? 'buy-quote-mode-active' : '']"
|
||||
v-for="(item, index) in qybPackageList" :key="index"
|
||||
@click="selectedQyb = item._id">
|
||||
v-for="(item, index) in qybPackageList" :key="index" @click="selectedQyb = item._id">
|
||||
<p>{{ item.amount }}元</p>
|
||||
<p>可获得{{ item.getNum }}次</p>
|
||||
</div>
|
||||
@@ -581,17 +609,39 @@
|
||||
<el-dialog title="支付凭证" :visible.sync="showPayVoucher" width="50%">
|
||||
<el-image :src="payVoucher" :preview-src-list="[payVoucher]" />
|
||||
</el-dialog>
|
||||
<!-- 右侧悬浮工具栏 -->
|
||||
<div class="float-toolbar">
|
||||
<div class="tool-item ai-hot">
|
||||
<a rel="nofollow" href="javascript:;" @click="$refs.aiChat.toggle()">
|
||||
<div class="item">
|
||||
<i class="wag-icon"><img src="@/static/images/cl4.png"></i>
|
||||
</div>
|
||||
<span class="tool-label">AI客服</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="tool-item ai-hot">
|
||||
<span class="tool-icon">📑</span>
|
||||
<span class="tool-label">合同审查</span>
|
||||
</div>
|
||||
</div>
|
||||
<ai-chat ref="aiChat" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {Agreement} from "@icon-park/vue";
|
||||
import {
|
||||
Agreement
|
||||
} from "@icon-park/vue";
|
||||
import dayjs from "dayjs";
|
||||
import {Loading} from "element-ui";
|
||||
import {
|
||||
Loading
|
||||
} from "element-ui";
|
||||
|
||||
|
||||
export default {
|
||||
components: {Agreement},
|
||||
components: {
|
||||
Agreement
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
numToChForThird: ['三', '四', '五', '六', '七', '八', '九', '十'],
|
||||
@@ -627,6 +677,12 @@ export default {
|
||||
showInvoice: false,
|
||||
isSignTips: false,
|
||||
signTips: '',
|
||||
// AI 客服数据
|
||||
chatMessages: [],
|
||||
chatInput: '',
|
||||
chatLoading: false,
|
||||
chatConversationId: null,
|
||||
chatScrollId: '',
|
||||
invoiceForm: {
|
||||
id: null,
|
||||
name: null,
|
||||
@@ -650,7 +706,10 @@ export default {
|
||||
buyerSignKeyword: '',
|
||||
sellerSignKeyword: '',
|
||||
otherFile: '',
|
||||
thirdList: [{phone: '', signKeyword: ''}],
|
||||
thirdList: [{
|
||||
phone: '',
|
||||
signKeyword: ''
|
||||
}],
|
||||
},
|
||||
// 表单属性
|
||||
props: {
|
||||
@@ -663,7 +722,9 @@ export default {
|
||||
thirdKeywords.push(item.signKeyword)
|
||||
}
|
||||
}
|
||||
uni.showLoading({title: '查验中'})
|
||||
uni.showLoading({
|
||||
title: '查验中'
|
||||
})
|
||||
let file = this.form1.data.contractFile[this.form1.data.contractFile.length - 1]
|
||||
if (Array.isArray(file)) file = file[file.length - 1]
|
||||
vk.request({
|
||||
@@ -690,7 +751,8 @@ export default {
|
||||
else {
|
||||
uni.hideLoading()
|
||||
this.form1.props.loading = true
|
||||
this.form1.data.thirdList = this.form1.data.thirdList.filter(item => item.phone && item.signKeyword)
|
||||
this.form1.data.thirdList = this.form1.data.thirdList.filter(
|
||||
item => item.phone && item.signKeyword)
|
||||
if (this.form1.data.thirdList.length > 0) {
|
||||
for (let i = 0; i < this.form1.data.thirdList.length; i++) {
|
||||
const item = this.form1.data.thirdList[i]
|
||||
@@ -721,7 +783,9 @@ export default {
|
||||
this.form1.props.loading = false
|
||||
return false
|
||||
}
|
||||
const res = await this.$confirm(`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`, '提示', {
|
||||
const res = await this.$confirm(
|
||||
`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`,
|
||||
'提示', {
|
||||
confirmButtonText: '知悉同意',
|
||||
showCancelButton: false,
|
||||
type: 'warning',
|
||||
@@ -732,7 +796,9 @@ export default {
|
||||
url: 'client/contract/kh/launch',
|
||||
data: this.form1.data
|
||||
})
|
||||
vk.redirectTo({url: '/pages/contract/index?tab=1'})
|
||||
vk.redirectTo({
|
||||
url: '/pages/contract/index?tab=1'
|
||||
})
|
||||
}
|
||||
}
|
||||
uni.hideLoading()
|
||||
@@ -741,8 +807,7 @@ export default {
|
||||
|
||||
},
|
||||
// 表单字段显示规则
|
||||
columns: [
|
||||
{
|
||||
columns: [{
|
||||
key: "title",
|
||||
title: "标题",
|
||||
type: "text"
|
||||
@@ -850,7 +915,10 @@ export default {
|
||||
tradeMethod: 0,
|
||||
payBy: 0,
|
||||
otherFile: [],
|
||||
thirdList: [{phone: '', signKeyword: ''}],
|
||||
thirdList: [{
|
||||
phone: '',
|
||||
signKeyword: ''
|
||||
}],
|
||||
},
|
||||
// 表单属性
|
||||
props: {
|
||||
@@ -863,7 +931,9 @@ export default {
|
||||
thirdKeywords.push(item.signKeyword)
|
||||
}
|
||||
}
|
||||
uni.showLoading({title: '查验中'})
|
||||
uni.showLoading({
|
||||
title: '查验中'
|
||||
})
|
||||
vk.request({
|
||||
method: "POST",
|
||||
url: 'https://hcsc.gxwebsoft.com/api/read-pdf',
|
||||
@@ -871,7 +941,8 @@ export default {
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
},
|
||||
data: {
|
||||
file: this.form2.data.contractFile[this.form2.data.contractFile.length - 1],
|
||||
file: this.form2.data.contractFile[this.form2.data.contractFile.length -
|
||||
1],
|
||||
buyerSignKeyword: this.form2.data.buyerSignKeyword,
|
||||
sellerSignKeyword: this.form2.data.sellerSignKeyword,
|
||||
thirdKeywords
|
||||
@@ -888,7 +959,8 @@ export default {
|
||||
else {
|
||||
uni.hideLoading()
|
||||
this.form2.props.loading = true
|
||||
this.form2.data.thirdList = this.form2.data.thirdList.filter(item => item.phone && item.signKeyword)
|
||||
this.form2.data.thirdList = this.form2.data.thirdList.filter(
|
||||
item => item.phone && item.signKeyword)
|
||||
if (this.form2.data.thirdList.length > 0) {
|
||||
for (let i = 0; i < this.form2.data.thirdList.length; i++) {
|
||||
const item = this.form2.data.thirdList[i]
|
||||
@@ -914,7 +986,8 @@ export default {
|
||||
this.form2.props.loading = false
|
||||
return false
|
||||
}
|
||||
if (this.form2.data.payBy === undefined || this.form2.data.payBy === '' || this.form2.data.payBy === null) {
|
||||
if (this.form2.data.payBy === undefined || this.form2.data
|
||||
.payBy === '' || this.form2.data.payBy === null) {
|
||||
vk.toast('请选择费用承担方')
|
||||
this.form2.props.loading = false
|
||||
return false
|
||||
@@ -924,7 +997,9 @@ export default {
|
||||
this.form2.props.loading = false
|
||||
return false
|
||||
}
|
||||
const res = await this.$confirm(`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`, '提示', {
|
||||
const res = await this.$confirm(
|
||||
`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`,
|
||||
'提示', {
|
||||
confirmButtonText: '知悉同意',
|
||||
showCancelButton: false,
|
||||
type: 'warning',
|
||||
@@ -935,7 +1010,9 @@ export default {
|
||||
url: 'client/contract/kh/addSign',
|
||||
data: this.form2.data
|
||||
})
|
||||
vk.redirectTo({url: '/pages/contract/index?tab=1'})
|
||||
vk.redirectTo({
|
||||
url: '/pages/contract/index?tab=1'
|
||||
})
|
||||
}
|
||||
}
|
||||
console.log('complete:', pdfRes)
|
||||
@@ -945,13 +1022,11 @@ export default {
|
||||
|
||||
},
|
||||
// 表单字段显示规则
|
||||
columns: [
|
||||
{
|
||||
columns: [{
|
||||
key: "signType",
|
||||
title: "",
|
||||
type: "radio",
|
||||
data: [
|
||||
{
|
||||
data: [{
|
||||
value: '1',
|
||||
label: "单据签约"
|
||||
},
|
||||
@@ -983,8 +1058,7 @@ export default {
|
||||
key: "payBy",
|
||||
title: "签约费用",
|
||||
type: "radio",
|
||||
data: [
|
||||
{
|
||||
data: [{
|
||||
value: 0,
|
||||
label: "发起方承担"
|
||||
},
|
||||
@@ -1023,8 +1097,7 @@ export default {
|
||||
key: "userType",
|
||||
title: "对方身份",
|
||||
type: "select",
|
||||
data: [
|
||||
{
|
||||
data: [{
|
||||
value: 1,
|
||||
label: "买家"
|
||||
},
|
||||
@@ -1175,7 +1248,9 @@ export default {
|
||||
this.formData.status = Number(options.tab)
|
||||
this.isSign = false
|
||||
if (options.result_desc) {
|
||||
uni.showLoading({title: '请求中...'})
|
||||
uni.showLoading({
|
||||
title: '请求中...'
|
||||
})
|
||||
setTimeout(async () => {
|
||||
await this.query(1)
|
||||
uni.hideLoading()
|
||||
@@ -1296,8 +1371,47 @@ export default {
|
||||
this.isSignTips = false
|
||||
this.menuIndex = ''
|
||||
},
|
||||
// AI 客服方法
|
||||
chatQuickSend(text) {
|
||||
this.chatInput = text;
|
||||
this.chatSend();
|
||||
},
|
||||
async chatSend() {
|
||||
const msg = this.chatInput.trim();
|
||||
if (!msg || this.chatLoading) return;
|
||||
this.chatInput = '';
|
||||
this.chatMessages.push({ role: 'user', content: msg });
|
||||
this.chatLoading = true;
|
||||
this.chatScrollToBottom();
|
||||
|
||||
try {
|
||||
const res = await vk.callFunction({
|
||||
url: 'client/ai/pub/chat',
|
||||
data: { message: msg, bot_id: '7683509749475819554' }
|
||||
});
|
||||
if (res.data.conversation_id) this.chatConversationId = res.data.conversation_id;
|
||||
this.chatMessages.push({ role: 'assistant', content: res.data.answer });
|
||||
} catch (e) {
|
||||
this.chatMessages.push({ role: 'assistant', content: '网络异常,请稍后重试' });
|
||||
}
|
||||
this.chatLoading = false;
|
||||
this.chatScrollToBottom();
|
||||
},
|
||||
chatScrollToBottom() {
|
||||
setTimeout(() => {
|
||||
if (this.chatMessages.length === 0) {
|
||||
this.chatScrollId = 'chat-welcome';
|
||||
} else if (this.chatLoading) {
|
||||
this.chatScrollId = 'chat-loading';
|
||||
} else {
|
||||
this.chatScrollId = 'chat-msg' + (this.chatMessages.length - 1);
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
changeAuthInfo() {
|
||||
vk.navigateTo({url: '/pages/user/user?menu=fadada'})
|
||||
vk.navigateTo({
|
||||
url: '/pages/user/user?menu=fadada'
|
||||
})
|
||||
},
|
||||
async getSignFlow() {
|
||||
const res = await vk.callFunction({
|
||||
@@ -1339,7 +1453,9 @@ export default {
|
||||
},
|
||||
async changeContract(contract) {
|
||||
this.form1.data.contractId = contract._id
|
||||
const {data} = await vk.callFunction({
|
||||
const {
|
||||
data
|
||||
} = await vk.callFunction({
|
||||
url: 'client/contract/kh/getDetail',
|
||||
title: '请求中...',
|
||||
data: {
|
||||
@@ -1379,7 +1495,9 @@ export default {
|
||||
// this.$refs.form2.resetForm()
|
||||
// this.$refs.form1.resetForm()
|
||||
// this.query(1)
|
||||
vk.redirectTo({url: '/pages/contract/index?tab=1'})
|
||||
vk.redirectTo({
|
||||
url: '/pages/contract/index?tab=1'
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 签署合同
|
||||
@@ -1389,7 +1507,9 @@ export default {
|
||||
async extSign(sign, contract) {
|
||||
if (sign) return
|
||||
try {
|
||||
await this.$confirm(`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`, '提示', {
|
||||
await this.$confirm(
|
||||
`1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;<br>2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;<br>3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;<br>4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;<br>5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;<br>6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`,
|
||||
'提示', {
|
||||
confirmButtonText: '知悉同意',
|
||||
showCancelButton: false,
|
||||
type: 'warning',
|
||||
@@ -1463,8 +1583,10 @@ export default {
|
||||
// })
|
||||
console.log(123123)
|
||||
let content = ''
|
||||
const buyer = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId === item.userId)
|
||||
const seller = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId !== item.userId)
|
||||
const buyer = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract
|
||||
.userId === item.userId)
|
||||
const seller = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract
|
||||
.userId !== item.userId)
|
||||
const thirdList = userContract.contract.partyList.filter(item => item.role === 'third')
|
||||
content += `<view class="flex flex-col justify-start items-start py-10 border-bottom">
|
||||
<view>身份:发起方</view>
|
||||
@@ -1519,7 +1641,8 @@ export default {
|
||||
let openUrl = url
|
||||
if (Array.isArray(url)) openUrl = url[url.length - 1]
|
||||
if (!openUrl) return
|
||||
window.open(`https://www.jinjiuxinzg.cn/pdfjs/web/viewer.html?file=${encodeURIComponent(openUrl)}`, '_blank')
|
||||
window.open(`https://www.jinjiuxinzg.cn/pdfjs/web/viewer.html?file=${encodeURIComponent(openUrl)}`,
|
||||
'_blank')
|
||||
},
|
||||
downloadContractTemplate() {
|
||||
window.open(this.contractTemplate)
|
||||
@@ -1581,7 +1704,8 @@ export default {
|
||||
if (contract.certificate.deliveryMethods.paper) {
|
||||
vk.toast('您的司法调证文件已发货,请注意查收')
|
||||
} else {
|
||||
if (contract.certificate.downloadUrl) window.open(contract.certificate.downloadUrl)
|
||||
if (contract.certificate.downloadUrl) window.open(contract.certificate
|
||||
.downloadUrl)
|
||||
else vk.toast('文件生成中,请耐心等待')
|
||||
}
|
||||
} else vk.toast('操作失败,请联系客服')
|
||||
@@ -1590,7 +1714,10 @@ export default {
|
||||
}
|
||||
},
|
||||
async downloadContract(contract_id) {
|
||||
let loadingInstance1 = Loading.service({fullscreen: true, text: '加载中...'});
|
||||
let loadingInstance1 = Loading.service({
|
||||
fullscreen: true,
|
||||
text: '加载中...'
|
||||
});
|
||||
const res = await vk.callFunction({
|
||||
url: 'client/contract/pub/getDownload',
|
||||
data: {
|
||||
@@ -1599,12 +1726,16 @@ export default {
|
||||
});
|
||||
loadingInstance1.close()
|
||||
if (res) {
|
||||
window.open(`https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704×tamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`)
|
||||
window.open(
|
||||
`https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704×tamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`
|
||||
)
|
||||
}
|
||||
},
|
||||
getUserInfo() {
|
||||
vk.userCenter.getCurrentUserInfo({
|
||||
success: ({userInfo}) => {
|
||||
success: ({
|
||||
userInfo
|
||||
}) => {
|
||||
this.userInfo = userInfo
|
||||
if (!this.userInfo.mobile) {
|
||||
this.$confirm('请先绑定手机号', '提示', {
|
||||
@@ -1612,9 +1743,11 @@ export default {
|
||||
showCancelButton: false,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
vk.redirectTo(`/pages/auth/login/wechat?state=jjx_` + this.userInfo.accountType)
|
||||
vk.redirectTo(`/pages/auth/login/wechat?state=jjx_` + this.userInfo
|
||||
.accountType)
|
||||
}).catch(() => {
|
||||
vk.redirectTo(`/pages/auth/login/wechat?state=jjx_` + this.userInfo.accountType)
|
||||
vk.redirectTo(`/pages/auth/login/wechat?state=jjx_` + this.userInfo
|
||||
.accountType)
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -1627,11 +1760,14 @@ export default {
|
||||
closeOnClickModal: false,
|
||||
closeOnPressEscape: false
|
||||
}).then(() => {
|
||||
vk.navigateTo({url: '/pages/user/user?menu=fadada'});
|
||||
vk.navigateTo({
|
||||
url: '/pages/user/user?menu=fadada'
|
||||
});
|
||||
})
|
||||
}
|
||||
this.invoiceForm.phone = this.userInfo.mobile
|
||||
this.invoiceForm.email = this.userInfo.businessCard ? this.userInfo.businessCard.email : ''
|
||||
this.invoiceForm.email = this.userInfo.businessCard ? this.userInfo.businessCard
|
||||
.email : ''
|
||||
if (this.userInfo.accountType === 2) {
|
||||
if (this.userInfo.fadadaConfirm && this.userInfo.company) {
|
||||
this.invoiceForm.name = this.userInfo.company.companyName
|
||||
@@ -1651,7 +1787,9 @@ export default {
|
||||
});
|
||||
},
|
||||
async getQybPackage() {
|
||||
const {rows} = await vk.callFunction({
|
||||
const {
|
||||
rows
|
||||
} = await vk.callFunction({
|
||||
url: 'client/qyb/list/pub/getList',
|
||||
data: {
|
||||
pageIndex: 1,
|
||||
@@ -1661,7 +1799,9 @@ export default {
|
||||
this.qybPackageList = rows
|
||||
},
|
||||
async doBuyQyb() {
|
||||
const {data} = await vk.callFunction({
|
||||
const {
|
||||
data
|
||||
} = await vk.callFunction({
|
||||
url: 'client/qyb/list/kh/buy',
|
||||
title: '请求中...',
|
||||
data: {
|
||||
@@ -1899,4 +2039,130 @@ export default {
|
||||
background-color: #f1c7c7;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* ===== 右侧悬浮工具栏 ===== */
|
||||
.float-toolbar {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
|
||||
padding: 12px 0;
|
||||
z-index: 100;
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 8px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item:hover {
|
||||
background: #f6eae9;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item .tool-icon {
|
||||
font-size: 22px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item .tool-label {
|
||||
font-size: 10px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-divider {
|
||||
height: 1px;
|
||||
background: #eee;
|
||||
margin: 4px 12px;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item.ai-hot {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.float-toolbar .tool-item.ai-hot::after {
|
||||
content: "AI";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 8px;
|
||||
background: #a92924;
|
||||
color: #fff;
|
||||
font-size: 8px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* ===== 新增AI功能菜单组 ===== */
|
||||
.menu-group-title {
|
||||
padding: 8px 20px 4px;
|
||||
font-size: 11px;
|
||||
color: #999;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* AI 客服嵌入样式 */
|
||||
.ai-chat-embed {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100vh - 260px);
|
||||
overflow: hidden;
|
||||
}
|
||||
.chat-header-bar {
|
||||
padding: 14px 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.chat-title { font-size: 15px; font-weight: 600; }
|
||||
.chat-subtitle { font-size: 12px; color: #999; }
|
||||
.chat-msg-list { flex: 1; padding: 16px 20px; background: #f7f8fa; }
|
||||
.chat-row { display: flex; gap: 10px; margin-bottom: 12px; }
|
||||
.chat-row.right { flex-direction: row-reverse; }
|
||||
.chat-avatar {
|
||||
width: 32px; height: 32px; border-radius: 50%;
|
||||
background: linear-gradient(135deg, #a92924, #d4574e);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
color: #fff; font-size: 14px; flex-shrink: 0;
|
||||
}
|
||||
.chat-bubble {
|
||||
max-width: 65%; padding: 10px 14px; border-radius: 12px;
|
||||
font-size: 13px; line-height: 1.6; word-break: break-word;
|
||||
}
|
||||
.chat-row:not(.right) .chat-bubble { background: #fff; border: 1px solid #eee; border-top-left-radius: 4px; }
|
||||
.chat-row.right .chat-bubble { background: #a92924; color: #fff; border-top-right-radius: 4px; }
|
||||
.chat-bubble.typing { color: #999; }
|
||||
.quick-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
|
||||
.quick-btn {
|
||||
padding: 5px 12px; border-radius: 14px; font-size: 12px; cursor: pointer;
|
||||
border: 1px solid #a92924; color: #a92924; background: #fff; transition: all 0.2s;
|
||||
}
|
||||
.quick-btn:hover { background: #a92924; color: #fff; }
|
||||
.chat-input-bar {
|
||||
padding: 12px 20px; border-top: 1px solid #eee;
|
||||
display: flex; gap: 10px; background: #fff;
|
||||
}
|
||||
.chat-input-bar input {
|
||||
flex: 1; height: 38px; border: 1px solid #ddd; border-radius: 8px;
|
||||
padding: 0 12px; font-size: 13px; outline: none;
|
||||
}
|
||||
.chat-input-bar input:focus { border-color: #a92924; }
|
||||
.chat-send-btn {
|
||||
padding: 0 20px; height: 38px; line-height: 38px;
|
||||
background: #a92924; color: #fff; border-radius: 8px;
|
||||
font-size: 13px; cursor: pointer;
|
||||
}
|
||||
.chat-send-btn:hover { background: #982520; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user