wujingling0908 2 weeks ago
commit ca109b8703
  1. 25
      src/components/chat-new.vue
  2. 23
      src/components/footer-bar-btn.vue
  3. 42
      src/components/footer-bar.vue
  4. 5
      src/components/history-content.vue
  5. 27
      src/components/history-main.vue

@ -4,7 +4,7 @@ import { showToast } from 'vant'
import _ from 'lodash'
import { showImagePreview } from 'vant'
import xss from 'xss'
import footerBarInput from '@/components/footer-bar-input.vue'
import footerBar from '@/components/footer-bar.vue'
import hotQuestionNew from '@/components/hot-question-new.vue'
import welcomes from '@/components/welcomes.vue'
import abstract from '@/components/abstract.vue'
@ -27,6 +27,9 @@ const userId = inject('userId', ref(''))
const isLostMessage = inject('isLostMessage', ref(null))
const mainContainerRef = ref(null)
// 参考 liics/chat-main 的 tokenExist:token 获取成功后才渲染聊天主内容
const tokenExist = computed(() => Boolean(store?.token))
const historylist = ref([])
const pageNum = ref(1)
const pageSize = ref(10)
@ -49,8 +52,8 @@ function isImageMessage(item) {
return !isTextAnswer && (
item?.message?.[0]?.type === 'image' ||
isProtocolImage ||
Boolean((item?.imageUrl || item?.imageKey || options.imageUrl || options.imageKey || raw.imgUrl || raw.imgKey || raw.fileKey) && !raw.msgText)
isProtocolImage ||
Boolean((item?.imageUrl || item?.imageKey || options.imageUrl || options.imageKey || raw.imgUrl || raw.imgKey || raw.fileKey) && !raw.msgText)
)
}
@ -329,17 +332,17 @@ watch(
<van-icon name="warning-o" size="22px" />
</div>
</template>
<span v-else class="message-text" v-html="getItemHtml(item)"></span>
</div>
</div>
<div class="msg-item from-bot" v-if="showTyping">
<div class="bubble typing"><span></span><span></span><span></span></div>
</div>
</div> -->
<span v-else class="message-text" v-html="getItemHtml(item)"></span>
</div>
</div>
<div class="msg-item from-bot" v-if="showTyping">
<div class="bubble typing"><span></span><span></span><span></span></div>
</div>
</div> -->
<chatContent :historylist="chatArr" />
</div>
<div class="chat-footer">
<footer-bar-input />
<footer-bar v-if="tokenExist" :tokenExist="tokenExist" />
</div>
</div>
</template>

@ -2,15 +2,8 @@
<div v-if="keyWordshow && manualService == '1'" class="qipaomain">
<div v-for="(item, index) in keywordslist" :key="index">
<div class="footer-bar-btn an-move-left" :class="elder ? 'elder-wrapper' : ''">
<a
href="javascript:;"
class="footer-items-list _line-fine-btn"
v-for="(item1, index1) in item"
:key="index1"
v-show="item1.name"
@click="keywordsClick(item1)"
>{{ longToShort(item1.name) }}</a
>
<a href="javascript:;" class="footer-items-list _line-fine-btn" v-for="(item1, index1) in item" :key="index1"
v-show="item1.name" @click="keywordsClick(item1)">{{ longToShort(item1.name) }}</a>
</div>
</div>
</div>
@ -74,6 +67,7 @@ function keywordsClick(item) {
}
async function initFooterBtn() {
const param = {
category: 4,
source: source.value || source,
@ -84,6 +78,7 @@ async function initFooterBtn() {
Post('config/activity', param)
.then((res) => {
console.log('config/activity 响应:', res)
if (res.code && res.code !== 0) return
for (let i = 0; i < 3; i++) {
const list = []
@ -94,16 +89,20 @@ async function initFooterBtn() {
}
if (keywordslist.value.length > 0) keyWordshow.value = true
})
.catch(console.log)
.catch((err) => {
console.log('config/activity 失败:', err)
})
}
function longToShort(name) {
return name.length > 6 ? name.slice(0, 5) + '...' : name
}
onMounted(() => initFooterBtn())
onMounted(() => {
initFooterBtn()
})
</script>
<style scoped>
/* ... 样式保持不变 ... */
</style>
</style>

@ -1,20 +1,20 @@
<template>
<div class="footer-bar" style="max-width: 750px">
<div class="footer-item footerBtn" v-show="footer_btn_type === 'footerBtn'">
<footer-bar-btn @onFooterBtnChoose="handleFooterBtnChoose" v-if="tokenExist && showQiPao"></footer-bar-btn>
</div>
<div class="footer-item footer-tips" v-if="manualService == 2">
<van-notice-bar mode="closeable" :scrollable="true" class="custom-notice-bar">
<template #left-icon>
<img class="notice-speaker" src="@/assets/images/noticeSpeaker.png" alt="" />
</template>
咨询中离开页面超过<span class="danger-text">3分钟</span>,可能会导致会话断开哦~若仍需咨询,可再次进入洋洋客服。
</van-notice-bar>
</div>
<div class="footer-item footerInput" v-show="footer_input_type === 'footerInput'">
<footer-bar-input ref="barInputCompontent"></footer-bar-input>
</div>
<div class="footer-bar" style="max-width: 750px">
<div class="footer-item footerBtn" v-show="footer_btn_type === 'footerBtn'">
<footer-bar-btn @onFooterBtnChoose="handleFooterBtnChoose" v-if="tokenExist && showQiPao"></footer-bar-btn>
</div>
<div class="footer-item footer-tips" v-if="manualService == 2">
<van-notice-bar mode="closeable" :scrollable="true" class="custom-notice-bar">
<template #left-icon>
<img class="notice-speaker" src="@/assets/images/noticeSpeaker.png" alt="" />
</template>
咨询中离开页面超过<span class="danger-text">3分钟</span>,可能会导致会话断开哦~若仍需咨询,可再次进入洋洋客服。
</van-notice-bar>
</div>
<div class="footer-item footerInput" v-show="footer_input_type === 'footerInput'">
<footer-bar-input ref="barInputCompontent"></footer-bar-input>
</div>
</div>
</template>
<script setup>
@ -23,7 +23,7 @@ import footerBarBtn from '@/components/footer-bar-btn.vue'
import footerBarInput from '@/components/footer-bar-input.vue'
const props = defineProps({
tokenExist: { type: Boolean, default: false },
tokenExist: { type: Boolean, default: false },
})
const source = inject('source', ref(''))
@ -35,16 +35,16 @@ const footer_input_type = ref('footerInput')
const showQiPao = ref(true)
onMounted(() => {
const src = source.value || source
if ((src === '95290000' || src === '95460000' || src === '95830000') && elder) {
showQiPao.value = false
}
const src = source.value || source
if ((src === '95290000' || src === '95460000' || src === '95830000') && elder) {
showQiPao.value = false
}
})
function handleFooterBtnChoose(item) { }
function offEmoticonsPictures() {
// 需要在父组件中通过 ref 调用
// 需要在父组件中通过 ref 调用
}
</script>

@ -16,6 +16,7 @@ import EditAddress from '@/components/edit-address.vue'
import PolicyList from '@/components/policyList.vue'
import XuqiPolicyList from '@/components/xuqiPolicyList.vue'
import imageService from '@/utils/imageService'
import { FormatDate } from '@/utils/filters'
const props = defineProps({
historylist: { type: Array, default: () => [] },
@ -126,10 +127,10 @@ onMounted(() => { processedEmoji() })
<template>
<div class="history-content-box" :class="elder ? 'elder-wrapper' : ''" v-if="historylist && historylist.length > 0">
<div class="chat-content-box-item" v-for="(item, index) in historylist" :key="index"
<div class="chat-content-box-item" v-for="(item, index) in historylist" :key="index" :id="item.VIEW_ID"
v-show="(item.msgText && item.msgText != 'null') || isImageMessage(item) || item.cmd === 'ServiceSessionOpenedEvent'">
<div class="time-show" v-if="showTimeLabel(item)">
<span class="session-tips">{{ item.timestamp | FormatDate('MM月dd日 hh:mm') }}</span>
<span class="session-tips">{{ FormatDate(item.timestamp, 'yyyy年MM月dd日 hh:mm') }}</span>
</div>
<div class="margin-bottom-10" v-else></div>

@ -32,17 +32,18 @@
<van-popup
class="edit-address-popup-box"
v-model:show="isEditShow"
get-container="body"
teleport="body"
position="bottom"
:duration="0.2"
>
<van-date-picker
type="year-month"
v-model="currentDate"
title="选择年月"
:min-date="minDate"
:max-date="maxDate"
:columns-type="['year', 'month']"
:formatter="pickerFormatter"
@confirm="onconfirm"
v-model="currentDate"
/>
</van-popup>
</div>
@ -77,7 +78,10 @@ const userInfo = inject('userInfo', ref({}))
const notitle = inject('notitle', ref(''))
const elder = inject('elder', false)
const currentDate = ref(new Date())
const currentDate = ref([
String(new Date().getFullYear()),
String(new Date().getMonth() + 1).padStart(2, '0'),
])
const minDate = computed(() => {
var now = new Date()
@ -245,10 +249,19 @@ function isNoticeFn(val) {
isNoticeShow.value = val
}
function onconfirm(picker) {
var year = new Date(picker).getFullYear()
var month = new Date(picker).getMonth() + 1
function pickerFormatter(type, option) {
if (type === 'year') return { ...option, text: `${option.text}年` }
if (type === 'month') return { ...option, text: `${option.text}月` }
return option
}
function onconfirm({ selectedValues }) {
const year = Number(selectedValues[0])
const month = Number(selectedValues[1])
startDate.value = new Date(year, month - 1, 1)
pageNum.value = 1
historylist.value = []
nolist.value = false
upCallback()
isEditShow.value = false
}

Loading…
Cancel
Save