|
|
|
|
|
<template>
|
|
|
|
|
|
<view class="p-home-chat g_w_all g_bg_f_5">
|
|
|
|
|
|
<!-- <img src="../../static/image/1.jpg" alt="" style="position: fixed;
|
|
|
|
|
|
width: 100vw;
|
|
|
|
|
|
height: 100vh;
|
|
|
|
|
|
z-index: 999;
|
|
|
|
|
|
opacity: 0.7;"> -->
|
|
|
|
|
|
<!-- aaa{{textareaHeight}}bbb -->
|
|
|
|
|
|
<view class="chat-content g_flex_column_end g_clear_scroll" :style="{ paddingBottom: `${textareaHeight + 80}px` }">
|
|
|
|
|
|
<scroll-view scroll-y="true" :scroll-top="scrollTop" class="chat-link g_clear_scroll m-scroll "
|
|
|
|
|
|
scroll-with-animation :show-scrollbar='false' style="padding: 24px 0;">
|
|
|
|
|
|
<view class="g_flex_column_end g_clear_scroll" style="overflow-y: auto;min-height: 100%;">
|
|
|
|
|
|
<view class="g_mb_10" v-for="(item,index) in list" :key="index"
|
|
|
|
|
|
:class="index % 2 === 0 ? '' : 'g_flex_row_end'"
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<view class="m-item chat-left g_flex_row_start" v-if="index % 2 === 0">
|
|
|
|
|
|
<view>
|
|
|
|
|
|
<view class="g_flex_row_start g_mb_10" v-if="gptType != 'ai-text' && gptType != 'ai'">
|
|
|
|
|
|
<view class="g_flex_column_center g_h_20" style="overflow: hidden;">
|
|
|
|
|
|
<image :src="item.avatar" mode="widthFix" class="g_w_20"></image>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_column_center g_ml_6 g_c_3 g_fs_15 g_fw_700">
|
|
|
|
|
|
{{item.username}}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="loader" v-if="(index+1 == list.length) && index > 0 && showLoad">
|
|
|
|
|
|
<text class="dot"></text>
|
|
|
|
|
|
<text class="dot"></text>
|
|
|
|
|
|
<text class="dot"></text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else>
|
|
|
|
|
|
<view class="msg g_bg_f g_c_0 g_pl_10 g_pr_10 g_pt_10 g_pb_10" style="min-width:calc(100vw - 20px);">
|
|
|
|
|
|
<view v-if="gptType == 'demo'">
|
|
|
|
|
|
<view class="" v-if="item.chat_type == 'text' && index == 0">
|
|
|
|
|
|
<g-chat-message :cusMessage='item.msg' />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="" v-if="index == 2">
|
|
|
|
|
|
<g-chat-message cusMessage='住宿有要求吗?' />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-if="item.chat_type == 'job' && index > 3">
|
|
|
|
|
|
<g-chat-job :cusAllJob='allJob'
|
|
|
|
|
|
:cusItem='item'
|
|
|
|
|
|
@exportToggle='toggleChange'
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-if="gptType == 'ai' || gptType == 'ai-text'">
|
|
|
|
|
|
<view class="" v-if="item.chat_type == 'text'">
|
|
|
|
|
|
<g-chat-message :cusMessage='item.msg' />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="" v-if="item.chat_type == 'rich-text'">
|
|
|
|
|
|
<g-chat-rich :cusMessage='item.msg' />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="" v-if="item.chat_type == 'job'">
|
|
|
|
|
|
<g-chat-job :cusAllJob='allJob'
|
|
|
|
|
|
:cusItem='item'
|
|
|
|
|
|
@exportToggle='toggleChange'
|
|
|
|
|
|
/>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<!-- 底部操作 -->
|
|
|
|
|
|
<view class="g_flex_row_between g_mt_10 g_h_22 g_pl_10 g_pr_10">
|
|
|
|
|
|
<view class="g_flex_1 g_flex_row_start" v-if="item.isShowIcon">
|
|
|
|
|
|
<view class="g_flex_column_center" @click="handleUpdateGood(item,'good')">
|
|
|
|
|
|
<i class="iconfont icon-useful g_fs_20 g_c_8" :class="item.isGood ? 'g_c_main' : ''"></i>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_column_center g_ml_12" @click="handleUpdateGood(item,'down')">
|
|
|
|
|
|
<i class="iconfont icon-un_useful g_fs_20 g_c_8" :class="item.isDown ? 'g_c_main' : ''"></i>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_none g_flex_row_end" v-if="item.isShowIcon">
|
|
|
|
|
|
<view class="g_flex_column_center g_mr_12" @click="handleClickCopy(item.msg)">
|
|
|
|
|
|
<i class="iconfont icon-fuzhi1 g_fs_20 g_c_8"></i>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_column_center g_position_rela" @click="animate()">
|
|
|
|
|
|
<i class="iconfont icon-fenxiangfenxiangshare g_fs_20 g_c_8"></i>
|
|
|
|
|
|
<button class="btn-share" open-type="share"></button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<view class="m-item chat-right g_flex_row_end" v-else style="max-width: 80vw;">
|
|
|
|
|
|
<view class="msg g_bg_main g_c_f g_fs_17 g_pl_16 g_pr_16 g_pt_10 g_pb_10">
|
|
|
|
|
|
<g-chat-message :cusMessage='item.msg' style="max-width: 80%;" />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="chat-operate g_flex_c">
|
|
|
|
|
|
<view class="g_bg_f m-input g_flex_row_center g_position_rela"
|
|
|
|
|
|
:class="hasTopPadding ? 'hasTopPadding' : ''"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
height: msgType == 'voice' ? '56px' : `${textareaHeight + 16}px`
|
|
|
|
|
|
}"
|
|
|
|
|
|
style="align-items: flex-end;min-height: 56px;"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="g_flex_none g_flex_c g_h_56 g_w_48"
|
|
|
|
|
|
@click="handleUpdateMsgType();"
|
|
|
|
|
|
:class="voiceStatus == 0 && spec ? 'g_bg_main' : (voiceStatus == 1 ? 'g_bg_f0a' : '')"
|
|
|
|
|
|
style="border-radius: 40px 0px 0px 40px;"
|
|
|
|
|
|
v-if="gptType != 'ai-text'"
|
|
|
|
|
|
>
|
|
|
|
|
|
<i class="iconfont g_ml_20"
|
|
|
|
|
|
:class="msgType == 'text' ? 'icon-huatongyuyin g_fs_22' : 'icon-weixinjianpan2 g_fs_26'"
|
|
|
|
|
|
v-if="voiceStatus == -1"></i>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_1 g_flex_column_end ">
|
|
|
|
|
|
<view v-if="msgType == 'text'" class="m-input-point g_w_all g_h_56 g_flex_column_end ">
|
|
|
|
|
|
<div class="container g_flex_column_end g_h_32" ref="container">
|
|
|
|
|
|
<textarea auto-height
|
|
|
|
|
|
cursor-spacing="50"
|
|
|
|
|
|
class="g_fs_17 g_c_0"
|
|
|
|
|
|
:class="hasTopPadding ? 'g_mt_0' : ''"
|
|
|
|
|
|
id="textarea"
|
|
|
|
|
|
placeholder="请输入内容"
|
|
|
|
|
|
v-model="sendMsg"
|
|
|
|
|
|
style="position: absolute;width: calc(100vw - 140px);top: 50%;transform: translateY(-50%);padding: 0 0 0 12px;"
|
|
|
|
|
|
:style="{ height: `${textareaHeight + 20}px` }"
|
|
|
|
|
|
@input="onInput"
|
|
|
|
|
|
@focus="onFocus"
|
|
|
|
|
|
@blur="onBlur"
|
|
|
|
|
|
@keyboardheightchange="keyboardheightchange"
|
|
|
|
|
|
@linechange="linechange"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view v-else>
|
|
|
|
|
|
<view class="g_w_all g_h_56 m-voice-point g_flex_c g_fw_700 g_fs_17" @touchstart="onTouchStart"
|
|
|
|
|
|
@touchend="onTouchEnd" @touchmove="onTouchMove"
|
|
|
|
|
|
:class="voiceStatus == 1 ? 'g_c_f g_bg_f0a' : (voiceStatus == 0 ? 'g_bg_main' : '')">
|
|
|
|
|
|
{{ voiceStatus == 1 ? '松手 取消' : '按住 说话'}}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="g_flex_none g_flex_c g_h_56 g_w_48 g_position_rela"
|
|
|
|
|
|
@click="handleSendMsg"
|
|
|
|
|
|
:class="voiceStatus == 0 && spec ? 'g_bg_main' : (voiceStatus == 1 ? 'g_bg_f0a' : '')"
|
|
|
|
|
|
style="border-radius: 0 40px 40px 0;"
|
|
|
|
|
|
>
|
|
|
|
|
|
<i class="iconfont icon-fasong g_fs_32 g_mr_20"
|
|
|
|
|
|
:class="sendIconStatus ? 'g_c_main' : 'g_c_b'"
|
|
|
|
|
|
v-if="voiceStatus == -1"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<i class="iconfont icon-close-circle g_fs_26 g_c_9"
|
|
|
|
|
|
style="position: absolute;right: 22px;top: 50%;transform: translateY(-80%);"
|
|
|
|
|
|
v-if="textareaHeight > 80 && msgType == 'text'"
|
|
|
|
|
|
@click.stop="sendMsg = '';textareaHeight = 22"
|
|
|
|
|
|
></i>
|
|
|
|
|
|
<view class="longpress-mask">
|
|
|
|
|
|
<view class="longpress-top-mask g_h_56 g_flex_c"
|
|
|
|
|
|
style="bottom:calc(70px + constant(safe-area-inset-bottom)); bottom: calc(70px + env(safe-area-inset-bottom));"
|
|
|
|
|
|
v-if="voiceStatus == 0 || voiceStatus == 1">
|
|
|
|
|
|
<div class="column-voice g_flex_row_center">
|
|
|
|
|
|
<div v-for="(item,index) in 26" :key="index" class="g_flex_column_center">
|
|
|
|
|
|
<div class="column-item" :style="{
|
|
|
|
|
|
'animation':'voi_animate 1.5s infinite ' + (0.1*index) + 's',
|
|
|
|
|
|
'-webkit-animation':'voi_animate 1.5s infinite ' + (0.1*index) + 's'
|
|
|
|
|
|
}"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="longpress-bottom-mask"
|
|
|
|
|
|
style="height:calc(70px + constant(safe-area-inset-bottom)); height: calc(70px + env(safe-area-inset-bottom));"
|
|
|
|
|
|
v-if="voiceStatus == 0"></view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import {
|
|
|
|
|
|
chatMock
|
|
|
|
|
|
} from '../../../utils/chat.js';
|
|
|
|
|
|
var plugin = requirePlugin("WechatSI")
|
|
|
|
|
|
let manager = plugin.getRecordRecognitionManager()
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
onShareAppMessage() {
|
|
|
|
|
|
return this.G.shareFun();
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
content: '',
|
|
|
|
|
|
textareaHeight: 30,
|
|
|
|
|
|
initialHeight: 0,
|
|
|
|
|
|
showLoad: false,
|
|
|
|
|
|
localBaseImg: this.G.store().localBaseImg,
|
|
|
|
|
|
scrollTop: 0,
|
|
|
|
|
|
windowHeight: 0,
|
|
|
|
|
|
list: chatMock,
|
|
|
|
|
|
|
|
|
|
|
|
dzj: "",
|
|
|
|
|
|
msgType: 'text',
|
|
|
|
|
|
sendMsg: '',
|
|
|
|
|
|
sendIconStatus: false,
|
|
|
|
|
|
voiceMsg: '按住 说话',
|
|
|
|
|
|
voiceStatus: -1, // -1 录音前 & 录音结束 0 录音时且在指定范围 1录音时但不在指定范围
|
|
|
|
|
|
recorderManager: null, // 录音管理对象
|
|
|
|
|
|
touchStartTime: 0, // 记录按下按钮的时间
|
|
|
|
|
|
longPressDelay: 0, // 设定长按所需时间,单位毫秒
|
|
|
|
|
|
spec: true,
|
|
|
|
|
|
isAuth: false,
|
|
|
|
|
|
content: '', // 内容
|
|
|
|
|
|
hasTopPadding: false,
|
|
|
|
|
|
allJob: [],
|
|
|
|
|
|
talkId:0,
|
|
|
|
|
|
gptType:'',
|
|
|
|
|
|
bottomHeight:100,
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
onLoad(options) {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
console.log('聊天页参数:',options)
|
|
|
|
|
|
if(options.type){
|
|
|
|
|
|
that.gptType = options.type;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
that.gptType = 'ai';
|
|
|
|
|
|
}
|
|
|
|
|
|
that.initSI();
|
|
|
|
|
|
},
|
|
|
|
|
|
onShow() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
that.voiceStatus = -1;
|
|
|
|
|
|
// 创建查询对象
|
|
|
|
|
|
const query = wx.createSelectorQuery();
|
|
|
|
|
|
// 选择指定的 DOM 元素
|
|
|
|
|
|
query.select('.chat-operate').boundingClientRect();
|
|
|
|
|
|
// 执行查询
|
|
|
|
|
|
query.exec((res) => {
|
|
|
|
|
|
if (res && res[0]) {
|
|
|
|
|
|
const height = res[0].height;
|
|
|
|
|
|
that.bottomHeight = height;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('未找到元素');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// that.list = [
|
|
|
|
|
|
// {
|
|
|
|
|
|
// avatar:uni.getStorageSync("miniApp-info").logo,
|
|
|
|
|
|
// username:uni.getStorageSync("miniApp-info").fullName,
|
|
|
|
|
|
// msg:'Hi,我是' + uni.getStorageSync("miniApp-info").fullName +',很高兴见到你',
|
|
|
|
|
|
// isGood:false,
|
|
|
|
|
|
// isDown:false,
|
|
|
|
|
|
// chat_type:'text',
|
|
|
|
|
|
// isToggle:false,
|
|
|
|
|
|
// isShowIcon:true,
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ];
|
|
|
|
|
|
that.initSocket();
|
|
|
|
|
|
},
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
'sendMsg'(val) {
|
|
|
|
|
|
if (val) {
|
|
|
|
|
|
this.sendIconStatus = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.sendIconStatus = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
initSocket(){
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
// 创建会话
|
|
|
|
|
|
if(that.gptType == 'ai' || that.gptType == 'ai-text'){
|
|
|
|
|
|
that.G.Get(that.api.chat_create,{},(res)=>{
|
|
|
|
|
|
console.log('获取 会话ID',res)
|
|
|
|
|
|
that.talkId = res;
|
|
|
|
|
|
});
|
|
|
|
|
|
}else{
|
|
|
|
|
|
that.getList();
|
|
|
|
|
|
that.talkId = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
getList(callback=()=>{}) {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
that.windowHeight = uni.getSystemInfoSync().windowHeight - 150;
|
|
|
|
|
|
if(!that.api.chat_daotian_job){
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
that.G.Post(that.api.chat_daotian_job, {
|
|
|
|
|
|
pageNum: 1,
|
|
|
|
|
|
pageSize: 8,
|
|
|
|
|
|
classify: 1,
|
|
|
|
|
|
sex: -1,
|
|
|
|
|
|
workTypeStr:"",
|
|
|
|
|
|
lat: "",
|
|
|
|
|
|
lng: "",
|
|
|
|
|
|
jobClassify:"",
|
|
|
|
|
|
sortTag: 0,
|
|
|
|
|
|
jobSpecialLabelIds:"",
|
|
|
|
|
|
cityName: '全国',
|
|
|
|
|
|
brandIds: '',
|
|
|
|
|
|
jobCategoryLabelIds:'',
|
|
|
|
|
|
ucj: 0,
|
|
|
|
|
|
provinceName:'',
|
|
|
|
|
|
keys: ''
|
|
|
|
|
|
}, (res) => {
|
|
|
|
|
|
console.log('稻田职位列表',res)
|
|
|
|
|
|
if (res.pageBean.recordCount > 0) {
|
|
|
|
|
|
res.pageBean.recordList = that.G.toGetAddress(res.pageBean.recordList);
|
|
|
|
|
|
res.pageBean.recordList = that.G.toGetAge(res.pageBean.recordList);
|
|
|
|
|
|
res.pageBean.recordList = that.G.yijobCopy(res.pageBean.recordList);
|
|
|
|
|
|
that.allJob = res.pageBean.recordList.map(item => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...item,
|
|
|
|
|
|
isToggle:false,
|
|
|
|
|
|
_time:that.G.setDeadLine(item.createTime,'jiaofu'),
|
|
|
|
|
|
liuNum: item.liuNum,
|
|
|
|
|
|
baoNum: uni.getStorageSync("lin-bao") ? uni.getStorageSync("lin-bao") / 10 : Math.ceil(item.liuNum / 10),
|
|
|
|
|
|
collected: item.collected ? true : false,
|
|
|
|
|
|
cus_price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValueHtml(item.salaryClassify, item.salaryClassifyValue) : "月薪",
|
|
|
|
|
|
isDown:false
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
that.allJob = [];
|
|
|
|
|
|
};
|
|
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
callback();
|
|
|
|
|
|
},300);
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
toggleChange(){
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
},600);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
keyboardheightchange(e) {
|
|
|
|
|
|
if (e.target.dataset.height == 0 && this.sendMsg == "") {
|
|
|
|
|
|
this.textareaHeight = 30
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
onInput(e) {
|
|
|
|
|
|
this.content = e.target.value;
|
|
|
|
|
|
this.updateTextareaHeight();
|
|
|
|
|
|
this.scrollToBottom();
|
|
|
|
|
|
},
|
|
|
|
|
|
onFocus() {
|
|
|
|
|
|
this.initialHeight = this.textareaHeight;
|
|
|
|
|
|
},
|
|
|
|
|
|
onBlur() {
|
|
|
|
|
|
this.updateTextareaHeight();
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
updateTextareaHeight() {
|
|
|
|
|
|
|
|
|
|
|
|
uni.createSelectorQuery()
|
|
|
|
|
|
.in(this)
|
|
|
|
|
|
.select('#textarea')
|
|
|
|
|
|
.boundingClientRect((rect) => {
|
|
|
|
|
|
this.textareaHeight = rect.height;
|
|
|
|
|
|
})
|
|
|
|
|
|
.exec();
|
|
|
|
|
|
},
|
|
|
|
|
|
linechange(e) {
|
|
|
|
|
|
if (e.detail.lineCount > 1) {
|
|
|
|
|
|
this.hasTopPadding = true
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.hasTopPadding = false
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
scrollToBottom() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
wx.pageScrollTo({
|
|
|
|
|
|
scrollTop: 999999,
|
|
|
|
|
|
duration: 100
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
handleUpdateGood($item,$tip) {
|
|
|
|
|
|
if($tip == 'good'){
|
|
|
|
|
|
if ($item.isGood) {
|
|
|
|
|
|
$item.isGood = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$item.isGood = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}else{
|
|
|
|
|
|
if ($item.isDown) {
|
|
|
|
|
|
$item.isDown = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$item.isDown = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this.animate();
|
|
|
|
|
|
},
|
|
|
|
|
|
handleClickCopy($content = '') {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
uni.setClipboardData({
|
|
|
|
|
|
data: $content,
|
|
|
|
|
|
success: () => {},
|
|
|
|
|
|
fail: (err) => {}
|
|
|
|
|
|
});
|
|
|
|
|
|
that.animate();
|
|
|
|
|
|
},
|
|
|
|
|
|
handleUpdateMsgType() {
|
|
|
|
|
|
this.animate()
|
|
|
|
|
|
if (this.msgType == 'text') {
|
|
|
|
|
|
this.msgType = 'voice'
|
|
|
|
|
|
this.checkRecordingPermission().then(() => {}).catch((error) => {});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.msgType = 'text'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
handleSendMsg() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
if (that.msgType == 'voice') {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (that.sendMsg == '') {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
title: '请输入内容'
|
|
|
|
|
|
})
|
|
|
|
|
|
return false;
|
|
|
|
|
|
};
|
|
|
|
|
|
that.animate()
|
|
|
|
|
|
that.sendAI();
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
that.sendMsg = '';
|
|
|
|
|
|
that.updateTextareaHeight();
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
that.textareaHeight = 30
|
|
|
|
|
|
}, 10);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
that.textareaHeight = 30
|
|
|
|
|
|
}, 80);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
checkRecordingPermission() {
|
|
|
|
|
|
var that = this;
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
wx.getSetting({
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.authSetting['scope.record']) {
|
|
|
|
|
|
that.voiceStatus = -1
|
|
|
|
|
|
that.isAuth = true;
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
that.voiceStatus = -1
|
|
|
|
|
|
wx.authorize({
|
|
|
|
|
|
scope: 'scope.record',
|
|
|
|
|
|
success: () => {
|
|
|
|
|
|
that.voiceStatus = -1
|
|
|
|
|
|
that.isAuth = true;
|
|
|
|
|
|
resolve(true);
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: () => {
|
|
|
|
|
|
that.isAuth = false;
|
|
|
|
|
|
reject(new Error('录音权限未授权'));
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: () => {
|
|
|
|
|
|
that.voiceStatus = -1
|
|
|
|
|
|
reject(new Error('无法获取权限设置'));
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
onTouchStart() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
if (!this.isAuth) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.touchStartTime = Date.now();
|
|
|
|
|
|
this.longPressTimer = setTimeout(() => {
|
|
|
|
|
|
this.checkRecordingPermission().then(() => {
|
|
|
|
|
|
this.voiceStatus = -1;
|
|
|
|
|
|
this.spec = true;
|
|
|
|
|
|
that.animate();
|
|
|
|
|
|
this.startRecording();
|
|
|
|
|
|
}).catch((error) => {});
|
|
|
|
|
|
}, this.longPressDelay);
|
|
|
|
|
|
},
|
|
|
|
|
|
onTouchMove(e) {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
const touch = e.touches[0];
|
|
|
|
|
|
let _x = touch.clientX,
|
|
|
|
|
|
_y = touch.clientY;
|
|
|
|
|
|
|
|
|
|
|
|
if (_y > (uni.getSystemInfoSync().windowHeight - that.bottomHeight) &&
|
|
|
|
|
|
_x > 30 &&
|
|
|
|
|
|
_x < (uni.getSystemInfoSync().windowWidth - 30)
|
|
|
|
|
|
) {
|
|
|
|
|
|
this.voiceStatus = 0;
|
|
|
|
|
|
this.spec = true;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.voiceStatus = 1;
|
|
|
|
|
|
this.spec = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
onTouchEnd() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
const touchEndTime = Date.now();
|
|
|
|
|
|
clearTimeout(this.longPressTimer);
|
|
|
|
|
|
// debugger
|
|
|
|
|
|
if (this.voiceStatus == 0 || this.voiceStatus == 1) {
|
|
|
|
|
|
this.stopRecording();
|
|
|
|
|
|
} else if (touchEndTime - this.touchStartTime < this.longPressDelay) {
|
|
|
|
|
|
this.voiceStatus = -1
|
|
|
|
|
|
} else {
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
that.voiceStatus = -1
|
|
|
|
|
|
manager.stop();
|
|
|
|
|
|
}, 300)
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
startRecording() {
|
|
|
|
|
|
this.voiceStatus = 0; // 标记为正在录音
|
|
|
|
|
|
// 语音识别开始
|
|
|
|
|
|
manager.start({
|
|
|
|
|
|
duration: 30000,
|
|
|
|
|
|
lang: 'zh_CN',
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
stopRecording() {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
// 语音识别结束
|
|
|
|
|
|
manager.stop();
|
|
|
|
|
|
that.voiceStatus = -1;
|
|
|
|
|
|
},
|
|
|
|
|
|
// 插件初始化
|
|
|
|
|
|
initSI() {
|
|
|
|
|
|
const that = this;
|
|
|
|
|
|
manager.onRecognize = function(res) {
|
|
|
|
|
|
};
|
|
|
|
|
|
manager.onStart = function(res) {
|
|
|
|
|
|
// 开始录音时-抖动一下手机
|
|
|
|
|
|
// that.animate();
|
|
|
|
|
|
};
|
|
|
|
|
|
// 识别错误事件
|
|
|
|
|
|
manager.onError = function(res) {
|
|
|
|
|
|
console.error('error msg', res);
|
|
|
|
|
|
const tips = {
|
|
|
|
|
|
'-30003': '说话时间间隔太短,无法识别语音',
|
|
|
|
|
|
'-30004': '没有听清,请再说一次~',
|
|
|
|
|
|
'-30011': '上个录音正在识别中,请稍后尝试',
|
|
|
|
|
|
};
|
|
|
|
|
|
const retcode = res?.retcode.toString();
|
|
|
|
|
|
retcode &&
|
|
|
|
|
|
wx.showToast({
|
|
|
|
|
|
title: tips[`${retcode}`],
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000,
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
manager.onStop = function(res) {
|
|
|
|
|
|
if (res.result === '') {
|
|
|
|
|
|
wx.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '没有听清,请再说一次~',
|
|
|
|
|
|
showCancel: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
that.content = '';
|
|
|
|
|
|
var text = that.content + res.result;
|
|
|
|
|
|
that.content = text;
|
|
|
|
|
|
that.sendAI('stop');
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
sendAI($form = '') {
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
if ($form == 'stop') {
|
|
|
|
|
|
if (that.voiceStatus == 1) {
|
|
|
|
|
|
that.voiceStatus = -1;
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
that.voiceStatus = -1;
|
|
|
|
|
|
that.list.push({
|
|
|
|
|
|
avatar: '',
|
|
|
|
|
|
username: '',
|
|
|
|
|
|
msg: that.msgType == 'text' ? that.sendMsg : that.content,
|
|
|
|
|
|
isGood: false,
|
|
|
|
|
|
isDown:false,
|
|
|
|
|
|
chat_type: that.sendMsg.indexOf('职位') > -1 ? 'job' : 'job',
|
|
|
|
|
|
isToggle: false,
|
|
|
|
|
|
isShowIcon:false,
|
|
|
|
|
|
}, );
|
|
|
|
|
|
var str = "根据输入框文本返回的内容根据输入框文本返回的内容根据输入框文本返回的内容"
|
|
|
|
|
|
var result = "";
|
|
|
|
|
|
let index = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(that.gptType == 'ai' || that.gptType == 'ai-text'){
|
|
|
|
|
|
that.list.push({
|
|
|
|
|
|
avatar: uni.getStorageSync("miniApp-info").logo,
|
|
|
|
|
|
username: uni.getStorageSync("miniApp-info").fullName,
|
|
|
|
|
|
msg: '',
|
|
|
|
|
|
isGood: false,
|
|
|
|
|
|
isDown:false,
|
|
|
|
|
|
chat_type:'',
|
|
|
|
|
|
isToggle: false,
|
|
|
|
|
|
isShowIcon:false,
|
|
|
|
|
|
});
|
|
|
|
|
|
that.textareaHeight = 30
|
|
|
|
|
|
that.showLoad = true;
|
|
|
|
|
|
|
|
|
|
|
|
that.G.Post(that.api.chat_send,{
|
|
|
|
|
|
content:that.msgType == 'text' ? that.sendMsg : that.content,
|
|
|
|
|
|
talkId:that.talkId
|
|
|
|
|
|
},(res)=>{
|
|
|
|
|
|
if(res.jobIds){
|
|
|
|
|
|
// 调用新职位接口
|
|
|
|
|
|
console.log('获取职位参数:',res.jobIds)
|
|
|
|
|
|
let mockJobIdGroup = [
|
|
|
|
|
|
10938,10977,10973,10605,10604,10355,10971,11025,9467,9909,10584,10562,10242,73,38,77,1,29,44
|
|
|
|
|
|
];
|
|
|
|
|
|
// 随机8个,逗号拼接
|
|
|
|
|
|
that.getNewList(res.jobIds + ',' + that.getRandomElements(mockJobIdGroup, Number(8 - res.jobIds.split(',').length)).join(','),()=>{
|
|
|
|
|
|
base()
|
|
|
|
|
|
});
|
|
|
|
|
|
}else{
|
|
|
|
|
|
// 调用稻田职位接口
|
|
|
|
|
|
that.getList(()=>{
|
|
|
|
|
|
base()
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function base(){
|
|
|
|
|
|
if(res.talk){
|
|
|
|
|
|
that.list[that.list.length-1].msg = res.content;
|
|
|
|
|
|
that.list[that.list.length-1].chat_type = 'text';
|
|
|
|
|
|
}else{
|
|
|
|
|
|
if(res.classify == 'text'){
|
|
|
|
|
|
that.list[that.list.length-1].chat_type = 'rich-text';
|
|
|
|
|
|
// 去除 **
|
|
|
|
|
|
res.content = res.content.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
|
|
|
|
|
that.list[that.list.length-1].msg = res.content;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
that.list[that.list.length-1].chat_type = 'job';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
|
that.handleSet(res.content,result,index,300);
|
|
|
|
|
|
},100);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}else{
|
|
|
|
|
|
that.list.push({
|
|
|
|
|
|
avatar: uni.getStorageSync("miniApp-info").logo,
|
|
|
|
|
|
username: uni.getStorageSync("miniApp-info").fullName,
|
|
|
|
|
|
msg: that.msgType == 'text' ? "" : '根据语音文件返回的ai内容',
|
|
|
|
|
|
isGood: false,
|
|
|
|
|
|
isDown:false,
|
|
|
|
|
|
chat_type: that.sendMsg.indexOf('职位') > -1 ? 'job' : 'job',
|
|
|
|
|
|
isToggle: false,
|
|
|
|
|
|
isShowIcon:false,
|
|
|
|
|
|
});
|
|
|
|
|
|
that.textareaHeight = 30
|
|
|
|
|
|
that.showLoad = true;
|
|
|
|
|
|
that.handleSet(str,result,index,1500);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
handleSet(str,result,index,time){
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
that.updateTextareaHeight();
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
}, 10);
|
|
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
that.showLoad = false;
|
|
|
|
|
|
// const typingInterval = setInterval(() => {
|
|
|
|
|
|
// if (index < str.length) {
|
|
|
|
|
|
// result += str[index];
|
|
|
|
|
|
// that.list[that.list.length - 1].msg = result
|
|
|
|
|
|
// index++;
|
|
|
|
|
|
// that.scrollToBottom();
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
that.list[that.list.length - 1].isShowIcon = true;
|
|
|
|
|
|
// clearInterval(typingInterval);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }, 100); // 每100ms显示一个字符,可以根据需要调整速度
|
|
|
|
|
|
}, time);
|
|
|
|
|
|
},
|
|
|
|
|
|
getRandomElements(array, count) {
|
|
|
|
|
|
let shuffled = array.slice();
|
|
|
|
|
|
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
|
|
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
|
|
|
|
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
|
|
|
|
}
|
|
|
|
|
|
return shuffled.slice(0, count);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getNewList($str,callback=()=>{}){
|
|
|
|
|
|
let that = this;
|
|
|
|
|
|
that.G.Get(that.api.chat_ai_job + '?storeJobIds=' + $str,{},(res)=>{
|
|
|
|
|
|
console.log('获取聊天职位列表:',res)
|
|
|
|
|
|
if (res.list && res.list.length > 0) {
|
|
|
|
|
|
res.list = that.G.toGetAddress(res.list);
|
|
|
|
|
|
res.list = that.G.toGetAge(res.list);
|
|
|
|
|
|
res.list = that.G.yijobCopy(res.list);
|
|
|
|
|
|
that.allJob = res.list.map(item => {
|
|
|
|
|
|
return {
|
|
|
|
|
|
...item,
|
|
|
|
|
|
isToggle:false,
|
|
|
|
|
|
_time:that.G.setDeadLine(item.updateTime,'jiaofu'),
|
|
|
|
|
|
liuNum: item.liuNum,
|
|
|
|
|
|
baoNum: uni.getStorageSync("lin-bao") ? uni.getStorageSync("lin-bao") / 10 : Math.ceil(item.liuNum / 10),
|
|
|
|
|
|
collected: item.collected ? true : false,
|
|
|
|
|
|
cus_price: item.salaryClassify != 7 ? that.G.getSalaryClassifyValueHtml(item.salaryClassify, item.salaryClassifyValue) : "月薪",
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
that.allJob = [];
|
|
|
|
|
|
};
|
|
|
|
|
|
setTimeout(()=>{
|
|
|
|
|
|
that.scrollToBottom();
|
|
|
|
|
|
callback();
|
|
|
|
|
|
},300);
|
|
|
|
|
|
callback();
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
animate() {
|
|
|
|
|
|
uni.vibrateShort({
|
|
|
|
|
|
success: function() {
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
|
.g_c_b {
|
|
|
|
|
|
color: #bbb;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.p-home-chat {
|
|
|
|
|
|
background-color: #efefef;
|
|
|
|
|
|
.g_bg_f0a{
|
|
|
|
|
|
background-color: #CC463A;
|
|
|
|
|
|
}
|
|
|
|
|
|
.chat-content {
|
|
|
|
|
|
width: calc(100% - 0px);
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
padding-bottom: 100px;
|
|
|
|
|
|
|
|
|
|
|
|
.chat-left {
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
|
|
|
|
|
|
.msg {
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
// letter-spacing: 1.5px;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chat-right {
|
|
|
|
|
|
padding: 0 10px;
|
|
|
|
|
|
.msg {
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
// letter-spacing: 1.5px;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chat-operate {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
|
|
|
|
|
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
|
|
|
|
|
padding-top: 12px;
|
|
|
|
|
|
background-color: #efefef;
|
|
|
|
|
|
|
|
|
|
|
|
.m-input {
|
|
|
|
|
|
width: calc(100% - 20px);
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
border-radius: 40px;
|
|
|
|
|
|
height: 56px;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
input {
|
|
|
|
|
|
height: 56px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.btn-share {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.longpress-top-mask {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
// bottom: 120px;
|
|
|
|
|
|
width: 100vw;
|
|
|
|
|
|
// height: 170px;
|
|
|
|
|
|
z-index: 99;
|
|
|
|
|
|
background-color: rgba(245, 245, 245, 0.5);
|
|
|
|
|
|
box-shadow: 0 -5px 10px rgba(245, 245, 245, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.longpress-bottom-mask {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
width: 100vw;
|
|
|
|
|
|
// height: 170px;
|
|
|
|
|
|
z-index: 99;
|
|
|
|
|
|
background-color: rgba(245, 245, 245, 0.5);
|
|
|
|
|
|
box-shadow: 0 -5px 10px rgba(245, 245, 245, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@keyframes voi_animate {
|
|
|
|
|
|
0% {
|
|
|
|
|
|
height: 50%;
|
|
|
|
|
|
background-color: #1677ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
20% {
|
|
|
|
|
|
height: 50%;
|
|
|
|
|
|
background-color: #92F7FE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
50% {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background-color: #1989fa;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
80% {
|
|
|
|
|
|
height: 50%;
|
|
|
|
|
|
background-color: #92F7FE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
100% {
|
|
|
|
|
|
height: 50%;
|
|
|
|
|
|
background-color: #1677ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.column-voice {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 22px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
// max-width: calc(100% - 140px);
|
|
|
|
|
|
max-width: calc(100% - 140px);
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
|
|
|
|
|
|
.column-item {
|
|
|
|
|
|
width: 3px;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
margin-left: 6px;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
background-color: #1677ff;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 容器样式 */
|
|
|
|
|
|
.loader {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
// justify-content: center;
|
|
|
|
|
|
// align-items: center;
|
|
|
|
|
|
// height: 100vh; /* 使容器占据整个视口的高度 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 单个点的样式 */
|
|
|
|
|
|
.dot {
|
|
|
|
|
|
width: 10px;
|
|
|
|
|
|
height: 10px;
|
|
|
|
|
|
margin: 0 2px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background-color: #666;
|
|
|
|
|
|
animation: dotPulse 1s infinite ease-in-out;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 动画定义 */
|
|
|
|
|
|
@keyframes dotPulse {
|
|
|
|
|
|
|
|
|
|
|
|
0%,
|
|
|
|
|
|
80%,
|
|
|
|
|
|
100% {
|
|
|
|
|
|
transform: scale(0.9);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
40% {
|
|
|
|
|
|
transform: scale(1.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 第二个点的延时 */
|
|
|
|
|
|
.dot:nth-child(2) {
|
|
|
|
|
|
animation-delay: -0.33s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 第三个点的延时 */
|
|
|
|
|
|
.dot:nth-child(3) {
|
|
|
|
|
|
animation-delay: -0.66s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.container {
|
|
|
|
|
|
// position: relative;
|
|
|
|
|
|
// overflow-y: auto; /* 设置滚动条 */
|
|
|
|
|
|
// height: 100%; /* 设置容器高度 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
textarea {
|
|
|
|
|
|
resize: none;
|
|
|
|
|
|
/* 禁止手动调整大小 */
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
/* 隐藏超出部分 */
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
/* 设置宽度 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hasTopPadding {
|
|
|
|
|
|
padding-top: 8px !important;
|
|
|
|
|
|
box-sizing: content-box !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
</style>
|