refactor(ai-chat): 重构AI聊天国际化文件结构

- 将 ai-chat 语言文件从 ai/ 迁移至 ai-chat/ 目录
- 重构消息组件及多个子组件
This commit is contained in:
2026-05-18 15:36:13 +08:00
parent 5c56cfaaa7
commit 556ce9d132
12 changed files with 312 additions and 96 deletions

View File

@@ -4,6 +4,7 @@
<ai-chat-search
ref="searchRef"
:messages="messages"
:show-label="false"
@scroll-to="onSearchScrollTo"
@active-change="onSearchActiveChange"
@result-change="onSearchResultChange"
@@ -73,7 +74,7 @@
<view class="message-content">
<!-- AI昵称固定,不可修改 - 左移到气泡上方 -->
<view class="message-nickname ai-nickname">
<text class="ai-nickname-text">智能助手</text>
<text class="ai-nickname-text">{{ $lang('aiNickname') }}</text>
<text class="message-time">{{ formatTime(message.timestamp) }}</text>
</view>
<view class="message-bubble"
@@ -118,7 +119,7 @@
<view v-else-if="message.type === 'audio'" class="audio-content">
<view class="audio-player">
<view class="audio-info">
<text class="audio-title">{{ message.title || '语音消息' }}</text>
<text class="audio-title">{{ message.title || $lang('audioMessage') }}</text>
<text class="audio-duration">{{ formatDuration(message.duration) }}</text>
</view>
<view class="audio-controls">
@@ -156,7 +157,7 @@
@pause="onVideoPause(message)">
</video>
<view class="video-info">
<text class="video-title">{{ message.title || '视频消息' }}</text>
<text class="video-title">{{ message.title || $lang('videoMessage') }}</text>
<text class="video-duration">{{ formatDuration(message.duration) }}</text>
</view>
</view>
@@ -186,7 +187,7 @@
<text class="dot"></text>
</view>
<text class="loading-text">
<text class="loading-status">{{ message.loadingText || 'AI正在思考' }}</text>
<text class="loading-status">{{ message.loadingText || $lang('aiThinking') }}</text>
<text class="loading-ellipsis">
<text class="ellipsis-dot">.</text>
<text class="ellipsis-dot">.</text>
@@ -231,7 +232,7 @@
<textarea
v-model="inputText"
class="message-input"
placeholder="请输入您的问题..."
:placeholder="$lang('inputPlaceholder')"
:maxlength="500"
:auto-height="true"
:show-confirm-bar="false"
@@ -257,7 +258,7 @@
:class="{ disabled: !canSendMessage }"
@click="sendMessage"
:disabled="!canSendMessage">
<text>发送</text>
<text>{{ $lang('send') }}</text>
</button>
</view>
</view>
@@ -282,7 +283,7 @@
<view class="expand-editor-mask" @click="closeExpandEditor"></view>
<view class="expand-editor-panel">
<view class="expand-editor-header">
<text>编辑内容</text>
<text>{{ $lang('expandEditorTitle') }}</text>
<button class="close-btn" @click="closeExpandEditor">
<text>×</text>
</button>
@@ -290,15 +291,15 @@
<textarea
v-model="expandInputText"
class="expand-editor-input"
placeholder="请输入您的问题..."
:placeholder="$lang('inputPlaceholder')"
:maxlength="500"
:auto-height="true"
:show-confirm-bar="false"
:adjust-position="true"
:focus="true" />
<view class="expand-editor-footer">
<button class="expand-cancel-btn" @click="closeExpandEditor">取消</button>
<button class="expand-send-btn" @click="sendFromExpandEditor" :disabled="!expandInputText.trim()">发送</button>
<button class="expand-cancel-btn" @click="closeExpandEditor">{{ $lang('cancel') }}</button>
<button class="expand-send-btn" @click="sendFromExpandEditor" :disabled="!expandInputText.trim()">{{ $lang('send') }}</button>
</view>
</view>
</view>
@@ -396,7 +397,7 @@ export default {
scrollTop: 0,
scrollIntoViewId: null,
hasMoreHistory: false,
loadingText: '加载更多历史消息',
loadingText: this.$lang('loadMoreHistory'),
voiceInputing: false,
audioContext: null,
currentAudio: null,
@@ -416,7 +417,7 @@ export default {
localUserAvatar: '',
showAvatarSelector: false, // 头像选择弹窗控制
localUserNickname: '', // 当前用户昵称
defaultNickname: '我', // 默认昵称
defaultNickname: this.$lang('defaultNickname'), // 默认昵称
showNicknameEditor: false, // 昵称编辑弹窗控制
// AI头像错误状态
avatarError: false,
@@ -823,12 +824,12 @@ async loadChatHistoryIfExist() {
type: 'loading',
content: '',
timestamp: Date.now(),
loadingText: 'AI正在思考',
loadingText: this.$lang('aiThinking'),
_loadingIndex: 0
}
this.shouldScrollToBottom = true
this.messages.push(loadingMessage)
// 启动处理状态文字轮换
this._startLoadingTextRotation(loadingMessage)
@@ -856,10 +857,10 @@ async loadChatHistoryIfExist() {
id: ++this.messageId,
role: 'ai',
type: 'text',
content: '抱歉,AI服务暂时不可用,请稍后重试。',
content: this.$lang('serviceUnavailable'),
timestamp: Date.now(),
actions: [
{ id: 1, text: '重试', type: 'retry' }
{ id: 1, text: this.$lang('retry'), type: 'retry' }
]
}
this.shouldScrollToBottom = true
@@ -940,7 +941,7 @@ async sendStreamMessage(userMessage) {
this.isStreaming = true
const loadingMsg = this.messages[loadingIdx]
this._stopLoadingTextRotation(loadingMsg)
loadingMsg.loadingText = '正在接收回复'
loadingMsg.loadingText = this.$lang('receivingReply')
let transformed = false
@@ -1006,15 +1007,16 @@ async sendStreamMessage(userMessage) {
id: ++this.messageId,
role: 'ai',
type: 'text',
content: '抱歉,服务暂时不可用,请稍后重试。',
content: this.$lang('serviceTemporaryUnavailable'),
timestamp: Date.now(),
actions: [{ id: 1, text: '重试', type: 'retry' }]
actions: [{ id: 1, text: this.$lang('retry'), type: 'retry' }]
}
this.messages.push(errorMsg)
this.$emit('ai-response', errorMsg)
}
},
// 完成流式消息处理(共用逻辑)
_finishStream(msg, result) {
msg.isStreaming = false
@@ -1051,9 +1053,9 @@ _handleStreamError(msg) {
id: ++this.messageId,
role: 'ai',
type: 'text',
content: '抱歉,服务暂时不可用,请稍后重试。',
content: this.$lang('serviceTemporaryUnavailable'),
timestamp: Date.now(),
actions: [{ id: 1, text: '重试', type: 'retry' }]
actions: [{ id: 1, text: this.$lang('retry'), type: 'retry' }]
}
this.messages.push(errorMsg)
this.$emit('ai-response', errorMsg)
@@ -1339,9 +1341,9 @@ _handleStreamError(msg) {
// 格式化文件大小
formatFileSize(bytes) {
if (!bytes) return '0B'
if (!bytes) return this.$lang('about')
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const sizes = [this.$lang('about'), 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + sizes[i]
},
@@ -1429,7 +1431,7 @@ _handleStreamError(msg) {
}
} catch (error) {
console.error('加载历史失败:', error);
uni.showToast({ title: '加载历史失败', icon: 'none' });
uni.showToast({ title: this.$lang('loadHistoryFail'), icon: 'none' });
this.hasMoreHistory = false;
} finally {
this.isLoadingHistory = false;
@@ -1444,7 +1446,7 @@ _handleStreamError(msg) {
// 预览文件
previewFile(message) {
uni.showLoading({ title: '打开文件中...' })
uni.showLoading({ title: this.$lang('openingFile') })
// #ifdef H5
window.open(message.url, '_blank')
@@ -1454,7 +1456,7 @@ _handleStreamError(msg) {
plus.runtime.openFile(message.url, {
error: (e) => {
uni.showToast({
title: '文件打开失败',
title: this.$lang('fileOpenFail'),
icon: 'none'
})
}
@@ -1628,7 +1630,7 @@ _handleStreamError(msg) {
copyText = message.content || ''
}
if (!copyText) {
uni.showToast({ title: '无可复制的内容', icon: 'none' })
uni.showToast({ title: this.$lang('noContentToCopy'), icon: 'none' })
return
}
@@ -1661,12 +1663,12 @@ _handleStreamError(msg) {
data: copyText,
success: () => {
console.log('[AI Chat] 复制成功')
uni.showToast({ title: '已复制', icon: 'success' })
uni.showToast({ title: this.$lang('copySuccess'), icon: 'success' })
},
fail: (err) => {
console.error('[AI Chat] 复制失败, 详细错误:', JSON.stringify(err))
console.error('[AI Chat] 复制失败 errMsg:', err.errMsg || err.message || '无错误消息')
uni.showToast({ title: '复制失败: ' + (err.errMsg || '未知错误'), icon: 'none', duration: 3000 })
uni.showToast({ title: this.$lang('copyFail') + ': ' + (err.errMsg || this.$lang('serviceUnavailable')), icon: 'none', duration: 3000 })
}
})
// #endif
@@ -1687,12 +1689,12 @@ _handleStreamError(msg) {
const success = document.execCommand('copy')
document.body.removeChild(textarea)
if (success) {
uni.showToast({ title: '已复制', icon: 'success' })
uni.showToast({ title: this.$lang('copySuccess'), icon: 'success' })
} else {
uni.showToast({ title: '复制失败', icon: 'none' })
uni.showToast({ title: this.$lang('copyFail'), icon: 'none' })
}
} catch (e) {
uni.showToast({ title: '复制失败', icon: 'none' })
uni.showToast({ title: this.$lang('copyFail'), icon: 'none' })
}
},
@@ -1795,10 +1797,10 @@ _handleStreamError(msg) {
type: 'loading',
content: '',
timestamp: Date.now(),
loadingText: 'AI正在思考',
loadingText: this.$lang('aiThinking'),
_loadingIndex: 0
}
this.messages.push(loadingMessage)
this._startLoadingTextRotation(loadingMessage)
@@ -1826,10 +1828,10 @@ _handleStreamError(msg) {
id: ++this.messageId,
role: 'ai',
type: 'text',
content: '抱歉,AI服务暂时不可用,请稍后重试。',
content: this.$lang('serviceUnavailable'),
timestamp: Date.now(),
actions: [
{ id: 1, text: '重试', type: 'retry' }
{ id: 1, text: this.$lang('retry'), type: 'retry' }
]
}

View File

@@ -3,7 +3,7 @@
<view class="avatar-selector-mask" @click="close"></view>
<view class="avatar-selector-panel">
<view class="avatar-selector-header">
<text>更换头像</text>
<text>{{ $lang('avatarSelectorTitle') }}</text>
<button class="close-btn" @click="close">
<text class="iconfont icon-close"></text>
</button>
@@ -15,10 +15,10 @@
<view class="avatar-selector-actions">
<button class="avatar-select-action" @click="chooseAvatarFromAlbum">
<text class="iconfont icon-album"></text>
<text>从相册选择</text>
<text>{{ $lang('chooseFromAlbum') }}</text>
</button>
<button class="avatar-select-action cancel" @click="close">
<text>取消</text>
<text>{{ $lang('cancel') }}</text>
</button>
</view>
</view>
@@ -80,7 +80,7 @@ export default {
reader.readAsDataURL(file)
this.$emit('avatar-change', tempFilePath)
this.close()
uni.showToast({ title: '头像更换成功', icon: 'success', duration: 1500 })
uni.showToast({ title: this.$lang('avatarChangeSuccess'), icon: 'success', duration: 1500 })
} else {
this.close()
}
@@ -99,11 +99,11 @@ export default {
uni.setStorageSync('user_avatar', tempFilePath)
this.$emit('avatar-change', tempFilePath)
this.close()
uni.showToast({ title: '头像更换成功', icon: 'success', duration: 1500 })
uni.showToast({ title: this.$lang('avatarChangeSuccess'), icon: 'success', duration: 1500 })
},
fail: (error) => {
if (error.errMsg && error.errMsg.includes('deny')) {
uni.showToast({ title: '请开启相册权限', icon: 'none', duration: 2000 })
uni.showToast({ title: this.$lang('enableAlbumPermission'), icon: 'none', duration: 2000 })
}
this.close()
}

View File

@@ -3,7 +3,7 @@
<view class="emoji-mask" @click="hideEmojiPanel"></view>
<view class="emoji-panel">
<view class="emoji-header">
<text>表情</text>
<text>{{ $lang('emojiTitle') }}</text>
<button class="close-btn" @click="hideEmojiPanel">
<text>×</text>
</button>

View File

@@ -3,7 +3,7 @@
<view class="nickname-editor-mask" @click="close"></view>
<view class="nickname-editor-panel">
<view class="nickname-editor-header">
<text>修改昵称</text>
<text>{{ $lang('editNickname') }}</text>
<button class="close-btn" @click="close">
<text class="iconfont icon-close"></text>
</button>
@@ -13,21 +13,21 @@
<input
v-model="tempNickname"
class="nickname-input"
placeholder="请输入您的新昵称"
:placeholder="$lang('newNicknamePlaceholder')"
:maxlength="12"
type="text" />
</view>
<view class="nickname-tip">昵称长度限制1-12个字符,仅自己可见</view>
<view class="nickname-tip">{{ $lang('nicknameTip') }}</view>
<view class="nickname-editor-actions">
<button class="nickname-action-btn cancel" @click="close">
<text>取消</text>
<text>{{ $lang('cancel') }}</text>
</button>
<button
class="nickname-action-btn confirm"
:class="{ disabled: !tempNickname.trim() }"
:disabled="!tempNickname.trim()"
@click="saveNickname">
<text>保存</text>
<text>{{ $lang('save') }}</text>
</button>
</view>
</view>
@@ -87,7 +87,7 @@ export default {
uni.setStorageSync('user_nickname', newNickname)
this.$emit('nickname-change', newNickname)
this.close()
uni.showToast({ title: '昵称修改成功', icon: 'success', duration: 1500 })
uni.showToast({ title: this.$lang('nicknameChangeSuccess'), icon: 'success', duration: 1500 })
}
}
}

View File

@@ -1,9 +1,9 @@
<template>
<view class="ai-chat-search">
<!-- 搜索入口按钮(浮动在消息区右上角) -->
<view class="search-entrance" v-if="!showSearchBar" @click="toggleSearch">
<view class="search-entrance" :class="{ 'icon-only': !showLabel }" v-if="!showSearchBar" @click="toggleSearch">
<text class="iconfont icon-sousuo search-entrance-icon"></text>
<text class="search-entrance-label">搜索</text>
<text class="search-entrance-label" v-if="showLabel">{{ $lang('searchEntrance') }}</text>
</view>
<!-- 搜索浮条 -->
@@ -14,7 +14,7 @@
<input
class="search-bar-input"
v-model="searchKeyword"
placeholder="搜索聊天记录"
:placeholder="$lang('searchPlaceholder')"
:focus="true"
@input="onSearchInput"
@confirm="doSearch" />
@@ -27,7 +27,7 @@
<text class="search-bar-nav" :class="{ disabled: searchResultIndex >= searchResults.length - 1 }" @click="scrollToNextResult">▼</text>
</view>
</view>
<text class="search-bar-close" @click="closeSearch">完成</text>
<text class="search-bar-close" @click="closeSearch">{{ $lang('searchClose') }}</text>
</view>
</view>
</view>
@@ -39,6 +39,7 @@
*
* Props:
* messages: Array - 原始消息列表
* showLabel: Boolean - (默认 true) 是否显示"搜索"文字;设为 false 则只显示搜索图标
*
* Events:
* scroll-to: (messageKey: string) => void - 请求父组件滚动到指定消息
@@ -53,6 +54,11 @@ export default {
messages: {
type: Array,
default: () => []
},
// 是否显示文字标签;设为 false 则只显示搜索图标
showLabel: {
type: Boolean,
default: true
}
},
@@ -66,6 +72,7 @@ export default {
},
computed: {
// 过滤后的消息列表(与 v-for 保持一致)
filteredMessages() {
return this.messages.filter(
@@ -150,7 +157,7 @@ export default {
this._emitScrollTo(filteredIdx)
})
} else {
uni.showToast({ title: '未找到匹配结果', icon: 'none' })
uni.showToast({ title: this.$lang('noMatchResult'), icon: 'none' })
}
},
@@ -174,7 +181,7 @@ export default {
if (idx >= 0) {
this.scrollToSearchResult(idx)
} else {
uni.showToast({ title: '已到顶部', icon: 'none' })
uni.showToast({ title: this.$lang('searchAtTop'), icon: 'none' })
}
},
@@ -183,7 +190,7 @@ export default {
if (idx < this.searchResults.length) {
this.scrollToSearchResult(idx)
} else {
uni.showToast({ title: '已到底部', icon: 'none' })
uni.showToast({ title: this.$lang('searchAtBottom'), icon: 'none' })
}
},
@@ -251,7 +258,7 @@ export default {
// 搜索入口按钮
.search-entrance {
position: absolute;
top: 88rpx;
top: 44rpx;
right: 16rpx;
z-index: 10;
display: flex;
@@ -277,6 +284,15 @@ export default {
&:active {
background: rgba(255, 255, 255, 0.8);
}
// 仅显示图标模式(圆形小按钮)
&.icon-only {
width: 56rpx;
height: 56rpx;
padding: 0;
justify-content: center;
border-radius: 50%;
}
}
// 搜索浮条

View File

@@ -3,7 +3,7 @@
<view class="tools-mask" @click="hideToolsPanel"></view>
<view class="tools-panel">
<view class="tools-header">
<text>更多功能</text>
<text>{{ $lang('moreFunctions') }}</text>
<button class="close-btn" @click="hideToolsPanel">
<text class="iconfont icon-close"></text>
</button>
@@ -13,25 +13,25 @@
<view class="tool-icon">
<text class="iconfont icon-image"></text>
</view>
<text class="tool-text">图片</text>
<text class="tool-text">{{ $lang('image') }}</text>
</view>
<view class="tool-item" @click="selectFile">
<view class="tool-icon">
<text class="iconfont icon-file"></text>
</view>
<text class="tool-text">文件</text>
<text class="tool-text">{{ $lang('file') }}</text>
</view>
<view class="tool-item" @click="startRecord">
<view class="tool-icon">
<text class="iconfont icon-voice"></text>
</view>
<text class="tool-text">语音</text>
<text class="tool-text">{{ $lang('voice') }}</text>
</view>
<view class="tool-item" @click="selectLocation">
<view class="tool-icon">
<text class="iconfont icon-location"></text>
</view>
<text class="tool-text">位置</text>
<text class="tool-text">{{ $lang('location') }}</text>
</view>
</view>
</view>

View File

@@ -3,7 +3,7 @@
<view class="voice-mask" @click="hideVoicePanel"></view>
<view class="voice-input-panel">
<view class="voice-header">
<text>语音输入</text>
<text>{{ $lang('voiceInputTitle') }}</text>
<button class="close-btn" @click="hideVoicePanel">
<text class="iconfont icon-close"></text>
</button>
@@ -16,7 +16,7 @@
class="wave-bar"
:style="{ animationDelay: (i * 0.1) + 's' }"></view>
</view>
<text class="voice-tip">{{ voiceInputing ? '正在录音,松开结束' : '点击开始录音' }}</text>
<text class="voice-tip">{{ voiceInputing ? $lang('recordingTip') : $lang('startRecordTip') }}</text>
</view>
<view class="voice-actions">
<button class="voice-btn" @click="toggleVoiceInput">
@@ -86,7 +86,7 @@ export default {
// 录音中,可扩展实时转文字
})
.catch(error => {
uni.showToast({ title: '语音输入失败', icon: 'none' })
uni.showToast({ title: this.$lang('voiceInputFailed'), icon: 'none' })
this.voiceInputing = false
})
}

View File

@@ -39,7 +39,7 @@
<view class="settings-mask" @click="hideSettings"></view>
<view class="settings-panel">
<view class="settings-header">
<text class="settings-title">设置</text>
<text class="settings-title">{{ $lang('settingsTitle') }}</text>
<view class="close-btn" @click="hideSettings">
<text>✕</text>
</view>
@@ -50,8 +50,8 @@
<text class="iconfont icon-user">📷</text>
</view>
<view class="setting-info">
<text class="setting-label">更换头像</text>
<text class="setting-desc">自定义您的聊天头像</text>
<text class="setting-label">{{ $lang('changeAvatar') }}</text>
<text class="setting-desc">{{ $lang('changeAvatarDesc') }}</text>
</view>
<text class="iconfont icon-right">›</text>
</view>
@@ -60,8 +60,8 @@
<text class="iconfont icon-edit">✏️</text>
</view>
<view class="setting-info">
<text class="setting-label">更换昵称</text>
<text class="setting-desc">自定义您的昵称</text>
<text class="setting-label">{{ $lang('changeNickname') }}</text>
<text class="setting-desc">{{ $lang('changeNicknameDesc') }}</text>
</view>
<text class="iconfont icon-right">›</text>
</view>
@@ -86,7 +86,7 @@ export default {
data() {
return {
initialMessages: [],
fallbackWelcome: '您好!我是AI智能客服,很高兴为您服务!\n\n我可以帮您:\n• 解答产品相关问题\n• 处理订单问题\n• 提供技术支持\n• 推荐相关商品\n\n请告诉我您需要什么帮助?',
fallbackWelcome: this.$lang('fallbackWelcome'),
// --- 系统导航栏/状态栏相关 ---
navBarHeight: 44, // uni-page-head 系统导航栏,默认高度为44px
@@ -132,7 +132,7 @@ export default {
// return;
// }
this. $langConfig.title('AI智能客服');
this.$langConfig.title(this.$lang('title'));
this.initChat();
},
@@ -144,12 +144,13 @@ export default {
console.log('[AI Chat Page] onShow 触发');
// 监听键盘高度变化(H5 可能不支持,try-catch 保护)
try {
uni.onKeyboardHeightChange((res) => {
this._keyboardChangeHandler = (res) => {
this.keyboardHeight = res.height;
if (this.$refs.chat && this.$refs.chat.updateKeyboardHeight) {
this.$refs.chat.updateKeyboardHeight(res.height);
}
});
};
uni.onKeyboardHeightChange(this._keyboardChangeHandler);
} catch (e) {
console.warn('onKeyboardHeightChange 不可用:', e.message);
}
@@ -163,7 +164,10 @@ export default {
onHide() {
// 取消监听键盘高度变化
uni.offKeyboardHeightChange();
if (this._keyboardChangeHandler) {
uni.offKeyboardHeightChange(this._keyboardChangeHandler);
this._keyboardChangeHandler = null;
}
this.keyboardHeight = 0;
if (this.$refs.chat && this.$refs.chat.updateKeyboardHeight) {
this.$refs.chat.updateKeyboardHeight(0);
@@ -233,7 +237,7 @@ export default {
component: this. $options.name
});
this.showError('操作失败,请重试');
this.showError(this.$lang('operationFailed'));
},
// ========== 初始化页面 ==========
@@ -287,6 +291,10 @@ export default {
},
cleanup() {
if (this._keyboardChangeHandler) {
uni.offKeyboardHeightChange(this._keyboardChangeHandler);
this._keyboardChangeHandler = null;
}
this.safeEventHandlers.forEach((handler, eventType) => {
this. $off(eventType, handler);
});
@@ -309,7 +317,7 @@ export default {
// 显示菜单
showMenu() {
uni.showActionSheet({
itemList: ['清空聊天', '导出记录', '设置', '帮助'],
itemList: [this.$lang('menuClearChat'), this.$lang('menuExport'), this.$lang('menuSettings'), this.$lang('menuHelp')],
success: (res) => {
switch (res.tapIndex) {
case 0:
@@ -331,8 +339,8 @@ export default {
clearChat() {
uni.showModal({
title: '提示',
content: '确定要清空聊天记录吗?',
title: this.$lang('prompt'),
content: this.$lang('confirmClearChat'),
success: (res) => {
if (res.confirm) {
this. $refs.chat.clearMessages();
@@ -340,7 +348,7 @@ export default {
id: Date.now(),
role: 'ai',
type: 'text',
content: '聊天记录已清空,有什么可以帮助您的吗?',
content: this.$lang('chatCleared'),
timestamp: Date.now()
});
}
@@ -350,7 +358,7 @@ export default {
exportChat() {
uni.showToast({
title: '功能开发中',
title: this.$lang('featureDeveloping'),
icon: 'none'
});
},
@@ -439,10 +447,10 @@ export default {
onActionClick({ action, message }) {
switch (action.type) {
case 'like':
uni.showToast({ title: '感谢您的反馈!', icon: 'success' });
uni.showToast({ title: this.$lang('thanksFeedback'), icon: 'success' });
break;
case 'dislike':
uni.showToast({ title: '我们会改进服务', icon: 'none' });
uni.showToast({ title: this.$lang('improveService'), icon: 'none' });
break;
}
},
@@ -451,7 +459,7 @@ export default {
},
onFilePreview(message) {
uni.showToast({ title: '打开文件: ' + message.fileName, icon: 'none' });
uni.showToast({ title: this.$lang('openingFile') + ' ' + message.fileName, icon: 'none' });
},
onAudioPlay(message) {
@@ -480,8 +488,8 @@ export default {
onLinkOpen(message) {
uni.showModal({
title: '打开链接',
content: `确定要打开链接: $ {message.url} 吗?`,
title: this.$lang('openLink'),
content: this.$lang('confirmOpenLink') + message.url + '?',
success: (res) => {
if (res.confirm) {
// #ifdef H5
@@ -496,7 +504,7 @@ export default {
},
onProductView(message) {
uni.showToast({ title: '查看商品: ' + message.title, icon: 'none' });
uni.showToast({ title: this.$lang('openingFile') + ': ' + message.title, icon: 'none' });
},
onInputChange(value) {
@@ -524,7 +532,7 @@ export default {
// #endif
if (currentType !== 'aikefu') {
uni.showToast({ title: '当前客服类型不支持此页面', icon: 'none' });
uni.showToast({ title: this.$lang('serviceTypeNotSupported'), icon: 'none' });
setTimeout(() => {
const pages = getCurrentPages();
if (pages.length > 1) {