Compare commits
29 Commits
8611ec4dc3
...
merge/tmp-
| Author | SHA1 | Date | |
|---|---|---|---|
| 50908a274b | |||
| 9e68562de5 | |||
| 8e5561c2a7 | |||
| 8d5c543a4f | |||
| cf411407dd | |||
| 86e4be302b | |||
| 2fd06796e1 | |||
| 60c51e551a | |||
| d0d3ac47c6 | |||
| af677f6565 | |||
| f889efeb16 | |||
| d026bb6180 | |||
| 82b856f5d9 | |||
| 7f33b6948a | |||
| 3489b89a0b | |||
| dc4f2769f9 | |||
| 5cf87e4d56 | |||
| c9ca63cff5 | |||
| a6072f4895 | |||
| 38947ddc62 | |||
| cfe83ada38 | |||
| 1e9e0ffea8 | |||
| 28acdfb621 | |||
| ad9f1c495b | |||
| 7c2a7468e7 | |||
| b2051dcf92 | |||
| e3c86de84a | |||
| 6e0eb5d4f3 | |||
| 9d186ff094 |
@@ -41,13 +41,17 @@ const localDevConfig = ({
|
|||||||
'local-2': { // 测试平台
|
'local-2': { // 测试平台
|
||||||
uniacid: 2,
|
uniacid: 2,
|
||||||
domain: 'http://localhost:8050/',
|
domain: 'http://localhost:8050/',
|
||||||
},
|
},
|
||||||
'2847': { // 家居装饰品
|
'100': {
|
||||||
uniacid: 2847,
|
uniacid: 100,
|
||||||
domain: 'https://xcx6.aigc-quickapp.com/',
|
domain: 'https://5g.aigc-quickapp.com/',
|
||||||
},
|
},
|
||||||
'1': { // 开发平台
|
'1': {
|
||||||
uniacid: 1,
|
uniacid: 1,
|
||||||
|
domain: 'https://5g.aigc-quickapp.com/',
|
||||||
|
},
|
||||||
|
'115': {
|
||||||
|
uniacid: 115,
|
||||||
domain: 'https://5g.aigc-quickapp.com/',
|
domain: 'https://5g.aigc-quickapp.com/',
|
||||||
},
|
},
|
||||||
})['1']; // 选择要使用的环境配置
|
})['1']; // 选择要使用的环境配置
|
||||||
|
|||||||
@@ -5,6 +5,17 @@ import store from '@/store/index.js'
|
|||||||
let currentConversationId = null;
|
let currentConversationId = null;
|
||||||
const CONVERSATION_KEY = 'ai_conversation_id';
|
const CONVERSATION_KEY = 'ai_conversation_id';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取域名配置参数(避免重复代码)
|
||||||
|
*/
|
||||||
|
function getDomainParams() {
|
||||||
|
return {
|
||||||
|
imgDomain: Config.imgDomain,
|
||||||
|
h5Domain: Config.h5Domain,
|
||||||
|
baseUrl: Config.baseUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化时从本地读取会话ID
|
// 初始化时从本地读取会话ID
|
||||||
try {
|
try {
|
||||||
const saved = uni.getStorageSync(CONVERSATION_KEY);
|
const saved = uni.getStorageSync(CONVERSATION_KEY);
|
||||||
@@ -16,12 +27,28 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
/**
|
||||||
|
* 获取uniacid
|
||||||
|
* @returns {number} uniacid
|
||||||
|
*/
|
||||||
|
getUniacid() {
|
||||||
|
return uni.getStorageSync('uniacid') || Config.uniacid; // 从缓存中获取uniacid,或使用默认uniacid
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送普通消息(blocking 模式)
|
* 发送普通消息(blocking 模式)
|
||||||
*/
|
*/
|
||||||
async sendMessage(message, options = {}) {
|
async sendMessage(message, options = {}) {
|
||||||
try {
|
try {
|
||||||
|
// 调试:打印关键状态
|
||||||
|
console.log('[AI Service] sendMessage 开始执行');
|
||||||
|
console.log('[AI Service] store.state.memberInfo:', store.state.memberInfo);
|
||||||
|
console.log('[AI Service] uniacid:', this.getUniacid());
|
||||||
|
console.log('[AI Service] currentConversationId:', this.getConversationId());
|
||||||
|
|
||||||
const aiConfig = store.getters.globalAIKefuConfig;
|
const aiConfig = store.getters.globalAIKefuConfig;
|
||||||
|
console.log('[AI Service] aiConfig:', aiConfig);
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
url: '/api/kefu/chat',
|
url: '/api/kefu/chat',
|
||||||
data: {
|
data: {
|
||||||
@@ -31,28 +58,38 @@ export default {
|
|||||||
query: message,
|
query: message,
|
||||||
response_mode: 'blocking', // 强制 blocking
|
response_mode: 'blocking', // 强制 blocking
|
||||||
user: store.state.memberInfo?.id || 'anonymous',
|
user: store.state.memberInfo?.id || 'anonymous',
|
||||||
conversation_id: this.getConversationId() || ''
|
conversation_id: this.getConversationId() || '',
|
||||||
|
...getDomainParams()
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Sending blocking request to:', params.url);
|
console.log('[AI Service] 发送请求到:', params.url);
|
||||||
console.log('Request data:', params.data);
|
console.log('[AI Service] 请求参数:', JSON.stringify(params.data, null, 2));
|
||||||
|
|
||||||
const response = await http.sendRequest({
|
const response = await http.sendRequest({
|
||||||
...params,
|
...params,
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('[AI Service] 收到响应:', response);
|
||||||
|
|
||||||
const result = this.handleResponse(response);
|
const result = this.handleResponse(response);
|
||||||
if (result.conversationId) {
|
if (result.conversationId) {
|
||||||
this.setConversationId(result.conversationId);
|
this.setConversationId(result.conversationId);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Dify API请求失败:', error);
|
console.error('[AI Service] Dify API请求失败,详细错误:', error);
|
||||||
|
console.error('[AI Service] 错误堆栈:', error.stack);
|
||||||
|
// 打印更多信息帮助调试
|
||||||
|
console.error('[AI Service] store 状态:', {
|
||||||
|
memberInfo: store.state.memberInfo,
|
||||||
|
uniacid: this.getUniacid(),
|
||||||
|
token: store.state.token
|
||||||
|
});
|
||||||
throw new Error('AI服务暂时不可用,请稍后重试');
|
throw new Error('AI服务暂时不可用,请稍后重试');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -81,7 +118,7 @@ export default {
|
|||||||
socketTask.send({
|
socketTask.send({
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
action: 'auth',
|
action: 'auth',
|
||||||
uniacid: store.state.uniacid || '1',
|
uniacid: this.getUniacid(),
|
||||||
token: store.state.token || 'test_token',
|
token: store.state.token || 'test_token',
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous'
|
user_id: store.state.memberInfo?.id || 'anonymous'
|
||||||
})
|
})
|
||||||
@@ -99,10 +136,11 @@ export default {
|
|||||||
socketTask.send({
|
socketTask.send({
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
action: 'chat',
|
action: 'chat',
|
||||||
uniacid: store.state.uniacid || '1',
|
uniacid: this.getUniacid(),
|
||||||
query: message,
|
query: message,
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous',
|
user_id: store.state.memberInfo?.id || 'anonymous',
|
||||||
conversation_id: this.getConversationId() || ''
|
conversation_id: this.getConversationId() || '',
|
||||||
|
...getDomainParams()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
} else if (data.type === 'auth_failed') {
|
} else if (data.type === 'auth_failed') {
|
||||||
@@ -179,12 +217,14 @@ export default {
|
|||||||
'Accept': 'text/event-stream',
|
'Accept': 'text/event-stream',
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
uniacid: store.state.uniacid || '1',
|
uniacid: this.getUniacid(),
|
||||||
|
token: store.state.token || 'test_token',
|
||||||
inputs: {},
|
inputs: {},
|
||||||
query: message,
|
query: message,
|
||||||
response_mode: 'streaming',
|
response_mode: 'streaming',
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous',
|
user_id: store.state.memberInfo?.id || 'anonymous',
|
||||||
conversation_id: this.getConversationId() || ''
|
conversation_id: this.getConversationId() || '',
|
||||||
|
...getDomainParams()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -318,17 +358,19 @@ export default {
|
|||||||
* 生成新会话(如需)
|
* 生成新会话(如需)
|
||||||
*/
|
*/
|
||||||
async generateConversationId() {
|
async generateConversationId() {
|
||||||
const params = {
|
const params = {
|
||||||
url: '/api/kefu/createConversation',
|
url: '/api/kefu/createConversation',
|
||||||
data: {
|
data: {
|
||||||
uniacid: store.state.uniacid,
|
uniacid: this.getUniacid(),
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous',
|
token: store.state.token || 'test_token',
|
||||||
member_id: store.state.memberInfo?.id || '',
|
user_id: store.state.memberInfo?.id || 'anonymous',
|
||||||
},
|
member_id: store.state.memberInfo?.id || '',
|
||||||
header: {
|
...getDomainParams()
|
||||||
'Content-Type': 'application/json'
|
},
|
||||||
}
|
header: {
|
||||||
};
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
};
|
||||||
const response = await http.sendRequest({
|
const response = await http.sendRequest({
|
||||||
...params,
|
...params,
|
||||||
async: false
|
async: false
|
||||||
@@ -346,6 +388,7 @@ export default {
|
|||||||
async: false,
|
async: false,
|
||||||
data: {}
|
data: {}
|
||||||
});
|
});
|
||||||
|
console.log('/api/kefu/health response', response);
|
||||||
const available = [response?.data?.status, response?.data?.components?.ai_service_config?.status]
|
const available = [response?.data?.status, response?.data?.components?.ai_service_config?.status]
|
||||||
.filter(item => item === 'healthy').length > 0;
|
.filter(item => item === 'healthy').length > 0;
|
||||||
return {
|
return {
|
||||||
@@ -367,7 +410,10 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const response = await http.sendRequest({
|
const response = await http.sendRequest({
|
||||||
url: '/api/kefu/clear-conversation',
|
url: '/api/kefu/clear-conversation',
|
||||||
data: { conversation_id: conversationId },
|
data: {
|
||||||
|
conversation_id: conversationId,
|
||||||
|
...getDomainParams()
|
||||||
|
},
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
return response.success;
|
return response.success;
|
||||||
@@ -386,13 +432,14 @@ export default {
|
|||||||
throw new Error('会话ID(conversation_id)是必填参数');
|
throw new Error('会话ID(conversation_id)是必填参数');
|
||||||
}
|
}
|
||||||
const requestData = {
|
const requestData = {
|
||||||
uniacid: params.uniacid || store.state.uniacid || '1',
|
uniacid: params.uniacid || this.getUniacid(),
|
||||||
conversation_id: params.conversation_id,
|
conversation_id: params.conversation_id,
|
||||||
user_id: params.user_id || store.state.memberInfo?.id || 'anonymous',
|
user_id: params.user_id || store.state.memberInfo?.id || 'anonymous',
|
||||||
limit: params.limit || 20,
|
limit: params.limit || 20,
|
||||||
offset: params.offset || 0,
|
offset: params.offset || 0,
|
||||||
member_id: params.member_id || store.state.memberInfo?.id || '',
|
member_id: params.member_id || store.state.memberInfo?.id || '',
|
||||||
token: params.token || ''
|
token: params.token || '',
|
||||||
|
...getDomainParams()
|
||||||
};
|
};
|
||||||
const response = await http.sendRequest({
|
const response = await http.sendRequest({
|
||||||
url: '/api/kefu/getHistory',
|
url: '/api/kefu/getHistory',
|
||||||
@@ -431,13 +478,15 @@ export default {
|
|||||||
if (window.currentEventSource) {
|
if (window.currentEventSource) {
|
||||||
window.currentEventSource.close();
|
window.currentEventSource.close();
|
||||||
}
|
}
|
||||||
const params = new URLSearchParams({
|
const paramsObj = {
|
||||||
uniacid: store.state.uniacid || '1',
|
uniacid: this.getUniacid(),
|
||||||
user_id: store.state.memberInfo?.id || '123456',
|
user_id: store.state.memberInfo?.id,
|
||||||
query: message,
|
query: message,
|
||||||
conversation_id: conversationId || '',
|
conversation_id: conversationId || '',
|
||||||
stream: 'true'
|
stream: 'true',
|
||||||
});
|
...getDomainParams()
|
||||||
|
};
|
||||||
|
const params = new URLSearchParams(paramsObj);
|
||||||
const url = `${Config.baseUrl}/api/kefu/chat?${params.toString()}`;
|
const url = `${Config.baseUrl}/api/kefu/chat?${params.toString()}`;
|
||||||
try {
|
try {
|
||||||
const eventSource = new EventSource(url);
|
const eventSource = new EventSource(url);
|
||||||
|
|||||||
@@ -99,9 +99,6 @@
|
|||||||
<text class="unit price-style small">.{{
|
<text class="unit price-style small">.{{
|
||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
|
||||||
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询底价' }}</text>
|
|
||||||
</block>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="member-price-tag"
|
<view class="member-price-tag"
|
||||||
v-if="item.member_price && item.member_price == showPrice(item)">
|
v-if="item.member_price && item.member_price == showPrice(item)">
|
||||||
@@ -120,6 +117,11 @@
|
|||||||
<text>{{ showMarketPrice(item) }}</text>
|
<text>{{ showMarketPrice(item) }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="ai-chat-btn-wrap" v-if="item.isinformation == 1">
|
||||||
|
<view class="ai-chat-btn" @tap.stop="sendToAIChat(item)">
|
||||||
|
立即咨询
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- <view class="right-wrap" v-if="value.template == 2 || value.template == 4">
|
<!-- <view class="right-wrap" v-if="value.template == 2 || value.template == 4">
|
||||||
<block v-if="item.is_virtual">
|
<block v-if="item.is_virtual">
|
||||||
@@ -185,18 +187,14 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="price-wrap">
|
<view class="price-wrap">
|
||||||
<view class="discount-price">
|
<view class="discount-price">
|
||||||
<block v-if="item.isinformation == 0">
|
<block v-if="item.isinformation == 0">
|
||||||
<text class="unit price-style small">¥</text>
|
<text class="unit price-style small">¥</text>
|
||||||
<text class="price price-style large">{{
|
<text class="price price-style large">{{
|
||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[0] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[0] }}</text>
|
||||||
<text class="unit price-style small">.{{
|
<text class="unit price-style small">.{{
|
||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
</view>
|
||||||
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询底价' }}</text>
|
|
||||||
</block>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
<view class="member-price-tag"
|
<view class="member-price-tag"
|
||||||
v-if="item.member_price && item.member_price == showPrice(item)">
|
v-if="item.member_price && item.member_price == showPrice(item)">
|
||||||
<image :src="$util.img('public/uniapp/index/VIP.png')" mode="widthFix" />
|
<image :src="$util.img('public/uniapp/index/VIP.png')" mode="widthFix" />
|
||||||
@@ -213,6 +211,11 @@
|
|||||||
<text>{{ showMarketPrice(item) }}</text>
|
<text>{{ showMarketPrice(item) }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="ai-chat-btn-wrap" v-if="item.isinformation == 1">
|
||||||
|
<view class="ai-chat-btn" @tap.stop="sendToAIChat(item)">
|
||||||
|
立即咨询
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="right-wrap" v-if="value.template == 2">
|
<view class="right-wrap" v-if="value.template == 2">
|
||||||
<block v-if="item.is_virtual">
|
<block v-if="item.is_virtual">
|
||||||
@@ -721,23 +724,13 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 发送商品信息到智能客服
|
* 跳转到商品详情
|
||||||
* @param {Object} item 商品信息
|
* @param {Object} item 商品信息
|
||||||
*/
|
*/
|
||||||
sendToAIChat(item) {
|
sendToAIChat(item) {
|
||||||
const productInfo = {
|
this.$util.redirectTo('/pages_goods/detail', {
|
||||||
goods_id: item.goods_id,
|
goods_id: item.goods_id
|
||||||
goods_name: item.goods_name,
|
});
|
||||||
price: this.showPrice(item),
|
|
||||||
image: this.goodsImg(item.goods_image),
|
|
||||||
category_id: item.category_id
|
|
||||||
}
|
|
||||||
|
|
||||||
uni.setStorageSync('selectedProduct', productInfo)
|
|
||||||
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages_tool/ai-chat/index'
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
diyRedirectTo(link) {
|
diyRedirectTo(link) {
|
||||||
if (!link) return;
|
if (!link) return;
|
||||||
@@ -1406,5 +1399,24 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ai-chat-btn-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-chat-btn {
|
||||||
|
background-color: #ff0000;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12rpx 30rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -913,7 +913,7 @@ export default {
|
|||||||
// ===== 主容器样式 =====
|
// ===== 主容器样式 =====
|
||||||
.tab-diy-component-preview-container {
|
.tab-diy-component-preview-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 300px;
|
min-height: 0px;
|
||||||
display: flex;
|
display: flex;
|
||||||
border: 1px solid #e0e0e0;
|
border: 1px solid #e0e0e0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|||||||
@@ -53,8 +53,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.listenPrivacySettingChange()
|
// 检查配置,决定是否显示隐私协议
|
||||||
this.curPageShow()
|
const shopInfo = uni.getStorageSync('shopInfo');
|
||||||
|
if (shopInfo?.ischina == 1 && shopInfo?.index_login_auth == 1) {
|
||||||
|
this.listenPrivacySettingChange()
|
||||||
|
this.curPageShow()
|
||||||
|
} else {
|
||||||
|
// 如果不需要显示隐私协议,直接触发同意事件
|
||||||
|
this.$emit('agree');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
try {
|
try {
|
||||||
@@ -152,6 +159,14 @@ export default {
|
|||||||
},
|
},
|
||||||
// 主动查询用户隐私政策授权状态
|
// 主动查询用户隐私政策授权状态
|
||||||
proactive() {
|
proactive() {
|
||||||
|
// 检查配置,决定是否显示隐私协议
|
||||||
|
const shopInfo = uni.getStorageSync('shopInfo');
|
||||||
|
if (!(shopInfo?.ischina == 1 && shopInfo?.index_login_auth == 1)) {
|
||||||
|
// 如果不需要显示隐私协议,直接触发同意事件
|
||||||
|
this.$emit('agree');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
if (wx.getPrivacySetting) {
|
if (wx.getPrivacySetting) {
|
||||||
wx.getPrivacySetting({
|
wx.getPrivacySetting({
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ export const lang = {
|
|||||||
title: '商品分类',
|
title: '商品分类',
|
||||||
search:'商品搜索',
|
search:'商品搜索',
|
||||||
seeMore : '查看更多',
|
seeMore : '查看更多',
|
||||||
Make: "询底价"
|
Make: "立即咨询"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ export const lang = {
|
|||||||
//title为每个页面的标题
|
//title为每个页面的标题
|
||||||
title: '',
|
title: '',
|
||||||
select: '选择',
|
select: '选择',
|
||||||
details:'资源详情',
|
details:'商品详情',
|
||||||
params: '参数',
|
params: '参数',
|
||||||
service: '商品服务',
|
service: '商品服务',
|
||||||
allGoods: '全部商品',
|
allGoods: '全部商品',
|
||||||
@@ -11,7 +11,7 @@ export const lang = {
|
|||||||
home:'首页',
|
home:'首页',
|
||||||
cart:'购物车',
|
cart:'购物车',
|
||||||
leave:'立即留言',
|
leave:'立即留言',
|
||||||
make:'联系我们',
|
make:'立即咨询',
|
||||||
|
|
||||||
send:'配送',
|
send:'配送',
|
||||||
express:'快递发货',
|
express:'快递发货',
|
||||||
@@ -22,7 +22,7 @@ export const lang = {
|
|||||||
status:'该商品已下架',
|
status:'该商品已下架',
|
||||||
sellout:'库存不足',
|
sellout:'库存不足',
|
||||||
max:'已达最大限购数量',
|
max:'已达最大限购数量',
|
||||||
makebtn:'价格电议',
|
makebtn:'立即咨询',
|
||||||
sales:'销量',
|
sales:'销量',
|
||||||
stock:'库存',
|
stock:'库存',
|
||||||
kefu:'客服',
|
kefu:'客服',
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ export const lang = {
|
|||||||
Price:'价格',
|
Price:'价格',
|
||||||
Filter:'筛选',
|
Filter:'筛选',
|
||||||
Search:'请输入您要搜索的商品',
|
Search:'请输入您要搜索的商品',
|
||||||
Make:'立即询底价',
|
Make:'立即咨询',
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
{
|
{
|
||||||
"path": "detail",
|
"path": "detail",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "资源详情"
|
"navigationBarTitleText": "商品详情"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
minScrollTop: 100, // 设置回到顶端按钮显示要求,最小页面滚动距离
|
minScrollTop: 100, // 设置回到顶端按钮显示要求,最小页面滚动距离
|
||||||
wechatQrcode: '', // 公众号二维码
|
wechatQrcode: '', // 公众号二维码
|
||||||
diyRoute: '/pages/index/index'
|
diyRoute: '/pages/index/index',
|
||||||
|
shopInfo: null // 店铺信息
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad(option) {
|
onLoad(option) {
|
||||||
@@ -15,10 +16,15 @@ export default {
|
|||||||
// #endif
|
// #endif
|
||||||
this.name = option.name || 'DIY_VIEW_INDEX'; // 根据店铺运营模式,打开平台(shop)或者连锁门店(stroe)页面,接口会自行判断
|
this.name = option.name || 'DIY_VIEW_INDEX'; // 根据店铺运营模式,打开平台(shop)或者连锁门店(stroe)页面,接口会自行判断
|
||||||
|
|
||||||
|
// 获取店铺信息
|
||||||
|
this.shopInfo = uni.getStorageSync('shopInfo');
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
// 获取关注公众号二维码
|
// 获取关注公众号二维码
|
||||||
this.getFollowQrcode();
|
this.getFollowQrcode();
|
||||||
|
|
||||||
|
// 重新获取店铺信息
|
||||||
|
this.shopInfo = uni.getStorageSync('shopInfo');
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 监听图片、文字、商品列表等组件的点击事件
|
// 监听图片、文字、商品列表等组件的点击事件
|
||||||
@@ -59,6 +65,11 @@ export default {
|
|||||||
officialAccountsClose() {
|
officialAccountsClose() {
|
||||||
this.$refs.officialAccountsPopup.close();
|
this.$refs.officialAccountsPopup.close();
|
||||||
},
|
},
|
||||||
|
// 判断是否需要登录授权
|
||||||
|
_needLoginAuth() {
|
||||||
|
// 检查 index_login_auth 都开启时才需要登录授权
|
||||||
|
return this.shopInfo?.index_login_auth == 1;
|
||||||
|
},
|
||||||
// 统一处理点击及触摸事件
|
// 统一处理点击及触摸事件
|
||||||
_handleDiyGroupInteractionEvent(payload) {
|
_handleDiyGroupInteractionEvent(payload) {
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
@@ -66,6 +77,11 @@ export default {
|
|||||||
return true;
|
return true;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
// 如果不需要登录授权,直接返回 true 继续传播
|
||||||
|
if (!this._needLoginAuth()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 如果已登录,直接返回 true 继续传播
|
// 如果已登录,直接返回 true 继续传播
|
||||||
if (this.storeToken) {
|
if (this.storeToken) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
|
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
|
||||||
<view class="goods-container">
|
<view class="goods-container">
|
||||||
<!-- AI客服悬浮按钮 -->
|
<!-- AI客服悬浮按钮 -->
|
||||||
<view class="ai-chat-float-btn" @tap.stop="$emit('aiChatClick')" v-if="goodsSkuDetail">
|
<view class="ai-chat-float-btn" @tap.stop="$emit('aiChatClick')" v-if="showAIChatBtn">
|
||||||
<image :src="aiAvatarUrl" mode="aspectFill" class="ai-avatar-icon" />
|
<image :src="aiAvatarUrl" mode="aspectFill" class="ai-avatar-icon" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -464,6 +464,7 @@
|
|||||||
import scroll from '@/common/js/scroll-view.js';
|
import scroll from '@/common/js/scroll-view.js';
|
||||||
import detail from './detail.js';
|
import detail from './detail.js';
|
||||||
import IMAGE_CONFIG from '@/common/js/image-config.js';
|
import IMAGE_CONFIG from '@/common/js/image-config.js';
|
||||||
|
import { createCustomerService } from '@/common/js/customer-service.js';
|
||||||
|
|
||||||
import pengpaiFadeinOut from '../pengpai-fadein-out/pengpai-fadein-out.vue';
|
import pengpaiFadeinOut from '../pengpai-fadein-out/pengpai-fadein-out.vue';
|
||||||
|
|
||||||
@@ -483,6 +484,10 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
aiAvatarUrl() {
|
aiAvatarUrl() {
|
||||||
return this.$util.img(IMAGE_CONFIG.aiAvatar);
|
return this.$util.img(IMAGE_CONFIG.aiAvatar);
|
||||||
|
},
|
||||||
|
showAIChatBtn() {
|
||||||
|
const customerService = createCustomerService(this);
|
||||||
|
return customerService.hasValidKefuConfig() && customerService.isAIKefu();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [scroll, detail]
|
mixins: [scroll, detail]
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
diyData: null
|
diyData: null,
|
||||||
|
mpShareData: null //小程序分享数据
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -38,6 +39,25 @@ export default {
|
|||||||
onShow() {
|
onShow() {
|
||||||
this.$util.hideHomeButton();
|
this.$util.hideHomeButton();
|
||||||
if (this.$refs.category) this.$refs.category[0].pageShow();
|
if (this.$refs.category) this.$refs.category[0].pageShow();
|
||||||
|
|
||||||
|
//小程序分享
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.$util.getMpShare('/pages_goods/category').then(res => {
|
||||||
|
this.mpShareData = res;
|
||||||
|
}).catch(err => {
|
||||||
|
// 如果后台没配置,用默认值
|
||||||
|
this.mpShareData = {
|
||||||
|
appMessage: {
|
||||||
|
title: '发现超多好物,快来看看',
|
||||||
|
path: '/pages_goods/category'
|
||||||
|
},
|
||||||
|
timeLine: {
|
||||||
|
title: '发现超多好物,快来看看',
|
||||||
|
query: '/pages_goods/category'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
},
|
},
|
||||||
onUnload() {
|
onUnload() {
|
||||||
if (!this.storeToken && this.$refs.login) this.$refs.login.cancelCompleteInfo();
|
if (!this.storeToken && this.$refs.login) this.$refs.login.cancelCompleteInfo();
|
||||||
@@ -69,6 +89,24 @@ export default {
|
|||||||
onPullDownRefresh() {
|
onPullDownRefresh() {
|
||||||
uni.hideTabBar();
|
uni.hideTabBar();
|
||||||
this.getDiyInfo();
|
this.getDiyInfo();
|
||||||
|
},
|
||||||
|
onShareAppMessage() {
|
||||||
|
return this.mpShareData?.appMessage || {
|
||||||
|
title: '发现超多好物,快来看看',
|
||||||
|
path: '/pages_goods/category'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onShareTimeline() {
|
||||||
|
return this.mpShareData?.timeLine || {
|
||||||
|
title: '发现超多好物,快来看看',
|
||||||
|
query: '/pages_goods/category'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onAddToFavorites() {
|
||||||
|
return {
|
||||||
|
title: '发现超多好物,快来看看',
|
||||||
|
path: '/pages_goods/category'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -77,7 +77,6 @@
|
|||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<template>
|
<template>
|
||||||
<text class="price price-font" style="font-weight: 600;">{{$lang('makebtn')}}</text>
|
|
||||||
</template>
|
</template>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
@@ -461,11 +460,12 @@
|
|||||||
<ns-goods-action-icon :text="$lang('follow')" :icon="whetherCollection == 1 ? 'icon-likefill color-base-text' : 'icon-guanzhu'" @click="editCollection" />
|
<ns-goods-action-icon :text="$lang('follow')" :icon="whetherCollection == 1 ? 'icon-likefill color-base-text' : 'icon-guanzhu'" @click="editCollection" />
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<block v-if="goodsSkuDetail.isinformation >= 1">
|
<block v-if="goodsSkuDetail.isinformation >= 1">
|
||||||
|
|
||||||
<ns-goods-action-button v-if="goodsSkuDetail.isinformation == 1" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="phoneClick(goodsSkuDetail.goods_mobile)" :text="$lang('make')" :disabled="false" />
|
<ns-goods-action-button v-if="goodsSkuDetail.isinformation == 1" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="phoneClick(goodsSkuDetail.goods_mobile)" :text="$lang('make')" :disabled="false" />
|
||||||
<ns-goods-action-button v-if="goodsSkuDetail.isinformation == 2" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="showinformation" :text="$lang('leave')" :disabled="false" />
|
<ns-goods-action-button v-if="goodsSkuDetail.isinformation == 2" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="showinformation" :text="$lang('leave')" :disabled="false" />
|
||||||
<!-- <ns-goods-action-button v-if="goodsSkuDetail.isinformation == 2" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="buyNow" text="商品留言" :disabled="false" /> -->
|
<ns-goods-action-button v-if="goodsSkuDetail.isinformation == 3" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="goToAIChat" text="智能客服" :disabled="false" />
|
||||||
|
<!-- <ns-goods-action-button v-if="goodsSkuDetail.isinformation == 2" class="goods-action-button active3" disabled-text="" backgroundColor="#54c952" @click="buyNow" text="商品留言" :disabled="false" /> -->
|
||||||
|
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<block v-if="goodsSkuDetail.stock == 0 && !goodsSkuDetail.sku_spec_format">
|
<block v-if="goodsSkuDetail.stock == 0 && !goodsSkuDetail.sku_spec_format">
|
||||||
@@ -515,6 +515,19 @@
|
|||||||
|
|
||||||
<!-- 隐私弹窗 -->
|
<!-- 隐私弹窗 -->
|
||||||
<privacy-popup ref="privacyPopup"></privacy-popup>
|
<privacy-popup ref="privacyPopup"></privacy-popup>
|
||||||
|
|
||||||
|
<!-- 联系电话弹窗 -->
|
||||||
|
<uni-popup ref="contactPopup" type="center">
|
||||||
|
<view class="contact-popup">
|
||||||
|
<view class="contact-content">
|
||||||
|
<text class="contact-text">可在手机端拨打 021-51815181</text>
|
||||||
|
</view>
|
||||||
|
<view class="contact-buttons">
|
||||||
|
<button class="contact-btn cancel-btn" @click="closeContactPopup">取消</button>
|
||||||
|
<button class="contact-btn copy-btn" @click="copyPhoneNumber">复制到剪切板</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -538,23 +551,54 @@ export default {
|
|||||||
* @param {Object} item 商品信息
|
* @param {Object} item 商品信息
|
||||||
*/
|
*/
|
||||||
sendToAIChat(item) {
|
sendToAIChat(item) {
|
||||||
|
this.$refs.contactPopup.open();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳转到智能客服页面
|
||||||
|
*/
|
||||||
|
goToAIChat() {
|
||||||
const productInfo = {
|
const productInfo = {
|
||||||
goods_id: item.goods_id || '',
|
goods_id: this.goodsSkuDetail.goods_id || '',
|
||||||
goods_name: item.goods_name || '',
|
goods_name: this.goodsSkuDetail.goods_name || '',
|
||||||
price: item.discount_price || item.member_price || item.price || '',
|
price: this.goodsSkuDetail.discount_price || this.goodsSkuDetail.member_price || this.goodsSkuDetail.price || '',
|
||||||
image: item.sku_image || '',
|
image: this.goodsSkuDetail.sku_image || '',
|
||||||
category_id: item.category_id || ''
|
category_id: this.goodsSkuDetail.category_id || ''
|
||||||
}
|
};
|
||||||
|
|
||||||
uni.setStorageSync('selectedProduct', productInfo)
|
uni.setStorageSync('selectedProduct', productInfo);
|
||||||
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages_tool/ai-chat/index'
|
url: '/pages_tool/ai-chat/index'
|
||||||
})
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭联系电话弹窗
|
||||||
|
*/
|
||||||
|
closeContactPopup() {
|
||||||
|
this.$refs.contactPopup.close();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制电话号码到剪切板
|
||||||
|
*/
|
||||||
|
copyPhoneNumber() {
|
||||||
|
uni.setClipboardData({
|
||||||
|
data: '021-51815181',
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '复制成功',
|
||||||
|
icon: 'success'
|
||||||
|
});
|
||||||
|
this.closeContactPopup();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '@/common/css/goods_detail.scss';
|
@import '@/common/css/goods_detail.scss';
|
||||||
@import './public/css/detail.scss';
|
@import './public/css/detail.scss';
|
||||||
@@ -566,6 +610,57 @@ export default {
|
|||||||
z-index: 999;
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contact-popup {
|
||||||
|
width: 600rpx;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-content {
|
||||||
|
padding: 60rpx 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-buttons {
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 90rpx;
|
||||||
|
line-height: 90rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-btn::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
color: #333333;
|
||||||
|
background: #ffffff;
|
||||||
|
border-right: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn {
|
||||||
|
color: #ffffff;
|
||||||
|
background: #54c952;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
::v-deep .action-icon-wrap .iconfont.icon-shouye1 {
|
::v-deep .action-icon-wrap .iconfont.icon-shouye1 {
|
||||||
|
|||||||
@@ -75,9 +75,6 @@
|
|||||||
<text class="unit price-style small">.{{
|
<text class="unit price-style small">.{{
|
||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="discount-price" v-else>
|
|
||||||
<text class="price price-style large">{{ langstatus ? $lang('Make') : '询底价' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="pro-info" v-if="item.isinformation == 0">
|
<view class="pro-info" v-if="item.isinformation == 0">
|
||||||
<view class="block-wrap">
|
<view class="block-wrap">
|
||||||
@@ -92,6 +89,11 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="ai-chat-btn-wrap" v-if="item.isinformation == 1">
|
||||||
|
<view class="ai-chat-btn" @click.stop="sendToAIChat(item)">
|
||||||
|
立即咨询
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -121,9 +123,6 @@
|
|||||||
<text class="unit price-style small">.{{
|
<text class="unit price-style small">.{{
|
||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="discount-price" v-else>
|
|
||||||
<text class="price price-style large">{{ langstatus ? $lang('Make') : '询底价' }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="pro-info" v-if="item.isinformation == 0">
|
<view class="pro-info" v-if="item.isinformation == 0">
|
||||||
<view class="block-wrap">
|
<view class="block-wrap">
|
||||||
@@ -138,6 +137,11 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="ai-chat-btn-wrap" v-if="item.isinformation == 1">
|
||||||
|
<view class="ai-chat-btn" @click.stop="sendToAIChat(item)">
|
||||||
|
立即咨询
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -219,7 +223,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
mixins: [list]
|
mixins: [list],
|
||||||
|
methods: {
|
||||||
|
sendToAIChat(item) {
|
||||||
|
this.$util.redirectTo('/pages_goods/detail', {
|
||||||
|
goods_id: item.goods_id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -235,4 +246,24 @@ export default {
|
|||||||
::v-deep .sku-layer .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
::v-deep .sku-layer .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||||
max-height: unset !important;
|
max-height: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ai-chat-btn-wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: auto;
|
||||||
|
padding-top: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-chat-btn {
|
||||||
|
background-color: #ff0000;
|
||||||
|
color: #fff;
|
||||||
|
padding: 12rpx 30rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="discount-price" v-else>
|
<view class="discount-price" v-else>
|
||||||
<text class="price price-style large">{{ $lang('Make') ? $lang('Make') : '询底价'
|
<text class="price price-style large">{{ $lang('Make') ? $lang('Make') : '立即咨询'
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="discount-price" v-else>
|
<view class="discount-price" v-else>
|
||||||
<text class="price price-style large">{{ $lang('Make') ? $lang('Make') : '询底价'
|
<text class="price price-style large">{{ $lang('Make') ? $lang('Make') : '立即咨询'
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="member-price-tag"
|
<view class="member-price-tag"
|
||||||
|
|||||||
@@ -209,14 +209,25 @@
|
|||||||
:adjust-position="true"
|
:adjust-position="true"
|
||||||
:cursor-spacing="150"
|
:cursor-spacing="150"
|
||||||
@confirm="sendMessage"
|
@confirm="sendMessage"
|
||||||
@input="onInput" />
|
@input="onInput"
|
||||||
|
@linechange="onLineChange" />
|
||||||
|
|
||||||
|
<!-- 扩大按钮 -->
|
||||||
|
<button v-if="inputLineCount > 3" class="expand-btn" @click="openExpandEditor">
|
||||||
|
<text class="iconfont icon-expand">[ ]</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Emoji按钮 -->
|
||||||
|
<button class="emoji-btn" @click="toggleEmojiPanel">
|
||||||
|
<text class="iconfont icon-smile">😊</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- 发送按钮 -->
|
<!-- 发送按钮 -->
|
||||||
<button
|
<button
|
||||||
class="send-btn"
|
class="send-btn"
|
||||||
:class="{ disabled: !inputText.trim() }"
|
:class="{ disabled: !canSendMessage }"
|
||||||
@click="sendMessage"
|
@click="sendMessage"
|
||||||
:disabled="!inputText.trim()">
|
:disabled="!canSendMessage">
|
||||||
<text>发送</text>
|
<text>发送</text>
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
@@ -261,6 +272,54 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- Emoji面板 -->
|
||||||
|
<view v-if="showEmojiPanel" class="emoji-popup">
|
||||||
|
<view class="emoji-mask" @click="hideEmojiPanel"></view>
|
||||||
|
<view class="emoji-panel">
|
||||||
|
<view class="emoji-header">
|
||||||
|
<text>表情</text>
|
||||||
|
<button class="close-btn" @click="hideEmojiPanel">
|
||||||
|
<text>×</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
<view class="emoji-grid">
|
||||||
|
<view
|
||||||
|
v-for="(emoji, index) in emojiList"
|
||||||
|
:key="index"
|
||||||
|
class="emoji-item"
|
||||||
|
@click="insertEmoji(emoji)">
|
||||||
|
<text class="emoji-text">{{ emoji }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 扩大编辑器弹窗 -->
|
||||||
|
<view v-if="showExpandEditor" class="expand-editor-popup">
|
||||||
|
<view class="expand-editor-mask" @click="closeExpandEditor"></view>
|
||||||
|
<view class="expand-editor-panel">
|
||||||
|
<view class="expand-editor-header">
|
||||||
|
<text>编辑内容</text>
|
||||||
|
<button class="close-btn" @click="closeExpandEditor">
|
||||||
|
<text>×</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
<textarea
|
||||||
|
v-model="expandInputText"
|
||||||
|
class="expand-editor-input"
|
||||||
|
placeholder="请输入您的问题..."
|
||||||
|
: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>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 语音输入面板 -->
|
<!-- 语音输入面板 -->
|
||||||
<view v-if="enalbeVoicePanelShow" class="voice-popup">
|
<view v-if="enalbeVoicePanelShow" class="voice-popup">
|
||||||
<view class="voice-mask" @click="hideVoicePanel"></view>
|
<view class="voice-mask" @click="hideVoicePanel"></view>
|
||||||
@@ -411,6 +470,12 @@ export default {
|
|||||||
messageId: 0,
|
messageId: 0,
|
||||||
showToolsPanel: false,
|
showToolsPanel: false,
|
||||||
enalbeVoicePanelShow: false,
|
enalbeVoicePanelShow: false,
|
||||||
|
showEmojiPanel: false,
|
||||||
|
// 扩大编辑器相关
|
||||||
|
showExpandEditor: false,
|
||||||
|
expandInputText: '',
|
||||||
|
inputLineCount: 0,
|
||||||
|
emojiList: ['😀','😃','😄','😁','😆','😅','🤣','😂','🙂','🙃','😉','😊','😇','🥰','😍','🤩','😘','😗','😚','😋','😛','😜','🤪','😝','🤑','🤗','🤭','🤫','🤔','🤐','🤨','😐','😑','😶','😏','😒','🙄','😬','🤥','😌','😔','😪','🤤','😴','😷','🤒','🤕','🤢','🤮','🤧','🥵','🥶','🥴','😵','🤯','🤠','🥳','😎','🤓','🧐','😕','😟','🙁','😮','😯','😲','😳','🥺','😦','😧','😨','😰','😥','😢','😭','😱','😖','😣','😞','😓','😩','😫','🥱','😤','😡','😠','🤬','😈','👿','💀','💩','👻','👽','🤖','🎃','😺','😸','😹','😻','😼','😽','🙀','😿','😾','👋','🤚','🖐','✋','🖖','👌','🤏','✌','🤞','🤟','🤘','🤙','👈','👉','👆','🖕','👇','☝','👍','👎','✊','👊','🤛','🤜','👏','🙌','👐','🤲','🤝','🙏','✍','💅','🤳','💪','💗','💓','💕','💖','💝','💞','💘','💌','💟','💛','💙','💜','🖤','💔','💢','💣','💥','💫','💦','💨','👁','👀','👅','👄','👂','👃','👶','👦','👧','👨','👩','👴','👵','👱','👲','👳','👴','👵','👶','👼','👸','🎅','🤶','🦸','🦹','🧙','🧚','🧛','🧜','🧝','🧞','🧟','🦄','🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🙈','🙉','🙊','🐒','🐔','🐧','🐦','🐤','🐣','🐥','🦆','🦅','🦉','🦇','🐺','🐗','🐴','🦄','🐝','🐛','🦋','🐌','🐞','🐜','🦟','🦗','🕷','🦂','🐢','🐍','🦎','🦖','🦕','🐙','🦑','🦐','🦞','🦀','🐡','🐠','🐟','🐬','🐳','🐋','🦈','🐊','🐅','🐆','🦓','🦍','🦧','🐘','🦛','🦏','🐪','🐫','🦒','🦘','🐃','🐂','🐄','🐎','🐖','🐏','🐑','🐐','🐓','🦃','🦚','🦜','🦢','🦩','🕊','🐕','🐩','🐈','🐓','🐇','🐁','🐀','🐿','🦔','🐾','🐉','🐲'],
|
||||||
streamingMessage: null,
|
streamingMessage: null,
|
||||||
streamInterval: null,
|
streamInterval: null,
|
||||||
streamContent: '',
|
streamContent: '',
|
||||||
@@ -461,6 +526,11 @@ export default {
|
|||||||
return {
|
return {
|
||||||
bottom: this.keyboardHeight > 0 ? this.keyboardHeight + 'px' : '0px'
|
bottom: this.keyboardHeight > 0 ? this.keyboardHeight + 'px' : '0px'
|
||||||
};
|
};
|
||||||
|
},
|
||||||
|
canSendMessage() {
|
||||||
|
const hasContent = this.inputText && this.inputText.trim() !== ''
|
||||||
|
const hasEmoji = this.containsEmoji(this.inputText)
|
||||||
|
return hasContent || hasEmoji
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
@@ -812,13 +882,17 @@ async loadChatHistoryIfExist() {
|
|||||||
|
|
||||||
// 发送消息
|
// 发送消息
|
||||||
async sendMessage() {
|
async sendMessage() {
|
||||||
if (!this.inputText.trim()) return
|
// 确保有内容或表情
|
||||||
|
const hasContent = this.inputText && this.inputText.trim() !== ''
|
||||||
|
const hasEmoji = this.containsEmoji(this.inputText)
|
||||||
|
|
||||||
|
if (!hasContent && !hasEmoji) return
|
||||||
|
|
||||||
const userMessage = {
|
const userMessage = {
|
||||||
id: ++this.messageId,
|
id: ++this.messageId,
|
||||||
role: 'user',
|
role: 'user',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
content: this.inputText.trim(),
|
content: this.inputText,
|
||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
}
|
}
|
||||||
this.shouldScrollToBottom = true
|
this.shouldScrollToBottom = true
|
||||||
@@ -846,10 +920,11 @@ async loadChatHistoryIfExist() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用AI服务获取回复
|
// 使用AI服务获取回复
|
||||||
|
const enhancedMessage = this.enhanceEmojiMessage(userMessage.content)
|
||||||
if (this.enableStreaming) {
|
if (this.enableStreaming) {
|
||||||
await this.sendStreamMessage(userMessage.content)
|
await this.sendStreamMessage(enhancedMessage)
|
||||||
} else {
|
} else {
|
||||||
await this.sendNormalMessage(userMessage.content)
|
await this.sendNormalMessage(enhancedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1071,11 +1146,8 @@ async loadChatHistoryIfExist() {
|
|||||||
|
|
||||||
// 格式化时间
|
// 格式化时间
|
||||||
formatTime(timestamp) {
|
formatTime(timestamp) {
|
||||||
console.log('【调试】formatTime 接收到的时间戳:', timestamp, typeof timestamp);
|
|
||||||
|
|
||||||
// 如果没有时间戳,就不显示时间
|
// 如果没有时间戳,就不显示时间
|
||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
console.warn('【调试】没有时间戳');
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,21 +1180,15 @@ async loadChatHistoryIfExist() {
|
|||||||
date = new Date(timeValue);
|
date = new Date(timeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('【调试】最终 Date 对象:', date);
|
|
||||||
console.log('【调试】本地时间:', date.toLocaleString());
|
|
||||||
console.log('【调试】小时:', date.getHours());
|
|
||||||
console.log('【调试】分钟:', date.getMinutes());
|
|
||||||
|
|
||||||
// 如果时间无效,就不显示时间
|
// 如果时间无效,就不显示时间
|
||||||
if (isNaN(date.getTime())) {
|
if (isNaN(date.getTime())) {
|
||||||
console.warn('【调试】时间无效:', timestamp);
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const hours = date.getHours().toString().padStart(2, '0');
|
const hours = date.getHours().toString().padStart(2, '0');
|
||||||
const minutes = date.getMinutes().toString().padStart(2, '0');
|
const minutes = date.getMinutes().toString().padStart(2, '0');
|
||||||
const result = hours + ':' + minutes;
|
const result = hours + ':' + minutes;
|
||||||
console.log('【调试】最终显示时间:', result);
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1251,6 +1317,22 @@ async loadChatHistoryIfExist() {
|
|||||||
this.showToolsPanel = false
|
this.showToolsPanel = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 切换Emoji面板
|
||||||
|
toggleEmojiPanel() {
|
||||||
|
this.showEmojiPanel = !this.showEmojiPanel
|
||||||
|
},
|
||||||
|
|
||||||
|
// 隐藏Emoji面板
|
||||||
|
hideEmojiPanel() {
|
||||||
|
this.showEmojiPanel = false
|
||||||
|
},
|
||||||
|
|
||||||
|
// 插入Emoji
|
||||||
|
insertEmoji(emoji) {
|
||||||
|
this.inputText += emoji
|
||||||
|
this.hideEmojiPanel()
|
||||||
|
},
|
||||||
|
|
||||||
// 显示语音面板
|
// 显示语音面板
|
||||||
showVoicePanel() {
|
showVoicePanel() {
|
||||||
this.enalbeVoicePanelShow = true
|
this.enalbeVoicePanelShow = true
|
||||||
@@ -1519,6 +1601,37 @@ async loadChatHistoryIfExist() {
|
|||||||
this.$emit('input-change', e.detail.value)
|
this.$emit('input-change', e.detail.value)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 输入框行数变化事件
|
||||||
|
onLineChange(e) {
|
||||||
|
this.inputLineCount = e.detail.lineCount || 0
|
||||||
|
},
|
||||||
|
|
||||||
|
// 打开扩大编辑器
|
||||||
|
openExpandEditor() {
|
||||||
|
this.expandInputText = this.inputText
|
||||||
|
this.showExpandEditor = true
|
||||||
|
this.hideEmojiPanel()
|
||||||
|
this.hideToolsPanel()
|
||||||
|
},
|
||||||
|
|
||||||
|
// 关闭扩大编辑器
|
||||||
|
closeExpandEditor() {
|
||||||
|
this.showExpandEditor = false
|
||||||
|
this.expandInputText = ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// 从扩大编辑器发送消息
|
||||||
|
async sendFromExpandEditor() {
|
||||||
|
if (!this.expandInputText.trim()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.inputText = this.expandInputText
|
||||||
|
this.closeExpandEditor()
|
||||||
|
|
||||||
|
await this.sendMessage()
|
||||||
|
},
|
||||||
|
|
||||||
// 处理头像加载失败
|
// 处理头像加载失败
|
||||||
handleAvatarError() {
|
handleAvatarError() {
|
||||||
this.avatarError = true
|
this.avatarError = true
|
||||||
@@ -1641,6 +1754,193 @@ async loadChatHistoryIfExist() {
|
|||||||
this.historyOffset = 0
|
this.historyOffset = 0
|
||||||
// 触发清空事件
|
// 触发清空事件
|
||||||
this.$emit('messages-cleared')
|
this.$emit('messages-cleared')
|
||||||
|
},
|
||||||
|
|
||||||
|
// 检测字符串中是否包含表情
|
||||||
|
containsEmoji(str) {
|
||||||
|
const emojiReg = /[\u{1f300}-\u{1f9ff}\u{1f1e0}-\u{1f1ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{200d}\u{2640}-\u{2642}\u{2300}-\u{23ff}\u{2b50}-\u{2bff}]/gu
|
||||||
|
return emojiReg.test(str)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 根据表情生成适当的提示文本,帮助 AI 更好地理解
|
||||||
|
enhanceEmojiMessage(content) {
|
||||||
|
// 常见表情的含义映射
|
||||||
|
const emojiResponses = {
|
||||||
|
'😀': '[开心]',
|
||||||
|
'😂': '[大笑]',
|
||||||
|
'😊': '[微笑]',
|
||||||
|
'❤️': '[爱心]',
|
||||||
|
'👍': '[点赞]',
|
||||||
|
'😭': '[哭泣]',
|
||||||
|
'🙏': '[感谢/拜托]',
|
||||||
|
'😍': '[喜欢]',
|
||||||
|
'🎉': '[庆祝]',
|
||||||
|
'🤔': '[思考]',
|
||||||
|
'😅': '[尴尬]',
|
||||||
|
'😁': '[开心]',
|
||||||
|
'🥰': '[喜爱]',
|
||||||
|
'😘': '[飞吻]',
|
||||||
|
'😏': '[坏笑]',
|
||||||
|
'🥳': '[庆祝]',
|
||||||
|
'😔': '[难过]',
|
||||||
|
'😢': '[哭泣]',
|
||||||
|
'😤': '[生气]',
|
||||||
|
'😴': '[困]',
|
||||||
|
'🤗': '[拥抱]',
|
||||||
|
'🙂': '[微笑]',
|
||||||
|
'😃': '[开心]',
|
||||||
|
'😄': '[大笑]',
|
||||||
|
'😆': '[开心]',
|
||||||
|
'😇': '[天使]',
|
||||||
|
'🤩': '[惊喜]',
|
||||||
|
'😋': '[好吃]',
|
||||||
|
'😛': '[调皮]',
|
||||||
|
'😜': '[调皮]',
|
||||||
|
'🤪': '[搞怪]',
|
||||||
|
'😝': '[开心]',
|
||||||
|
'🤑': '[发财]',
|
||||||
|
'🤭': '[害羞]',
|
||||||
|
'🤫': '[嘘]',
|
||||||
|
'🤐': '[闭嘴]',
|
||||||
|
'🤨': '[疑惑]',
|
||||||
|
'😐': '[无语]',
|
||||||
|
'😑': '[无语]',
|
||||||
|
'😶': '[沉默]',
|
||||||
|
'😒': '[不屑]',
|
||||||
|
'🙄': '[白眼]',
|
||||||
|
'😬': '[尴尬]',
|
||||||
|
'🤥': '[说谎]',
|
||||||
|
'😌': '[安心]',
|
||||||
|
'😪': '[困]',
|
||||||
|
'🤤': '[流口水]',
|
||||||
|
'😷': '[生病]',
|
||||||
|
'🤒': '[发烧]',
|
||||||
|
'🤕': '[受伤]',
|
||||||
|
'🤢': '[恶心]',
|
||||||
|
'🤮': '[呕吐]',
|
||||||
|
'🤧': '[感冒]',
|
||||||
|
'🥵': '[热]',
|
||||||
|
'🥶': '[冷]',
|
||||||
|
'🥴': '[头晕]',
|
||||||
|
'😵': '[晕]',
|
||||||
|
'🤯': '[爆炸]',
|
||||||
|
'🤠': '[酷]',
|
||||||
|
'😎': '[酷]',
|
||||||
|
'🤓': '[书呆子]',
|
||||||
|
'🧐': '[疑惑]',
|
||||||
|
'😕': '[困惑]',
|
||||||
|
'😟': '[担心]',
|
||||||
|
'🙁': '[难过]',
|
||||||
|
'😮': '[惊讶]',
|
||||||
|
'😯': '[惊讶]',
|
||||||
|
'😲': '[震惊]',
|
||||||
|
'😳': '[脸红]',
|
||||||
|
'🥺': '[恳求]',
|
||||||
|
'😦': '[惊讶]',
|
||||||
|
'😧': '[惊讶]',
|
||||||
|
'😨': '[害怕]',
|
||||||
|
'😰': '[紧张]',
|
||||||
|
'😥': '[失望]',
|
||||||
|
'😱': '[恐惧]',
|
||||||
|
'😖': '[困扰]',
|
||||||
|
'😣': '[痛苦]',
|
||||||
|
'😞': '[难过]',
|
||||||
|
'😓': '[汗]',
|
||||||
|
'😩': '[累]',
|
||||||
|
'😫': '[累]',
|
||||||
|
'🥱': '[困]',
|
||||||
|
'😡': '[愤怒]',
|
||||||
|
'😠': '[生气]',
|
||||||
|
'🤬': '[咒骂]',
|
||||||
|
'😈': '[恶魔]',
|
||||||
|
'👿': '[生气]',
|
||||||
|
'💀': '[骷髅]',
|
||||||
|
'💩': '[便便]',
|
||||||
|
'👻': '[鬼]',
|
||||||
|
'👽': '[外星人]',
|
||||||
|
'🤖': '[机器人]',
|
||||||
|
'🎃': '[万圣节]',
|
||||||
|
'😺': '[开心猫]',
|
||||||
|
'😸': '[微笑猫]',
|
||||||
|
'😹': '[大笑猫]',
|
||||||
|
'😻': '[花痴猫]',
|
||||||
|
'😼': '[得意猫]',
|
||||||
|
'😽': '[亲亲猫]',
|
||||||
|
'🙀': '[惊讶猫]',
|
||||||
|
'😿': '[哭泣猫]',
|
||||||
|
'😾': '[生气猫]',
|
||||||
|
'👋': '[挥手]',
|
||||||
|
'🤚': '[举手]',
|
||||||
|
'🖐': '[手掌]',
|
||||||
|
'✋': '[手掌]',
|
||||||
|
'🖖': '[V]',
|
||||||
|
'👌': '[OK]',
|
||||||
|
'🤏': '[捏]',
|
||||||
|
'✌️': '[耶]',
|
||||||
|
'🤞': '[好运]',
|
||||||
|
'🤟': '[爱你]',
|
||||||
|
'🤘': '[摇滚]',
|
||||||
|
'🤙': '[打电话]',
|
||||||
|
'👈': '[左边]',
|
||||||
|
'👉': '[右边]',
|
||||||
|
'👆': '[上边]',
|
||||||
|
'🖕': '[竖中指]',
|
||||||
|
'👇': '[下边]',
|
||||||
|
'☝': '[向上]',
|
||||||
|
'👎': '[鄙视]',
|
||||||
|
'✊': '[拳头]',
|
||||||
|
'👊': '[拳头]',
|
||||||
|
'🤛': '[左拳]',
|
||||||
|
'🤜': '[右拳]',
|
||||||
|
'👏': '[鼓掌]',
|
||||||
|
'🙌': '[举手庆祝]',
|
||||||
|
'👐': '[张开手]',
|
||||||
|
'🤲': '[摊手]',
|
||||||
|
'🤝': '[握手]',
|
||||||
|
'✍️': '[写字]',
|
||||||
|
'💅': '[美甲]',
|
||||||
|
'🤳': '[自拍]',
|
||||||
|
'💪': '[肌肉]',
|
||||||
|
'💗': '[爱心]',
|
||||||
|
'💓': '[心跳]',
|
||||||
|
'💕': '[两颗心]',
|
||||||
|
'💖': '[闪亮心]',
|
||||||
|
'💝': '[礼物心]',
|
||||||
|
'💞': '[旋转心]',
|
||||||
|
'💘': '[丘比特]',
|
||||||
|
'💌': '[情书]',
|
||||||
|
'💟': '[心形]',
|
||||||
|
'💛': '[黄心]',
|
||||||
|
'💙': '[蓝心]',
|
||||||
|
'💜': '[紫心]',
|
||||||
|
'🖤': '[黑心]',
|
||||||
|
'💔': '[心碎]',
|
||||||
|
'💢': '[愤怒]',
|
||||||
|
'💣': '[炸弹]',
|
||||||
|
'💥': '[爆炸]',
|
||||||
|
'💫': '[头晕]',
|
||||||
|
'💦': '[汗]',
|
||||||
|
'💨': '[风]',
|
||||||
|
'👁️': '[眼睛]',
|
||||||
|
'👀': '[看]',
|
||||||
|
'👅': '[舌头]',
|
||||||
|
'👄': '[嘴巴]',
|
||||||
|
'👂': '[耳朵]',
|
||||||
|
'👃': '[鼻子]'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是纯表情消息,添加一些提示
|
||||||
|
if (this.containsEmoji(content) && !content.match(/[\u4e00-\u9fa5a-zA-Z]/)) {
|
||||||
|
let enhancedMessage = content
|
||||||
|
// 为表情添加描述
|
||||||
|
for (let emoji in emojiResponses) {
|
||||||
|
if (content.includes(emoji)) {
|
||||||
|
enhancedMessage += ` (${emojiResponses[emoji]})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enhancedMessage
|
||||||
|
}
|
||||||
|
return content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2375,13 +2675,33 @@ $radius-lg: 36rpx;
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
border: 1rpx solid #e5e5e5;
|
border: 1rpx solid #e5e5e5;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
margin-right: -50rpx;
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: #999;
|
color: #999;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Emoji按钮 */
|
||||||
|
.emoji-btn {
|
||||||
|
width: 89rpx;
|
||||||
|
height: 89rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
|
||||||
|
margin-left: 2rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
left:43rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 36rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 发送按钮 - 微信聊天样式 */
|
/* 发送按钮 - 微信聊天样式 */
|
||||||
.send-btn {
|
.send-btn {
|
||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
@@ -2419,7 +2739,7 @@ $radius-lg: 36rpx;
|
|||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
height: 72rpx;
|
height: 72rpx;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
font-size: 28rpx;
|
font-size: 33rpx;
|
||||||
margin-top: 0rpx;
|
margin-top: 0rpx;
|
||||||
margin-bottom: 0rpx;
|
margin-bottom: 0rpx;
|
||||||
}
|
}
|
||||||
@@ -3226,7 +3546,246 @@ $radius-lg: 36rpx;
|
|||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
height: 72rpx;
|
height: 72rpx;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
font-size: 28rpx;
|
font-size: 33rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emoji面板 */
|
||||||
|
.emoji-popup {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
.emoji-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
backdrop-filter: blur(6rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-panel {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 24rpx 24rpx 0 0;
|
||||||
|
padding: 0;
|
||||||
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||||||
|
max-height: 55vh;
|
||||||
|
|
||||||
|
.emoji-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16rpx 20rpx;
|
||||||
|
border-bottom: 1rpx solid #e5e5e5;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
width: 48rpx;
|
||||||
|
height: 48rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(8, 1fr);
|
||||||
|
gap: 8rpx;
|
||||||
|
padding: 20rpx 16rpx;
|
||||||
|
overflow-y: auto;
|
||||||
|
max-height: 45vh;
|
||||||
|
|
||||||
|
.emoji-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
background-color: transparent;
|
||||||
|
transition: all 0.15s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-text {
|
||||||
|
font-size: 48rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 扩大按钮 */
|
||||||
|
.expand-btn {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
padding: 0;
|
||||||
|
left:60rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 36rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 扩大编辑器弹窗 */
|
||||||
|
.expand-editor-popup {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.expand-editor-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
|
backdrop-filter: blur(6rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-editor-panel {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 0;
|
||||||
|
margin-top: 100rpx;
|
||||||
|
|
||||||
|
.expand-editor-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
border-bottom: 1rpx solid #e5e5e5;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
width: 64rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: transparent;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
text {
|
||||||
|
font-size: 48rpx;
|
||||||
|
color: #999;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-editor-input {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 300rpx;
|
||||||
|
max-height: none;
|
||||||
|
padding: 32rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: #fff;
|
||||||
|
border: none;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-editor-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
border-top: 1rpx solid #e5e5e5;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||||
|
|
||||||
|
.expand-cancel-btn {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
color: #666;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-send-btn {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
background-color: #07c160;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background-color: #ccc;
|
||||||
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,7 +248,8 @@ export default {
|
|||||||
latitude: 0,
|
latitude: 0,
|
||||||
longitude: 0,
|
longitude: 0,
|
||||||
},
|
},
|
||||||
personnel_bg: ''
|
personnel_bg: '',
|
||||||
|
mpShareData: null //小程序分享数据
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad(option) {
|
onLoad(option) {
|
||||||
@@ -303,6 +304,24 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.$util.getMpShare('/pages_tool/contact/contact').then(res => {
|
||||||
|
this.mpShareData = res;
|
||||||
|
}).catch(err => {
|
||||||
|
// 如果后台没配置,用默认值
|
||||||
|
this.mpShareData = {
|
||||||
|
appMessage: {
|
||||||
|
title: '联系我们',
|
||||||
|
path: '/pages_tool/contact/contact'
|
||||||
|
},
|
||||||
|
timeLine: {
|
||||||
|
title: '联系我们',
|
||||||
|
query: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
this.$util.hideHomeButton();
|
this.$util.hideHomeButton();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -449,9 +468,28 @@ export default {
|
|||||||
longitude: parseFloat(this.shop.longitude),
|
longitude: parseFloat(this.shop.longitude),
|
||||||
name: this.$lang('oneClickNavigation'),
|
name: this.$lang('oneClickNavigation'),
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
onShareAppMessage() {
|
||||||
|
return this.mpShareData?.appMessage || {
|
||||||
|
title: '联系我们',
|
||||||
|
path: '/pages_tool/contact/contact'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onShareTimeline() {
|
||||||
|
return this.mpShareData?.timeLine || {
|
||||||
|
title: '联系我们',
|
||||||
|
query: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onAddToFavorites() {
|
||||||
|
return {
|
||||||
|
title: '联系我们',
|
||||||
|
path: '/pages_tool/contact/contact'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -134,7 +134,8 @@ export default {
|
|||||||
levelId: 0,
|
levelId: 0,
|
||||||
levelInfo: {
|
levelInfo: {
|
||||||
bg_color: '#333'
|
bg_color: '#333'
|
||||||
}
|
},
|
||||||
|
mpShareData: null //小程序分享数据
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad() {
|
||||||
@@ -161,7 +162,26 @@ export default {
|
|||||||
});
|
});
|
||||||
this.levelInfo = levelInfo;
|
this.levelInfo = levelInfo;
|
||||||
},
|
},
|
||||||
onShow() { },
|
onShow() {
|
||||||
|
//小程序分享
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
this.$util.getMpShare('/pages_tool/member/card').then(res => {
|
||||||
|
this.mpShareData = res;
|
||||||
|
}).catch(err => {
|
||||||
|
// 如果后台没配置,用默认值
|
||||||
|
this.mpShareData = {
|
||||||
|
appMessage: {
|
||||||
|
title: '专属会员权益,快来体验',
|
||||||
|
path: '/pages_tool/member/card'
|
||||||
|
},
|
||||||
|
timeLine: {
|
||||||
|
title: '专属会员权益,快来体验',
|
||||||
|
query: '/pages_tool/member/card'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
headimgError() {
|
headimgError() {
|
||||||
this.memberInfo.headimg = this.$util.getDefaultImage().head;
|
this.memberInfo.headimg = this.$util.getDefaultImage().head;
|
||||||
@@ -185,6 +205,24 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$util.redirectTo(this.$util.MEMBER_PAGE_URL);
|
this.$util.redirectTo(this.$util.MEMBER_PAGE_URL);
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
onShareAppMessage() {
|
||||||
|
return this.mpShareData?.appMessage || {
|
||||||
|
title: '专属会员权益,快来体验',
|
||||||
|
path: '/pages_tool/member/card'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onShareTimeline() {
|
||||||
|
return this.mpShareData?.timeLine || {
|
||||||
|
title: '专属会员权益,快来体验',
|
||||||
|
query: '/pages_tool/member/card'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
onAddToFavorites() {
|
||||||
|
return {
|
||||||
|
title: '专属会员权益,快来体验',
|
||||||
|
path: '/pages_tool/member/card'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user