Merge branch 'dev-AI-v5' into dev

This commit is contained in:
lifizer
2026-07-02 10:46:23 +08:00
15 changed files with 878 additions and 157 deletions
+9 -5
View File
@@ -112,6 +112,10 @@ export default {
keyboardHeight: { keyboardHeight: {
type: Number, type: Number,
default: 0 default: 0
},
voiceException: {
type: String,
default: '没有听清您说了什么,请再说一遍'
} }
}, },
data() { data() {
@@ -262,11 +266,11 @@ export default {
fail: err => { fail: err => {
console.log(err) console.log(err)
uni.hideLoading() uni.hideLoading()
_this.$toast('没有听清您说了什么,请再说一遍') _this.$toast(_this.voiceException)
} }
}) })
} else { } else {
_this.$toast('没有听清您说了什么,请再说一遍') _this.$toast(_this.voiceException)
} }
}) })
} }
@@ -282,7 +286,7 @@ export default {
_this.getTransResultReq() _this.getTransResultReq()
}).catch(() => { }).catch(() => {
uni.hideLoading() uni.hideLoading()
_this.$toast('没有听清您说了什么,请再说一遍') _this.$toast(_this.voiceException)
}) })
}, },
getTransResultReq() { getTransResultReq() {
@@ -296,7 +300,7 @@ export default {
uni.hideLoading() uni.hideLoading()
_this.clearIntervalFn() _this.clearIntervalFn()
if (data === '__NULL__') { if (data === '__NULL__') {
_this.$toast('没有听清您说了什么,请再说一遍') _this.$toast(_this.voiceException)
} else { } else {
if (data.length > 0) { if (data.length > 0) {
const prompt = data[0].Text const prompt = data[0].Text
@@ -308,7 +312,7 @@ export default {
} }
}).catch(() => { }).catch(() => {
uni.hideLoading() uni.hideLoading()
_this.$toast('没有听清您说了什么,请再说一遍') _this.$toast(_this.voiceException)
}) })
}, 1000) }, 1000)
}, },
+28 -4
View File
@@ -112,7 +112,9 @@
<script> <script>
import { import {
getChatList, getChatList,
deleteChatListByType deleteChatListByType,
getCountyAiChatList,
deleteCountyChatListByType
} from '@/api/chat/index' } from '@/api/chat/index'
export default { export default {
name: 'AiHistoryList', name: 'AiHistoryList',
@@ -125,6 +127,10 @@ export default {
formModule: { formModule: {
type: String, type: String,
default: '' default: ''
},
countyId: {
type: String,
default: ''
} }
}, },
data() { data() {
@@ -142,7 +148,17 @@ export default {
this.getChatListReq() this.getChatListReq()
}, },
getChatListReq() { getChatListReq() {
getChatList().then(res => { let reqFn = null
let params = {}
if (this.countyId) {
reqFn = getCountyAiChatList
params = {
countyId: this.countyId
}
} else {
reqFn = getChatList
}
reqFn(params).then(res => {
const { success, data } = res const { success, data } = res
if (success) { if (success) {
this.todayList = data['今天'] || [] this.todayList = data['今天'] || []
@@ -152,7 +168,15 @@ export default {
}) })
}, },
deleteRecords(type) { deleteRecords(type) {
deleteChatListByType(type).then(res => { let reqFn = null
let params = ''
if (this.countyId) {
reqFn = deleteCountyChatListByType
params = `?countyId=${this.countyId}&type=${type}`
} else {
reqFn = deleteChatListByType
}
reqFn(type, params).then(res => {
const { success } = res const { success } = res
if (success) { if (success) {
this.getChatListReq() this.getChatListReq()
@@ -160,7 +184,7 @@ export default {
}) })
}, },
historyItemClick(item) { historyItemClick(item) {
const paramsStr = `?chatNumber=${item.chatNumber}&title=${item.title}&click=1` const paramsStr = `?chatNumber=${item.chatNumber}&title=${item.title}&click=1&countyId=${this.countyId}`
if (!this.formModule) { if (!this.formModule) {
uni.navigateTo({ uni.navigateTo({
url: '/aiChat/views/history' + paramsStr url: '/aiChat/views/history' + paramsStr
+8 -5
View File
@@ -100,10 +100,7 @@ export const chatMixins = {
}.bind(this)).exec() }.bind(this)).exec()
}, },
onUnload() { onUnload() {
if (this.audioContext) { this.audioStopHandle()
this.audioContext.stop()
}
wx.getBackgroundAudioManager().stop()
this.closeWsFn() this.closeWsFn()
}, },
created() { created() {
@@ -447,9 +444,15 @@ export const chatMixins = {
this.audioAyy = [] this.audioAyy = []
if (this.audioContext) { if (this.audioContext) {
this.audioContext.stop() this.audioContext.stop()
this.audioContext.destroy() // 强制销毁释放资源
this.audioContext = null
} }
this.isPlayAudio = false this.isPlayAudio = false
wx.getBackgroundAudioManager().stop()
// 强制关闭微信小程序背景音频
if (typeof wx !== 'undefined' && wx.getBackgroundAudioManager) {
wx.getBackgroundAudioManager().stop()
}
}, },
ttsHandle(item) { ttsHandle(item) {
this.audioAyy = [] this.audioAyy = []
+327 -89
View File
@@ -3,9 +3,18 @@ import {
getCompletionsV3, getCompletionsV3,
deleteChatItemByConversationId, deleteChatItemByConversationId,
// getAnalyzeKeywordsV1, // getAnalyzeKeywordsV1,
getAnalyzeKeywordsChangeV3 getAnalyzeKeywordsChangeV3,
getSseCountyAiConfigV1,
getCountyAiCompletionsV1,
getGiftRecommendOptions,
getGiftRecommendPrompt
} from '@/api/chat/index' } from '@/api/chat/index'
import { import {
getExceptionConfig,
getBottomNavigationConfigList
} from '@/api/public'
import {
getProductDetail,
postCartAdd postCartAdd
} from '@/api/store' } from '@/api/store'
import { VUE_APP_API_URL } from '@/config' import { VUE_APP_API_URL } from '@/config'
@@ -21,29 +30,7 @@ export const chatMixinsV2 = {
token: cookie.get('login_status'), token: cookie.get('login_status'),
userInfo: cookie.get('userInfo'), userInfo: cookie.get('userInfo'),
webUrl: this.$VUE_APP_RESOURCES_URL, webUrl: this.$VUE_APP_RESOURCES_URL,
bottomTools: Object.freeze([ bottomTools: [],
{
icon: 'icon-50',
text: '我要送礼',
type: 'prompt',
prompt: '我要送礼,请给我推荐一些平台的礼品',
url: ''
},
{
icon: 'icon-51',
text: '订单查询',
type: 'prompt',
prompt: '帮我查询我的待发货、待收货订单信息',
url: ''
},
{
icon: 'icon-52',
text: '拍照识图',
type: 'link',
prompt: '',
url: '/aiChat/views/imageRecognition'
}
]),
scrollData: {}, scrollData: {},
scrollTop: 0, scrollTop: 0,
isScrollToBottom: false, isScrollToBottom: false,
@@ -57,31 +44,19 @@ export const chatMixinsV2 = {
loading: false, loading: false,
chatNumber: '', chatNumber: '',
infoResData: {}, infoResData: {},
chatMessageList: [ chatMessageList: [],
/*
{
type: -2,
isError: false,
showCursor: false,
conversationId: '',
prompt: '',
nodes: '-------------监听 WebSocket 接受到服务器的消息事件',
content: '-------------监听 WebSocket 接受到服务器的消息事件',
listQuestion: [
'监听 WebSocket 接受到服务器的消息事件',
'监听 WebSocket 接受到服务器的消息事件',
'监听 WebSocket 接受到服务器的消息事件'
]
}
*/
],
errorMsg: Object.freeze('您提的问题未能理解,云灵思想跑偏啦,重新整理一下问题或者重新提问,让云灵再试试!'),
audioAyy: [], audioAyy: [],
isPlayAudio: false, isPlayAudio: false,
audioContext: null, audioContext: null,
audioPlayId: '', audioPlayId: '',
showGiftBtn: false, showGiftBtn: false,
buyLoading: false buyLoading: false,
exceptionConfig: {
model_exception: '您提的问题未能理解,云灵思想跑偏啦,重新整理一下问题或者重新提问,让云灵再试试!',
voice_exception: ''
},
giftStepLoading: false,
onlyOneToAddCart: false
} }
}, },
computed: { computed: {
@@ -106,12 +81,12 @@ export const chatMixinsV2 = {
}.bind(this)).exec() }.bind(this)).exec()
}, },
onUnload() { onUnload() {
if (this.audioContext) { this.audioStopHandle()
this.audioContext.stop()
}
wx.getBackgroundAudioManager().stop()
this.closeWsFn() this.closeWsFn()
}, },
onHide() {
this.audioStopHandle()
},
created() { created() {
const _this = this const _this = this
uni.getSystemInfo({ uni.getSystemInfo({
@@ -131,7 +106,37 @@ export const chatMixinsV2 = {
}, },
methods: { methods: {
createdCallbak() { createdCallbak() {
console.log('页面初始话回调') this.$nextTick(() => {
this.scrollToBottomHandle()
getExceptionConfig().then(res => {
const { success, data } = res
if (success) {
this.exceptionConfig = data || {}
}
})
// 县域AI没有底部快捷操作和送礼配置
if (!this.countyId) {
getBottomNavigationConfigList().then(res => {
const { success, data } = res
if (success) {
this.bottomTools = data || []
this.bottomTools.forEach(item => {
item.display = true
})
}
})
getGiftRecommendOptions().then(res => {
const { success, data } = res
if (success) {
this.giftBuyOptions = data || {}
}
})
}
this.extraReqFn()
})
},
extraReqFn() {
console.log('首页/历史详情页面单独请求接口逻辑')
}, },
inputFocusHandle(value) { inputFocusHandle(value) {
this.onFocus = value === 1 this.onFocus = value === 1
@@ -215,7 +220,16 @@ export const chatMixinsV2 = {
handleLoginFailure() handleLoginFailure()
return return
} }
const prompt = params.prompt if (params.prompt.length > 500) {
uni.showToast({
title: "字数已超出限制",
icon: "none",
duration: 5000
})
return
}
if (this.loading) return
const prompt = params.prompt.substr(0, 500)
if (params.init !== 1) { if (params.init !== 1) {
_this.chatMessageList.push({ _this.chatMessageList.push({
prompt, prompt,
@@ -257,21 +271,49 @@ export const chatMixinsV2 = {
}) })
_this.loading = true _this.loading = true
_this.showCursor = false _this.showCursor = false
getSseConfigV1({ let reqFn = null
'chatNumber': _this.chatNumber, let postData = {}
prompt if (_this.countyId) {
}).then(resConfig => { reqFn = getSseCountyAiConfigV1
postData = {
'countyId': _this.countyId,
'chatNumber': _this.chatNumber,
prompt
}
} else {
reqFn = getSseConfigV1
postData = {
'chatNumber': _this.chatNumber,
prompt
}
}
reqFn(postData).then(resConfig => {
const conversationId = resConfig.data.conversationId const conversationId = resConfig.data.conversationId
_this.chatNumber = resConfig.data.chatNumber || '' _this.chatNumber = resConfig.data.chatNumber || ''
_this.chatMessageList[_this.chatMessageListLength - 1].showCursor = true _this.chatMessageList[_this.chatMessageListLength - 1].showCursor = true
_this.chatMessageList[_this.chatMessageListLength - 1].conversationId = conversationId _this.chatMessageList[_this.chatMessageListLength - 1].conversationId = conversationId
if (conversationId) { if (conversationId) {
_this.initWebSocket(conversationId, () => { _this.initWebSocket(conversationId, () => {
getCompletionsV3({
conversationId, let completionsReqFn = null
ws: true, let completionsPostData = {}
isNoNeedPublicErrorNotification: 1 if (_this.countyId) {
}).then(sseRes => { completionsReqFn = getCountyAiCompletionsV1
completionsPostData = {
conversationId,
countyId: _this.countyId,
ws: true,
isNoNeedPublicErrorNotification: 1
}
} else {
completionsReqFn = getCompletionsV3
completionsPostData = {
conversationId,
ws: true,
isNoNeedPublicErrorNotification: 1
}
}
completionsReqFn(completionsPostData).then(sseRes => {
console.log(sseRes) console.log(sseRes)
// _this.closeWsFn() // _this.closeWsFn()
}).catch(err => { }).catch(err => {
@@ -483,16 +525,59 @@ export const chatMixinsV2 = {
}) })
}, },
productItemBuyNowClickHandle(item) { productItemBuyNowClickHandle(item) {
this.audioStopHandle()
this.showGiftBtn = false this.showGiftBtn = false
this.cart_num = 1 this.productItemBuyNowOrGiftBuy(item, 1)
this.addToCart(item)
}, },
productItemGiftBuyClickHandle(item) { productItemGiftBuyClickHandle(item) {
this.audioStopHandle()
this.showGiftBtn = true this.showGiftBtn = true
this.productItemBuyNowOrGiftBuy(item, 2)
},
productItemBuyNowOrGiftBuy(item, BuyNowOrGiftBuyType) {
this.audioStopHandle()
this.cart_num = 1 this.cart_num = 1
this.addToCart(item) this.m_id = item.id
getProductDetail(item.id).then(res => {
const { data } = res
this.storeInfo = {...data.storeInfo}
if(data.storeInfo.stock === 0) {
uni.showToast({
title: "产品库存不足,请选择其他商品",
icon: "none",
duration: 5000
})
return
}
this.isWenwan = data.isWenwan
this.qualifications = data.qualifications || []
// 给 attr 赋值,将请求回来的规格赋值给 attr
if (this.source !== 'pre' && this.source !== 'day' && this.source !== 'kill' && this.source !== 'spe') {
this.attr.productAttr = data.productAttr || []
this.productValueArr = []
for (const key in data.productValue) {
this.productValueArr.push({
attrItemkey: key,
...data.productValue[key]
})
}
// 初始化认为所有的规格都是可以选的
this.attr.productAttr.map(item => {
item.attrValue.map(subItem => {
subItem.canUsed = true
})
})
}
this.attr.defaultSku = data.defaultSku
this.attr.defaultSkuIndex = data.defaultSkuIndex
this.DefaultSelect()
// 是否单一规格
const onlyOne = Object.keys(data.productValue).length === 1
if(onlyOne) {
this.buyNowOrGiftBuyReq(BuyNowOrGiftBuyType)
return
}
this.attr.cartAttr = !this.isOpen ? true : false
})
}, },
buyNowOrGiftBuyReq(type) { buyNowOrGiftBuyReq(type) {
const _this = this const _this = this
@@ -570,8 +655,8 @@ export const chatMixinsV2 = {
}, },
chatErrorSetContent() { chatErrorSetContent() {
this.chatMessageList[this.chatMessageListLength - 1].isError = true this.chatMessageList[this.chatMessageListLength - 1].isError = true
this.chatMessageList[this.chatMessageListLength - 1].content = this.errorMsg this.chatMessageList[this.chatMessageListLength - 1].content = this.exceptionConfig.model_exception
this.chatMessageList[this.chatMessageListLength - 1].nodes = this.errorMsg this.chatMessageList[this.chatMessageListLength - 1].nodes = this.exceptionConfig.model_exception
this.closeWsFn() this.closeWsFn()
}, },
closeWsFn() { closeWsFn() {
@@ -589,13 +674,26 @@ export const chatMixinsV2 = {
}) })
}, },
audioStopHandle() { audioStopHandle() {
// 强制关闭微信小程序背景音频
try {
const bgAudio = wx.getBackgroundAudioManager ? wx.getBackgroundAudioManager() : null
if (bgAudio && typeof bgAudio.stop === 'function') {
bgAudio.stop()
bgAudio.src = ''
bgAudio.title = ''
}
} catch (e) {
console.warn('stop background audio failed', e)
}
this.audioPlayId = ''
// Fix bug#4049 // Fix bug#4049
this.audioAyy = [] this.audioAyy = []
if (this.audioContext) { if (this.audioContext) {
this.audioContext.stop() this.audioContext.stop()
this.audioContext.destroy() // 强制销毁释放资源
this.audioContext = null
} }
this.isPlayAudio = false this.isPlayAudio = false
wx.getBackgroundAudioManager().stop()
}, },
ttsHandle(item) { ttsHandle(item) {
this.audioAyy = [] this.audioAyy = []
@@ -604,13 +702,13 @@ export const chatMixinsV2 = {
// this.audioContext.destroy() // this.audioContext.destroy()
} }
// 如果正在播放,点击当前播放的则认为是暂停 // 如果正在播放,点击当前播放的则认为是暂停
if (this.isPlayAudio && item.conversationId === this.audioPlayId) { if (this.isPlayAudio && [item.conversationId, item.messageId, item.parentMessageId].includes(this.audioPlayId)) {
this.isPlayAudio = false this.isPlayAudio = false
this.audioPlayId = '' this.audioPlayId = ''
return return
} }
this.isPlayAudio = false this.isPlayAudio = false
this.audioPlayId = item.conversationId this.audioPlayId = item.conversationId || item.messageId || item.parentMessageId
const flag = 1 const flag = 1
if (flag === 1) { if (flag === 1) {
console.log(removeMarkdown(item.content).replace(/[\n\t\s]/g, '')) console.log(removeMarkdown(item.content).replace(/[\n\t\s]/g, ''))
@@ -674,34 +772,74 @@ export const chatMixinsV2 = {
} }
}, },
playNextChunk() { playNextChunk() {
if (this.audioAyy.length > 0 && this.audioPlayId) { if (!this.audioAyy.length || !this.audioPlayId) {
const src = this.audioAyy.shift()
this.isPlayAudio = true
const audioContext = uni.createInnerAudioContext({
// 是否使用 WebAudio 作为底层音频驱动,默认关闭。对于短音频、播放频繁的音频建议开启此选项,开启后将获得更优的性能表现。由于开启此选项后也会带来一定的内存增长,因此对于长音频建议关闭此选项
useWebAudioImplement: false
})
this.audioContext = audioContext
audioContext.src = src
audioContext.onEnded(() => {
audioContext.destroy()
this.playNextChunk()
})
audioContext.play()
console.log('------------src' + src)
} else {
console.log('------------end')
this.isPlayAudio = false this.isPlayAudio = false
return
} }
// 销毁旧实例
if (this.audioContext) {
this.audioContext.stop()
this.audioContext.destroy()
this.audioContext = null
}
const src = this.audioAyy.shift()
this.isPlayAudio = true
const audioContext = uni.createInnerAudioContext({
useWebAudioImplement: true // 短音频建议 true
})
this.audioContext = audioContext
audioContext.src = src
audioContext.onPlay(() => {
console.log('audio play:', src)
})
audioContext.onEnded(() => {
this.audioContext = null
audioContext.destroy()
this.playNextChunk()
})
audioContext.onError((err) => {
console.error('audio error', err)
this.audioContext = null
audioContext.destroy()
this.playNextChunk()
})
audioContext.play()
}, },
bottomToolClickHandle(item) { bottomToolClickHandle(item) {
if (item.type === 'prompt') { // 非界面跳转的需要校验登录状态
if (!this.token && item.navType !== 'url') {
handleLoginFailure()
return
}
const idx = this.bottomTools.findIndex((i) => i.giftCardEnabled === 1)
if (item.giftCardEnabled === 1) {
// 新建会话
this.createNewHandle('giftChat')
this.$set(this, 'showGiftSteps', true)
if (idx > -1) {
this.$set(this.bottomTools[idx], 'display', false)
}
return
}
this.$set(this, 'showGiftSteps', false)
if (idx > -1) {
this.$set(this.bottomTools[idx], 'display', true)
}
if (item.navType === 'prompt') {
this.streamReq({ this.streamReq({
prompt: item.prompt, prompt: item.promptContent,
init: 0 init: 0
}) })
} }
if (item.type === 'link') { if (item.navType === 'url') {
uni.navigateTo({ uni.navigateTo({
url: item.url url: item.url
}) })
@@ -711,6 +849,106 @@ export const chatMixinsV2 = {
uni.navigateTo({ uni.navigateTo({
url: '/pagesOrder/order/OrderDetails/index?id=' + order.orderId url: '/pagesOrder/order/OrderDetails/index?id=' + order.orderId
}) })
},
isGiftOptionSelected(configId, optionId) {
if (!this.giftSelections[configId]) return false
return this.giftSelections[configId].includes(optionId)
},
toggleGiftOption(configId, optionId) {
if (!this.giftSelections[configId]) {
this.$set(this.giftSelections, configId, [])
}
const index = this.giftSelections[configId].indexOf(optionId)
if (index > -1) {
this.giftSelections[configId].splice(index, 1)
} else {
this.giftSelections[configId].push(optionId)
}
},
prevGiftStep() {
if (this.currentGiftStepIndex > 0) {
this.currentGiftStepIndex--
}
},
nextGiftStep() {
const currentStep = this.giftBuyOptions[this.currentGiftStepIndex]
let hasSelection = false
// 校验是否已选择
if (currentStep.type === 'option_card') {
const selectedIds = this.giftSelections[currentStep.id] || []
hasSelection = selectedIds.length > 0
} else if (currentStep.type === 'price_input') {
hasSelection = !!this.giftBudget
}
if (!hasSelection) {
uni.showToast({
title: '请完善信息后再点击下一步',
icon: 'none'
})
return
}
if (this.currentGiftStepIndex < this.giftBuyOptions.length - 1) {
this.currentGiftStepIndex++
} else {
this.finishGiftSteps()
}
},
skipGiftStep() {
if (this.currentGiftStepIndex < this.giftBuyOptions.length - 1) {
this.currentGiftStepIndex++
} else {
this.finishGiftSteps()
}
},
finishGiftSteps() {
if (this.giftStepLoading || this.loading) return
const selectedSteps = []
this.giftBuyOptions.forEach(step => {
if (step.type === 'option_card') {
const selectedIds = this.giftSelections[step.id] || []
if (selectedIds.length > 0) {
const selectedNames = step.options.filter(opt => selectedIds.includes(opt.id)).map(opt => opt.optionName)
selectedSteps.push({
sort: step.sort,
title: step.title,
type: step.type,
options: selectedNames
})
}
} else if (step.type === 'price_input') {
if (this.giftBudget) {
selectedSteps.push({
sort: step.sort,
title: step.title,
type: step.type,
options: [this.giftBudget]
})
}
}
})
console.log(selectedSteps)
uni.showLoading()
this.giftStepLoading = true
getGiftRecommendPrompt(selectedSteps).then(res => {
const { success, data } = res
if (success) {
this.showGiftSteps = false
this.streamReq({
prompt: data.prompt || '我想送礼',
init: 0
})
// 清空所有送礼选项
this.giftSelections = {}
this.giftBudget = ''
this.currentGiftStepIndex = 0
}
}).finally(() => {
uni.hideLoading()
this.giftStepLoading = false
})
} }
} }
} }
+53 -12
View File
@@ -45,14 +45,14 @@
</view> </view>
</view> </view>
<view v-if="item.type === -2" class="chat-message-body"> <view v-if="item.type === -2" class="chat-message-body">
<view v-if="item.nodes && item.nodes.length" class="avatar"> <view class="avatar">
<image <image
:src="webUrl + '/aiChat/avatar.png'" :src="webUrl + '/aiChat/avatar.png'"
class="chat-avatar" class="chat-avatar"
mode="widthFix" mode="widthFix"
/> />
</view> </view>
<view v-if="item.nodes && item.nodes.length" class="item-left"> <view class="item-left">
<view class="txt"> <view class="txt">
<view <view
ref="rich-text-box" ref="rich-text-box"
@@ -67,7 +67,7 @@
space="nbsp" space="nbsp"
/> />
<view v-if="!(item.nodes && item.nodes.length) && loading" class="loader-wrap"> <view v-if="!(item.nodes && item.nodes.length) && loading" class="loader-wrap">
<div class="loader" /> <div class="loading2" />
</view> </view>
</view> </view>
<view <view
@@ -109,13 +109,13 @@
</view> </view>
<view <view
:class="{ :class="{
'playing': audioPlayId === item.conversationId && isPlayAudio 'playing': [item.conversationId, item.messageId, item.parentMessageId].includes(audioPlayId) && isPlayAudio
}" }"
class="item" class="item"
@click="ttsHandle(item)" @click="ttsHandle(item)"
> >
<image <image
:src="webUrl + '/aiChat/' + ((audioPlayId === item.conversationId && isPlayAudio) ? 'audio-on' : 'audio-off') +'.png'" :src="webUrl + '/aiChat/' + (([item.conversationId, item.messageId, item.parentMessageId].includes(audioPlayId) && isPlayAudio) ? 'audio-on' : 'audio-off') +'.png'"
class="icon" class="icon"
mode="widthFix" mode="widthFix"
/> />
@@ -379,7 +379,12 @@
@click="scrollToBottomHandle" @click="scrollToBottomHandle"
/> />
</view> </view>
<view class="container"> <view
:class="{
'container-county': !!countyId
}"
class="container"
>
<view <view
v-if="chatNumber" v-if="chatNumber"
class="new-chat" class="new-chat"
@@ -393,17 +398,21 @@
开启新对话 开启新对话
</view> </view>
<view <view
v-if="!countyId"
v-for="(item, index) in bottomTools" v-for="(item, index) in bottomTools"
:key="index" :key="index"
:class="{
'hide': !item.display
}"
class="bottom-tool-item" class="bottom-tool-item"
@click="bottomToolClickHandle(item)" @click="bottomToolClickHandle(item)"
> >
<image <image
:src="webUrl + '/aiChat/' + item.icon + '.png'" :src="item.icon"
class="tool-icon" class="tool-icon"
mode="widthFix" mode="widthFix"
/> />
{{ item.text }} {{ item.name }}
</view> </view>
</view> </view>
</view> </view>
@@ -411,6 +420,7 @@
ref="bottomSend" ref="bottomSend"
:loading="loading" :loading="loading"
:keyboard-height="keyboardHeight" :keyboard-height="keyboardHeight"
:voice-exception="exceptionConfig.voice_exception"
@send="streamReq" @send="streamReq"
@history="historyViewHandle" @history="historyViewHandle"
@focus="inputFocusHandle" @focus="inputFocusHandle"
@@ -418,6 +428,7 @@
<AiHistoryList <AiHistoryList
ref="historyView" ref="historyView"
:status-bar-height="statusBarHeight" :status-bar-height="statusBarHeight"
:county-id="countyId"
form-module="history" form-module="history"
@enter-history="audioStopHandle" @enter-history="audioStopHandle"
/> />
@@ -445,7 +456,8 @@ import BottomSend from '../components/bottomSend.vue'
import OrderItem from '../components/orderItem.vue' import OrderItem from '../components/orderItem.vue'
import ProductWindow from '@/components/ProductWindow' import ProductWindow from '@/components/ProductWindow'
import { import {
historyChatMessage historyChatMessage,
getCountyAiHistoryChatMessage
} from '@/api/chat/index' } from '@/api/chat/index'
import { formatAiMsgContent } from '../utils/aiChat' import { formatAiMsgContent } from '../utils/aiChat'
export default { export default {
@@ -459,19 +471,27 @@ export default {
mixins: [chatMixinsV2, goCartMixin], mixins: [chatMixinsV2, goCartMixin],
data() { data() {
return { return {
pageTitle: '' pageTitle: '',
countyId: ''
} }
}, },
onLoad(options) { onLoad(options) {
this.chatNumber = options.chatNumber this.chatNumber = options.chatNumber
this.pageTitle = options.title this.pageTitle = options.title || ''
this.countyId = options.countyId || ''
this.pageTitle = this.pageTitle.length > 8 ? (this.pageTitle.substring(0, 8) + '...') : this.pageTitle this.pageTitle = this.pageTitle.length > 8 ? (this.pageTitle.substring(0, 8) + '...') : this.pageTitle
this.init() this.init()
}, },
methods: { methods: {
init() { init() {
this.loading = true this.loading = true
historyChatMessage({ let reqFn = null
if (this.countyId) {
reqFn = getCountyAiHistoryChatMessage
} else {
reqFn = historyChatMessage
}
reqFn({
chatNumber: this.chatNumber chatNumber: this.chatNumber
}).then(res => { }).then(res => {
const { success, data = [] } = res const { success, data = [] } = res
@@ -547,6 +567,9 @@ export default {
} }
}) })
console.log(this.chatMessageList) console.log(this.chatMessageList)
this.$nextTick(() => {
this.scrollToBottomHandle()
})
} catch (err) { } catch (err) {
uni.showModal({ uni.showModal({
title: '错误提示', title: '错误提示',
@@ -572,6 +595,24 @@ export default {
createNewHandle() { createNewHandle() {
uni.setStorageSync('addNewChat', '1') uni.setStorageSync('addNewChat', '1')
uni.navigateBack() uni.navigateBack()
},
bottomToolClickHandle(item) {
if (item.giftCardEnabled === 1) {
uni.setStorageSync('addNewChat', '2')
uni.navigateBack()
return
}
if (item.navType === 'prompt') {
this.streamReq({
prompt: item.promptContent,
init: 0
})
}
if (item.navType === 'url') {
uni.navigateTo({
url: item.url
})
}
} }
} }
} }
+21 -1
View File
@@ -38,7 +38,10 @@
</view> </view>
</view> </view>
<view class="sheet-divider" /> <view class="sheet-divider" />
<view class="goods-grid"> <view v-if="!loaded" class="loading-state">
<u-loading-icon mode="circle" size="36" text="正在识别中..." vertical textSize="14"></u-loading-icon>
</view>
<view v-else class="goods-grid">
<view <view
v-for="(item, index) in goodsList" v-for="(item, index) in goodsList"
:key="index" :key="index"
@@ -66,6 +69,9 @@
lazy-load lazy-load
/> />
</view> </view>
<view v-if="item.similarityScore > 0" class="goods-desc">
相似度{{ item.similarityScore }}%
</view>
</view> </view>
</view> </view>
</view> </view>
@@ -84,6 +90,7 @@ export default {
}, },
data() { data() {
return { return {
loaded: false,
webUrl: this.$VUE_APP_RESOURCES_URL, webUrl: this.$VUE_APP_RESOURCES_URL,
statusBarHeight: 20, statusBarHeight: 20,
imageUrl: '', imageUrl: '',
@@ -245,6 +252,13 @@ export default {
margin: 0 32rpx; margin: 0 32rpx;
} }
.loading-state {
padding: 120rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
.empty-state { .empty-state {
text-align: center; text-align: center;
} }
@@ -301,6 +315,12 @@ export default {
align-items: flex-end; align-items: flex-end;
justify-content: space-between; justify-content: space-between;
} }
.goods-desc {
padding: 10rpx 14rpx 20rpx 14rpx;
font-size: 24rpx;
color: #999;
line-height: 1;
}
.price-left { .price-left {
display: flex; display: flex;
+226 -34
View File
@@ -16,7 +16,7 @@
transparent="auto" transparent="auto"
barPlaceholder="hidden" barPlaceholder="hidden"
title="云灵" title="云灵"
@click-left="clickBackHandle" @click-left="pageContainerBeforeleave"
/> />
<page-container <page-container
:show="true" :show="true"
@@ -40,17 +40,25 @@
conversationId: '123' conversationId: '123'
})">播放</button> --> })">播放</button> -->
<block v-if="chatMessageListLength < 1"> <block v-if="chatMessageListLength < 1">
<view class="home-wrap"> <view
:class="{
'county-home-wrap': !!countyId
}"
class="home-wrap"
>
<view class="home-focus-wrap"> <view class="home-focus-wrap">
<view class="focus-guide-wrap"> <view class="focus-guide-wrap">
<view class="guide-left"> <view class="guide-left">
<image <image
:src="webUrl + '/aiChat/logo-01.gif'" :src="webUrl + '/aiChat/logo-transition.png'"
class="avatar" :class="{
'county-avatar': !!countyId
}"
class="avatar avatar-bounce"
mode="widthFix" mode="widthFix"
/> />
</view> </view>
<view class="guide-right"> <view v-if="!showGiftSteps" class="guide-right">
<view class="title">{{ settingInfo.helloMessageTitle }}</view> <view class="title">{{ settingInfo.helloMessageTitle }}</view>
<view class="content">{{ settingInfo.helloMessageContent }}</view> <view class="content">{{ settingInfo.helloMessageContent }}</view>
</view> </view>
@@ -99,7 +107,8 @@
</swiper-item> </swiper-item>
</swiper> </swiper>
</view> --> </view> -->
<view class="topic-wrap"> <!-- 大家都在问 -->
<view v-if="!showGiftSteps && !countyId" class="topic-wrap">
<view class="title"> <view class="title">
<view class="title-left">大家都在问</view> <view class="title-left">大家都在问</view>
<view class="title-right" @click="loadData('click')"> <view class="title-right" @click="loadData('click')">
@@ -133,6 +142,61 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 县域 -->
<view v-if="!showGiftSteps && countyId" class="county-tools-wrap">
<view class="list-cont">
<view
v-for="(item, index) in countyTools"
:key="index"
class="list-item"
@click="countyToolItemClickHandle(item)"
>
<image
:src="item.icon"
class="icon"
mode="widthFix"
/>
<view class="name">{{ item.name }}</view>
</view>
</view>
</view>
<!-- 在这里实现送礼步骤 -->
<view v-if="showGiftSteps" class="gift-steps-wrap">
<view
v-for="(item, index) in giftBuyOptions"
:key="index"
style="width: 100%;"
>
<view v-show="currentGiftStepIndex === index" class="gift-step-item">
<view class="gift-step-title">{{ item.title }}</view>
<view v-if="item.type === 'option_card'" class="gift-options">
<view
v-for="opt in item.options"
:key="opt.id"
class="gift-option-item"
:class="{ active: isGiftOptionSelected(item.id, opt.id) }"
@click="toggleGiftOption(item.id, opt.id)"
>
{{ opt.optionName }}
<image v-if="isGiftOptionSelected(item.id, opt.id)" :src="webUrl + '/aiChat/gift-options-check.png'" class="icon-check" />
</view>
</view>
<view v-if="item.type === 'price_input'" class="gift-price-input">
<view class="input-wrap">
<text class="label">价格预算</text>
<input v-model="giftBudget" placeholder="例如100以内/300~500元" class="input-budget" placeholder-style="color: #ccc;" />
</view>
</view>
</view>
</view>
<view class="gift-step-actions">
<view class="action-btn-group">
<view v-if="currentGiftStepIndex > 0" class="btn btn-prev" @click="prevGiftStep">上一步</view>
<view class="btn btn-next" :class="{'full-width': currentGiftStepIndex === 0}" @click="nextGiftStep">下一步</view>
</view>
<view class="btn-skip" @click="skipGiftStep">跳过</view>
</view>
</view>
</view> </view>
</block> </block>
<view v-if="chatMessageListLength > 0" class="chat-wrap"> <view v-if="chatMessageListLength > 0" class="chat-wrap">
@@ -224,13 +288,13 @@
</view> </view>
<view <view
:class="{ :class="{
'playing': audioPlayId === item.conversationId && isPlayAudio 'playing': [item.conversationId, item.messageId, item.parentMessageId].includes(audioPlayId) && isPlayAudio
}" }"
class="item" class="item"
@click="ttsHandle(item)" @click="ttsHandle(item)"
> >
<image <image
:src="webUrl + '/aiChat/' + ((audioPlayId === item.conversationId && isPlayAudio) ? 'audio-on' : 'audio-off') +'.png'" :src="webUrl + '/aiChat/' + (([item.conversationId, item.messageId, item.parentMessageId].includes(audioPlayId) && isPlayAudio) ? 'audio-on' : 'audio-off') +'.png'"
class="icon" class="icon"
mode="widthFix" mode="widthFix"
/> />
@@ -500,9 +564,14 @@
@click="scrollToBottomHandle" @click="scrollToBottomHandle"
/> />
</view> </view>
<view class="container"> <view
:class="{
'container-county': !!countyId
}"
class="container"
>
<view <view
v-if="chatNumber" v-if="chatNumber || showGiftSteps"
class="new-chat" class="new-chat"
@click="createNewHandle" @click="createNewHandle"
> >
@@ -514,17 +583,21 @@
开启新对话 开启新对话
</view> </view>
<view <view
v-if="!countyId"
v-for="(item, index) in bottomTools" v-for="(item, index) in bottomTools"
:key="index" :key="index"
:class="{
'hide': !item.display
}"
class="bottom-tool-item" class="bottom-tool-item"
@click="bottomToolClickHandle(item)" @click="bottomToolClickHandle(item)"
> >
<image <image
:src="webUrl + '/aiChat/' + item.icon + '.png'" :src="item.icon"
class="tool-icon" class="tool-icon"
mode="widthFix" mode="widthFix"
/> />
{{ item.text }} {{ item.name }}
</view> </view>
</view> </view>
</view> </view>
@@ -532,6 +605,7 @@
ref="bottomSend" ref="bottomSend"
:loading="loading" :loading="loading"
:keyboard-height="keyboardHeight" :keyboard-height="keyboardHeight"
:voice-exception="exceptionConfig.voice_exception"
@send="streamReq" @send="streamReq"
@add="createNewHandle" @add="createNewHandle"
@history="historyViewHandle" @history="historyViewHandle"
@@ -540,6 +614,7 @@
<AiHistoryList <AiHistoryList
ref="historyView" ref="historyView"
:status-bar-height="statusBarHeight" :status-bar-height="statusBarHeight"
:county-id="countyId"
@enter-history="audioStopHandle" @enter-history="audioStopHandle"
/> />
<ProductWindow <ProductWindow
@@ -565,6 +640,9 @@ import {
getAiSystemInfoSetting, getAiSystemInfoSetting,
getAiSystemInfoTopic getAiSystemInfoTopic
} from '@/api/public' } from '@/api/public'
import {
getCountyAiDetail
} from '@/api/chat/index'
import AiHistoryList from '../components/historyList' import AiHistoryList from '../components/historyList'
import BottomSend from '../components/bottomSend.vue' import BottomSend from '../components/bottomSend.vue'
import OrderItem from '../components/orderItem.vue' import OrderItem from '../components/orderItem.vue'
@@ -581,39 +659,68 @@ export default {
data() { data() {
return { return {
cityName: '', cityName: '',
countyId: '',
animationWidth: '150%', animationWidth: '150%',
animationStr: '', animationStr: '',
settingInfo: {}, settingInfo: {},
topicList: [], topicList: [],
onlyOneToAddCart: false, topicIsRotate: false,
topicIsRotate: false showGiftSteps: false,
currentGiftStepIndex: 0,
giftSelections: {},
giftBudget: '',
giftBuyOptions: [],
countyTools: []
} }
}, },
onLoad(options) { onLoad(options) {
this.cityName = options.cityName || '' this.cityName = options.cityName || ''
this.countyId = options.countyId || ''
}, },
onShow() { onShow() {
const addNewChat = uni.getStorageSync('addNewChat') === '1' // 1-新对话,2-我要送礼
const addNewChat = uni.getStorageSync('addNewChat') || ''
// 从历史界面点击新增对话 // 从历史界面点击新增对话
if (addNewChat && this.chatNumber) { if (addNewChat) {
console.log(addNewChat) if (addNewChat === '1' && (this.chatNumber || this.showGiftSteps)) {
this.createNewHandle()
}
if (addNewChat === '2') {
const giftOptionItem = this.bottomTools.find((i) => i.giftCardEnabled === 1)
if (giftOptionItem) {
this.bottomToolClickHandle(giftOptionItem)
}
}
uni.removeStorageSync('addNewChat') uni.removeStorageSync('addNewChat')
this.createNewHandle()
} }
this.audioStopHandle()
}, },
methods: { methods: {
createdCallbak() { extraReqFn() {
this.$nextTick(() => { this.$nextTick(() => {
this.scrollToBottomHandle() this.scrollToBottomHandle()
getAiSystemInfoSetting().then(res => { if (this.countyId) {
const { success, data } = res getCountyAiDetail({
if (success) { countyId: this.countyId
this.settingInfo = data }).then(res => {
this.animationWidth = `${data.systemTopicDivMaxWidth * 750}rpx` const { success, data } = res
this.animationStr = `TranslateXSwiper-${data.systemTopicDivMaxWidth * 10} ${data.systemTopicDivScrollDuration}s infinite linear alternate` if (success) {
} this.settingInfo.helloMessageTitle = data.title || ''
}) this.settingInfo.helloMessageContent = data.introduction || ''
this.loadData() this.countyTools = data.modules || []
}
})
} else {
getAiSystemInfoSetting().then(res => {
const { success, data } = res
if (success) {
this.settingInfo = data
this.animationWidth = `${data.systemTopicDivMaxWidth * 750}rpx`
this.animationStr = `TranslateXSwiper-${data.systemTopicDivMaxWidth * 10} ${data.systemTopicDivScrollDuration}s infinite linear alternate`
}
})
this.loadData()
}
}) })
}, },
loadData(type = '') { loadData(type = '') {
@@ -643,13 +750,12 @@ export default {
}) })
}, },
// 创建新会话 // 创建新会话
createNewHandle() { createNewHandle(type = '') {
this.closeAttrWindow() this.closeAttrWindow()
if (this.audioContext) { if (this.audioContext) {
this.audioContext.stop() this.audioContext.stop()
} }
wx.getBackgroundAudioManager().stop() wx.getBackgroundAudioManager().stop()
if (!this.chatNumber) return
this.closeWsFn() this.closeWsFn()
this.chatNumber = '' this.chatNumber = ''
this.showCursor = false this.showCursor = false
@@ -657,9 +763,21 @@ export default {
this.getConfigLoading = false this.getConfigLoading = false
this.chatMessageList = [] this.chatMessageList = []
this.loadData() this.loadData()
// 清空所有送礼选项
this.giftSelections = {}
this.giftBudget = ''
this.currentGiftStepIndex = 0
if (type !== 'giftChat') {
const idx = this.bottomTools.findIndex((i) => i.giftCardEnabled === 1)
this.$set(this, 'showGiftSteps', false)
if (idx > -1) {
this.$set(this.bottomTools[idx], 'display', true)
}
}
}, },
/*
clickBackHandle() { clickBackHandle() {
if (!this.chatNumber) { if (!this.chatNumber && !this.showGiftSteps) {
if (getCurrentPages().length > 1) { if (getCurrentPages().length > 1) {
uni.navigateBack() uni.navigateBack()
} else { } else {
@@ -671,8 +789,9 @@ export default {
this.createNewHandle() this.createNewHandle()
} }
}, },
*/
pageContainerBeforeleave() { pageContainerBeforeleave() {
if (!this.chatNumber) { if (!this.chatNumber && !this.showGiftSteps) {
if (getCurrentPages().length > 1) { if (getCurrentPages().length > 1) {
uni.navigateBack() uni.navigateBack()
} else { } else {
@@ -683,6 +802,19 @@ export default {
} else { } else {
this.createNewHandle() this.createNewHandle()
} }
},
countyToolItemClickHandle(item) {
if (item.moduleType === 'prompt') {
this.streamReq({
prompt: item.promptContent,
init: 0
})
}
if (item.moduleType === 'url') {
uni.navigateTo({
url: item.url
})
}
} }
} }
} }
@@ -728,6 +860,7 @@ export default {
height: calc(100vh - 240rpx); height: calc(100vh - 240rpx);
padding: 0 0 240rpx 0; padding: 0 0 240rpx 0;
box-sizing: border-box; box-sizing: border-box;
overflow-y: auto;
} }
.focus-guide-wrap { .focus-guide-wrap {
display: flex; display: flex;
@@ -737,8 +870,13 @@ export default {
.guide-left { .guide-left {
.avatar { .avatar {
display: block; display: block;
width: 230rpx; width: 400rpx;
height: 404rpx; }
.county-avatar {
width: 360rpx;
}
.avatar-bounce {
animation: bounce 2s infinite ease-in-out;
} }
} }
.guide-right { .guide-right {
@@ -822,4 +960,58 @@ export default {
transform: translateX(-50%); transform: translateX(-50%);
} }
} }
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-20rpx);
}
}
.county-home-wrap {
justify-content: flex-start;
.guide-right {
.content {
padding: 30rpx 32rpx 0 32rpx;
color: #666;
text-align: left;
}
}
}
.county-tools-wrap {
width: 100%;
padding: 40rpx 0 0 0;
.list-cont {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 100%;
padding: 0 60rpx;
box-sizing: border-box;
.list-item {
display: flex;
align-items: center;
flex-direction: column;
width: 28%;
padding: 20rpx 0 12rpx 0;
margin: 0 0 24rpx 0;
border-radius: 12rpx;
background-color: #fff;
box-shadow: 0 0 12rpx rgba(0, 0, 0, 0.1);
.icon {
display: block;
width: 60rpx;
height: 60rpx;
margin: 0 8rpx 0 0;
}
.name {
padding: 8rpx 0 0 0;
font-size: 28rpx;
color: #333;
}
}
}
}
</style> </style>
+34
View File
@@ -38,6 +38,10 @@ export function deleteChatListByType(type) {
return request.delete('/v1/chat/type/' + type, {}, { login: true }) return request.delete('/v1/chat/type/' + type, {}, { login: true })
} }
export function deleteCountyChatListByType(type, params) {
return request.delete('/county-ai/chat/type/' + type + params, {}, { login: true })
}
export function getWeatherData(params) { export function getWeatherData(params) {
return request.get('/v1/chat/weatherData', params, { login: true }) return request.get('/v1/chat/weatherData', params, { login: true })
} }
@@ -59,3 +63,33 @@ export function getAnalyzeKeywordsChangeV3(data) {
export function getAnalyzeByImageV3(data) { export function getAnalyzeByImageV3(data) {
return request.post('/v1/chat/image/recognition', data, { login: true }) return request.post('/v1/chat/image/recognition', data, { login: true })
} }
// 获取送礼选项配置
export function getGiftRecommendOptions(params) {
return request.get('/ai/gift-recommend/options', params, { login: true })
}
// 获取县域AI详情
export function getCountyAiDetail(params) {
return request.get('/county-ai/detail', params, { login: true })
}
export function getSseCountyAiConfigV1(data) {
return request.post('/county-ai/chat', data, { login: true })
}
export function getCountyAiCompletionsV1(params) {
return request.get('/county-ai/chat/recognize', params, { login: true })
}
export function getCountyAiChatList(params) {
return request.get('/county-ai/chat/list', params, { login: true })
}
export function getCountyAiHistoryChatMessage(params) {
return request.get('/county-ai/chat/message', params, { login: true })
}
export function getGiftRecommendPrompt(data) {
return request.post('/ai/gift-recommend/build-prompt', data, { login: true })
}
+10
View File
@@ -223,6 +223,16 @@ export function getAiSystemInfoTopic() {
return request.get('/ai/systemTopic', {}, { login: false }) return request.get('/ai/systemTopic', {}, { login: false })
} }
// 获取异常提示配置
export function getExceptionConfig() {
return request.get('/ai/exceptionConfig', {}, { login: true })
}
// 获取已启用的底部导航配置列表
export function getBottomNavigationConfigList() {
return request.get('/ai/bottom-navigation/list', {}, { login: true })
}
// 获取通用分享配置 // 获取通用分享配置
export function getWeixinShareConfig() { export function getWeixinShareConfig() {
return request.get('/weixinShareConfig', {}, { login: false }) return request.get('/weixinShareConfig', {}, { login: false })
+132
View File
@@ -111,6 +111,12 @@ page {
box-sizing: border-box; box-sizing: border-box;
overflow-x: auto; overflow-x: auto;
} }
.container-county {
justify-content: flex-end;
.new-chat {
margin-right: 0;
}
}
.new-chat { .new-chat {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -161,6 +167,9 @@ page {
&:last-child { &:last-child {
margin-right: 0; margin-right: 0;
} }
&.hide {
display: none;
}
.tool-icon { .tool-icon {
display: block; display: block;
width: 32rpx; width: 32rpx;
@@ -1365,3 +1374,126 @@ page {
transform: rotate(720deg); transform: rotate(720deg);
} }
} }
.gift-steps-wrap {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 0 80rpx;
box-sizing: border-box;
.gift-step-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 60rpx;
text-align: center;
}
.gift-options {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
.gift-option-item {
width: 48%;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #f2f4ff;
color: #333;
border-radius: 12rpx;
margin-bottom: 20rpx;
font-size: 28rpx;
position: relative;
transition: all 0.2s;
&.active {
background-color: #3D4CF0;
color: #fff;
}
.icon-check {
margin-left: 8rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.gift-price-input {
width: 100%;
margin-bottom: 40rpx;
.input-wrap {
display: flex;
align-items: center;
padding: 0 24rpx;
height: 88rpx;
background-color: #f2f4ff;
border-radius: 12rpx;
.label {
font-size: 28rpx;
color: #333;
white-space: nowrap;
}
.input-budget {
flex: 1;
font-size: 28rpx;
color: #333;
padding-left: 10rpx;
}
}
}
.gift-step-actions {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
.action-btn-group {
display: flex;
justify-content: space-between;
width: 100%;
margin-bottom: 20rpx;
.btn {
height: 62rpx;
line-height: 62rpx;
text-align: center;
border-radius: 12rpx;
font-size: 30rpx;
&-prev {
width: 48%;
background-color: #fff;
color: #3D4CF0;
border: 2rpx solid #3D4CF0;
box-sizing: border-box;
}
&-next {
width: 48%;
background-color: #3D4CF0;
color: #fff;
&.full-width {
width: 100%;
}
}
}
}
.btn-skip {
font-size: 28rpx;
color: #3D4CF0;
padding: 10rpx 20rpx;
}
}
}
+21 -1
View File
@@ -13,12 +13,19 @@
import { import {
getAiSystemInfoSetting getAiSystemInfoSetting
} from '@/api/public' } from '@/api/public'
import {
getCountyAiDetail
} from '@/api/chat/index'
export default { export default {
name: 'AiEntrance', name: 'AiEntrance',
props: { props: {
cityName: { cityName: {
type: String, type: String,
default: '' default: ''
},
countyId: {
type: String,
default: ''
} }
}, },
data() { data() {
@@ -33,6 +40,19 @@ export default {
}, },
methods: { methods: {
init() { init() {
if (this.countyId) {
getCountyAiDetail({
countyId: this.countyId
}).then(res => {
const { success, data } = res
if (success) {
const aiImage = data.aiImage || ''
this.settingInfo.mainImage = aiImage
this.showImg = !!aiImage
}
})
return
}
getAiSystemInfoSetting().then(res => { getAiSystemInfoSetting().then(res => {
const { success, data } = res const { success, data } = res
if (success) { if (success) {
@@ -43,7 +63,7 @@ export default {
}, },
enterAiChat() { enterAiChat() {
uni.navigateTo({ uni.navigateTo({
url: '/aiChat/views/index?click=1&cityName=' + (this.cityName || this.localCityName) url: '/aiChat/views/index?click=1&cityName=' + (this.cityName || this.localCityName) + '&countyId=' + (this.countyId || '')
}) })
} }
} }
+1 -1
View File
@@ -161,7 +161,7 @@
{ {
"path": "pages/VideoPlayBackList/VideoPlayBackList", "path": "pages/VideoPlayBackList/VideoPlayBackList",
"style": { "style": {
"navigationBarTitleText": "寻看点", "navigationBarTitleText": "使用指南",
"navigationBarBackgroundColor": "#FFFFFF" "navigationBarBackgroundColor": "#FFFFFF"
} }
}, },
+1 -1
View File
@@ -64,7 +64,7 @@
<!-- 导航v9 --> <!-- 导航v9 -->
<view class="menus-wrap"> <view class="menus-wrap">
<view class="menus-bg" /> <view class="menus-bg" />
<scroll-view scroll-x :scroll-into-view="scrollView" class="scroll-view" scroll-with-animation @scroll="onscroll" > <scroll-view scroll-x :scroll-into-view="scrollView" class="scroll-view" scroll-with-animation>
<view class="menus-list"> <view class="menus-list">
<view <view
v-for="(item, index) in menus" v-for="(item, index) in menus"
+4 -1
View File
@@ -904,7 +904,10 @@
@ok="handleOk" @ok="handleOk"
/> />
<FunctionGuide @hide="setGuide('countyFamousIndex')" :maxStep="2" :guideData="functionGuideData" ref="FunctionGuide"></FunctionGuide> <FunctionGuide @hide="setGuide('countyFamousIndex')" :maxStep="2" :guideData="functionGuideData" ref="FunctionGuide"></FunctionGuide>
<AiEntrance /> <AiEntrance
v-if="isLoad"
:county-id="inn.areaId"
/>
</view> </view>
</template> </template>
+3 -3
View File
@@ -80,7 +80,7 @@ function baseRequest(options) {
_params = { _params = {
params: params params: params
} }
} else if (['post', 'POST'].includes(options.method)) { } else if (['post', 'POST', 'put', 'PUT', 'patch', 'PATCH', 'delete', 'DELETE'].includes(options.method)) {
_params = params || data _params = params || data
} }
@@ -153,7 +153,7 @@ function baseRequest(options) {
* 参考文档 https://www.kancloud.cn/yunye/axios/234845 * 参考文档 https://www.kancloud.cn/yunye/axios/234845
* *
*/ */
const request = ["post", "put", "patch"].reduce((request, method) => { const request = ["post", "put", "patch", "delete"].reduce((request, method) => {
/** /**
* *
* @param url string 接口地址 * @param url string 接口地址
@@ -169,7 +169,7 @@ const request = ["post", "put", "patch"].reduce((request, method) => {
return request; return request;
}, {}); }, {});
["get", "delete", "head"].forEach(method => { ["get", "head"].forEach(method => {
/** /**
* *
* @param url string 接口地址 * @param url string 接口地址