This commit is contained in:
2026-03-20 16:40:16 +08:00
parent deb949600b
commit 230bb76f63
23 changed files with 9306 additions and 637 deletions

6831
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,9 @@
"core-js": "^3.6.5", "core-js": "^3.6.5",
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"flyio": "^0.6.2", "flyio": "^0.6.2",
"marked": "^4.3.0",
"moment": "^2.29.3", "moment": "^2.29.3",
"mp-html": "^2.5.2",
"node-sass": "4.14.1", "node-sass": "4.14.1",
"sass": "1.26.2", "sass": "1.26.2",
"sass-loader": "8.0.2", "sass-loader": "8.0.2",

View File

@ -107,6 +107,88 @@ export function getHomeServices(data) {
}) })
} }
/**
* 获取 AI 顾问工具列表(无参数)
* @returns {Promise}
*/
export function getAiConsultServices() {
return request({
url: URL.AI_CONSULT_SERVICES,
method: 'POST'
})
}
/**
* 获取 AI 顾问概览(剩余积分、体验人数)(无参数)
* @returns {Promise}
*/
export function getAiConsultOverview() {
return request({
url: URL.AI_CONSULT_OVERVIEW,
method: 'POST'
})
}
/**
* 发送 AI 顾问消息
* @param {Object} data - 请求体
* @param {number} [data.service_id] - AI 服务 ID新会话时必传
* @param {number} [data.session_id] - 会话 ID继续已有会话时传
* @param {Array} data.parts - 消息内容数组,至少 1 项
* @param {string} data.parts[].part_type - "text" | "image" | "audio"
* @param {string} [data.parts[].text_content] - part_type=text 时必填
* @param {string} [data.parts[].file_url] - part_type=image/audio 时必填
* @param {string} [data.parts[].mime_type] - 文件 MIME 类型
* @param {number} [data.parts[].duration_ms] - 音频时长,毫秒
* @returns {Promise}
*/
export function sendAiConsultMessage(data) {
return request({
url: URL.AI_CONSULT_MESSAGES_SEND,
method: 'POST',
data: data || {}
})
}
/**
* 获取 AI 顾问会话消息列表
* @param {Object} params - 请求参数,如 { session_id: string }
* @returns {Promise}
*/
export function getAiConsultSessionMessages(params) {
return request({
url: URL.AI_CONSULT_SESSION_MESSAGES,
method: 'POST',
data: params || {}
})
}
/**
* 获取 AI 顾问历史会话列表(按日期分组)
* @param {Object} params - 请求参数 { service_id: number, pet_id: number|string }
* @returns {Promise}
*/
export function getAiConsultServiceSessions(params) {
return request({
url: URL.AI_CONSULT_SERVICE_SESSIONS,
method: 'POST',
data: params || {}
})
}
/**
* 获取 AI 顾问最近一条会话的消息(根据 service_id + pet_id
* @param {Object} params - { service_id: number, pet_id: number|string }
* @returns {Promise}
*/
export function getAiConsultLatestSessionMessages(params) {
return request({
url: URL.AI_CONSULT_LATEST_SESSION_MESSAGES,
method: 'POST',
data: params || {}
})
}
/** /**
* 获取领养列表 * 获取领养列表
* @param {Object} data - 请求参数 { page: 1, page_size: 10 } * @param {Object} data - 请求参数 { page: 1, page_size: 10 }

View File

@ -304,5 +304,23 @@ export const HOMETRAINING_ORDERS_CANCEL = '/hometraining/orders/cancel'
// 撤销申请(领养申请) // 撤销申请(领养申请)
export const ADOPTIONS_PET_APPLY_CANCEL = '/adoptions/pet/apply/cancel' export const ADOPTIONS_PET_APPLY_CANCEL = '/adoptions/pet/apply/cancel'
// AI 顾问工具列表(无参数)
export const AI_CONSULT_SERVICES = '/ai/consult/services'
// AI 顾问概览:剩余积分 & 体验人数(无参数)
export const AI_CONSULT_OVERVIEW = '/ai/consult/summary'
// AI 顾问发送消息
export const AI_CONSULT_MESSAGES_SEND = '/ai/consult/messages/send'
// AI 顾问获取会话消息列表
export const AI_CONSULT_SESSION_MESSAGES = '/ai/consult/session/messages'
// AI 顾问获取历史会话列表(按日期分组)
export const AI_CONSULT_SERVICE_SESSIONS = '/ai/consult/service/sessions'
// AI 顾问获取最近一条会话消息(根据 service_id + pet_id
export const AI_CONSULT_LATEST_SESSION_MESSAGES = '/ai/consult/service/latest-session/messages'

View File

@ -0,0 +1,188 @@
<template>
<view class="contact-popup-modal" v-if="visible">
<view class="modal-mask" @click="handleCancel"></view>
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">请添加客服</text>
</view>
<view class="modal-body">
<view class="wechat-info-box">
<text class="wechat-code">{{ weChatCode }}</text>
<view class="copy-btn" @click="handleCopy">
<text class="copy-text">复制</text>
</view>
</view>
</view>
<view class="modal-footer">
<view class="cancel-btn" @click="handleCancel">取消</view>
<view class="confirm-btn" @click="handleConfirm">确认</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'ContactPopupModal',
props: {
visible: {
type: Boolean,
default: false
},
weChatCode: {
type: String,
default: 'Wagoo2025'
}
},
emits: ['cancel', 'confirm', 'close'],
methods: {
handleCopy() {
uni.setClipboardData({
data: this.weChatCode,
success: () => {
uni.showToast({
title: '微信号已复制',
icon: 'success'
})
},
fail: (err) => {
console.error('复制失败', err)
uni.showModal({
title: '复制失败',
content: '微信号:' + this.weChatCode + '\n\n请手动输入添加',
showCancel: false,
confirmText: '知道了',
success: () => {
this.$emit('close')
}
})
}
})
},
handleCancel() {
this.$emit('cancel')
this.$emit('close')
},
handleConfirm() {
this.handleCopy()
this.$emit('confirm')
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.contact-popup-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: relative;
width: 600rpx;
background-color: #fff;
border-radius: 24rpx;
overflow: hidden;
animation: modalFadeIn 0.3s ease-out;
@keyframes modalFadeIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
.modal-header {
padding: 40rpx 32rpx 20rpx;
text-align: center;
.modal-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
}
}
.modal-body {
padding: 0 32rpx 40rpx;
.wechat-info-box {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #f5f5f5;
border-radius: 16rpx;
padding: 24rpx 32rpx;
.wechat-code {
font-size: 36rpx;
font-weight: 500;
color: #333;
font-family: monospace;
}
.copy-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 8rpx 16rpx;
.copy-text {
font-size: 24rpx;
color: #ff19a0;
}
}
}
}
.modal-footer {
display: flex;
padding: 0 32rpx 40rpx;
gap: 24rpx;
.cancel-btn,
.confirm-btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
border-radius: 44rpx;
}
.cancel-btn {
background-color: #fff;
color: #ff19a0;
border: 2rpx solid #ff19a0;
}
.confirm-btn {
background-color: #ff19a0;
color: #fff;
border: 2rpx solid #ff19a0;
}
}
}
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<view>
<view
class="draggable-contact"
:style="{ right: right + 'rpx', bottom: bottom + 'rpx' }"
:hover-class="'draggable-contact-hover'"
:hover-stay-time="150"
@touchstart="handleClick"
@tap="handleClick"
>
<view class="click-area">
<image class="contact-icon" :src="iconSrc" mode="aspectFill" />
<view class="contact-btn fs-20" v-if="showText">
{{ text }}
</view>
</view>
</view>
<!-- 联系客服弹窗 -->
<ContactPopupModal
:visible="showContactModalFlag"
@cancel="closeContactModal"
@confirm="closeContactModal"
@close="closeContactModal"
/>
</view>
</template>
<script>
import { jumpToWeChat } from '@/utils/common'
import ContactPopupModal from './ContactPopupModal.vue'
export default {
name: 'DraggableContact',
components: {
ContactPopupModal
},
props: {
// 图标 URL
iconSrc: {
type: String,
default: 'https://static.wagoo.pet/statics/supportStaff.png'
},
// 是否显示文字
showText: {
type: Boolean,
default: true
},
// 按钮文字
text: {
type: String,
default: '联系客服'
},
// 初始底部距离rpx
initialBottom: {
type: Number,
default: 200
},
// 点击回调,不传则使用默认的微信客服弹窗
onClick: {
type: Function,
default: null
}
},
data() {
return {
right: 0,
bottom: this.initialBottom,
showContactModalFlag: false
}
},
mounted() {
// 如果没有传入 initialBottom使用默认计算值
if (this.initialBottom === 200) {
this.initPosition()
}
},
methods: {
// 初始化位置
initPosition() {
const systemInfo = uni.getSystemInfoSync()
const windowHeight = systemInfo.windowHeight
// 计算底部距离35vh 位置
const vh35InRpx = (windowHeight * 0.35 / windowHeight) * 750
this.bottom = vh35InRpx - 130 - 48 + 110 // 往上挪 50px
this.right = 20 // 往左边挪 10px
},
// 点击处理
handleClick(e) {
// console.log('[DraggableContact] handleClick called, event:', e)
// 优先使用传入的回调,否则使用默认弹窗
if (this.onClick) {
console.log('[DraggableContact] calling onClick callback')
try {
this.onClick()
} catch (err) {
// console.error('[DraggableContact] onClick callback error:', err)
// 回调执行失败时使用默认弹窗
this.showContactModal()
}
} else {
// console.log('[DraggableContact] showing default contact modal')
// 默认行为:显示添加客服弹窗
this.showContactModal()
}
},
// 显示联系客服弹窗
showContactModal() {
this.showContactModalFlag = true
},
// 关闭联系客服弹窗
closeContactModal() {
this.showContactModalFlag = false
}
}
}
</script>
<style lang="scss" scoped>
.draggable-contact {
position: fixed;
text-align: center;
z-index: 100000;
display: flex;
flex-direction: column;
align-items: center;
pointer-events: auto;
touch-action: none;
.click-area {
display: flex;
flex-direction: column;
align-items: center;
pointer-events: auto;
touch-action: none;
}
&-hover {
opacity: 0.7;
transform: scale(0.95);
}
.contact-icon {
width: 66rpx;
height: 66rpx;
margin: auto;
border-radius: 50%;
}
.contact-btn {
color: #FFFFFF;
background-color: #FF19A0;
border-radius: 257px;
padding: 6rpx 12rpx;
transform: translateY(-8px);
white-space: nowrap;
}
}
</style>

View File

@ -0,0 +1,208 @@
<template>
<view class="wechat-copy-modal" v-if="visible">
<view class="modal-mask" @click="handleCancel"></view>
<view class="modal-content">
<view class="modal-header">
<view class="modal-title">{{ title }}</view>
</view>
<view class="modal-body">
<view class="wechat-code-wrapper">
<text class="wechat-code">{{ weChatCode }}</text>
<view class="copy-btn" @click="handleCopy">
<image class="copy-icon" :src="copyIcon" mode="aspectFit" />
<text class="copy-text">复制</text>
</view>
</view>
</view>
<view class="modal-footer">
<view class="cancel-btn" @click="handleCancel">取消</view>
<view class="confirm-btn" @click="handleConfirm">确认</view>
</view>
</view>
</view>
</template>
<script>
import { imgPrefix } from "@/utils/common";
export default {
name: "WeChatCopyModal",
data() {
return {
visible: false,
title: '请添加客服号',
weChatCode: 'Wagoo2025',
copyIcon: `${imgPrefix}home-copy.png`
};
},
methods: {
show(options = {}) {
if (options.title) this.title = options.title;
if (options.weChatCode) this.weChatCode = options.weChatCode;
this.visible = true;
// 强制更新视图
this.$forceUpdate();
},
hide() {
this.visible = false;
},
handleCopy() {
// 执行复制
uni.setClipboardData({
data: this.weChatCode,
success: () => {
uni.showToast({
title: '微信号已复制',
icon: 'success'
});
this.hide();
},
fail: (err) => {
console.error('复制失败', err);
// 3. 降级方案:直接显示微信号,引导手动输入
uni.showModal({
title: '复制失败',
content: '微信号:' + this.weChatCode + '\n\n请手动输入添加',
showCancel: false,
confirmText: '知道了'
});
}
});
},
handleCancel() {
this.hide();
this.$emit('cancel');
},
handleConfirm() {
this.handleCopy();
this.hide();
this.$emit('confirm');
}
}
};
</script>
<style lang="scss" scoped>
.wechat-copy-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
.modal-mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
position: relative;
width: 600rpx;
background-color: #fff;
border-radius: 24rpx;
overflow: hidden;
animation: modalSlideIn 0.3s ease-out;
@keyframes modalSlideIn {
from {
opacity: 0;
transform: translateY(-50rpx);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal-header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx 32rpx 20rpx;
}
.modal-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
text-align: center;
}
.modal-body {
padding: 0 32rpx 40rpx;
.wechat-code-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #f5f5f5;
border-radius: 16rpx;
padding: 24rpx 32rpx;
.wechat-code {
font-size: 36rpx;
font-weight: 600;
color: #333;
font-family: monospace;
}
.copy-btn {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
.copy-icon {
width: 40rpx;
height: 40rpx;
}
.copy-text {
font-size: 22rpx;
color: #ff19a0;
}
}
}
}
.modal-footer {
display: flex;
padding: 0 32rpx 40rpx;
gap: 24rpx;
.cancel-btn,
.confirm-btn {
flex: 1;
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
border-radius: 44rpx;
}
.cancel-btn {
background-color: #fff;
color: #ff19a0;
border: 2rpx solid #ff19a0;
}
.confirm-btn {
background-color: #ff19a0;
color: #fff;
border: 2rpx solid #ff19a0;
}
}
}
}
</style>

View File

@ -0,0 +1,343 @@
<template>
<view class="ai-advisor-container">
<scroll-view class="ai-scroll" scroll-y>
<!-- 头部背景图 -->
<view class="advisor-hero">
<image class="advisor-hero-img" :src="imgPrefix + 'ai-ground.png'" mode="widthFix" />
<view class="advisor-hero-overlay">
<text class="hero-subtitle">
已经有<text class="hero-subtitle-value">{{ experienceCount }}</text>位朋友体验过啦~
</text>
<view class="hero-bottom-row">
<view class="hero-btn" @click="goToRecharge">
<text class="hero-btn-text">充值中心</text>
<image :src="imgPrefix + 'recharge-whiteArrow.png'" class="rightArrow" mode="aspectFit" />
</view>
<view class="hero-points">
<image :src="imgPrefix + 'integral-icon.png'" class="hero-points-icon" mode="aspectFit" />
<text class="hero-points-label">剩余积分</text>
<text class="hero-points-value">{{ remainingPoints }}</text>
</view>
<view class="hero-rules" @click="openRulesModal">
<text class="hero-rules-text">使用规则</text>
<image class="hero-rules-icon" :src="imgPrefix + 'trainingTips.png'" mode="aspectFit" />
</view>
</view>
</view>
</view>
<view class="advisor-content">
<view class="tool-grid">
<view class="tool-card" v-for="tool in toolList" :key="tool.id" @click="goToChat(tool)">
<view class="tool-icon-wrap">
<image v-if="tool.service_icon" class="tool-icon" :src="tool.service_icon" mode="aspectFit" />
</view>
<text class="tool-title">{{ tool.service_name }}</text>
</view>
</view>
</view>
</scroll-view>
<!-- 使用规则弹窗 -->
<view v-if="showRulesModal" class="rules-modal-mask" @click="closeRulesModal">
<view class="rules-modal" @click.stop="">
<text class="rules-title">使用规则</text>
<scroll-view scroll-y class="rules-content">
<text class="rules-text">{{ rulesText }}</text>
</scroll-view>
<view class="rules-btn" @click.stop="closeRulesModal">
<text class="rules-btn-text">我知道了</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { imgPrefix } from '@/utils/common';
import { getAiConsultServices, getAiConsultOverview } from '@/api/common';
export default {
name: 'AiAdvisorView',
data() {
return {
imgPrefix,
toolList: [
{ key: 'drug', title: '药品成分分析', icon: 'ai-tool-drug.png' },
{ key: 'vomit', title: '呕吐物分析', icon: 'ai-tool-vomit.png' },
],
remainingPoints: 0,
experienceCount: 0,
showRulesModal: false,
rulesText:
'本平台提供 AI 顾问服务,支持文字咨询与图片生成 / 解析。积分消耗标准:\n1. 文字咨询50 积分 / 次\n2. 图片服务100 积分 / 张',
petInfo: {},
};
},
created() {
getAiConsultServices().then((res) => {
const list = res?.data?.toolList ?? res?.data ?? [];
this.toolList = Array.isArray(list) ? list : [];
});
getAiConsultOverview().then((res) => {
const data = res?.data ?? {};
this.remainingPoints = data?.current_points;
this.experienceCount = data?.consult_user_count;
this.petInfo = data.pet_info
});
},
methods: {
openRulesModal() {
this.showRulesModal = true;
},
closeRulesModal() {
this.showRulesModal = false;
},
goToChat(tool) {
if (this.petInfo == null) {
uni.navigateTo({
url: '/pageHome/selectPet/index?from=aiAdvisor',
});
return;
}
try {
uni.setStorageSync('aiAdvisorPetInfo', this.petInfo || {});
} catch (e) {}
uni.navigateTo({
url: `/pageHome/ai-advisor/chat?key=${encodeURIComponent(tool.id)}&title=${encodeURIComponent(tool.service_name || '')}`,
});
},
goToRecharge() {
uni.navigateTo({
url: '/pages/client/recharge/index?tab=points',
});
},
},
};
</script>
<style lang="scss" scoped>
.ai-advisor-container {
width: 100%;
height: 100%;
}
.ai-scroll {
height: calc(100vh - 176rpx);
}
.advisor-hero {
width: 100%;
border-radius: 24rpx;
overflow: hidden;
margin-bottom: 32rpx;
position: relative;
}
.advisor-hero-img {
width: 100%;
display: block;
}
.advisor-hero-overlay {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 0rpx 24rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.hero-subtitle {
font-size: 20rpx;
color: #7a7a7a;
}
.hero-subtitle-value {
font-size: 24rpx;
color: #ff19a0;
margin: 0rpx 4rpx;
}
.hero-bottom-row {
margin-top: 20rpx;
display: flex;
align-items: center;
}
.hero-btn {
background-color: #ff19a0;
border-radius: 999rpx;
padding: 6rpx 12rpx;
display: flex;
align-items: center;
}
.hero-btn-text {
font-size: 22rpx;
color: #ffffff;
line-height: 1;
}
.rightArrow {
width: 11rpx;
height: 18rpx;
margin-left: 8rpx;
}
.hero-points {
margin-left: 16rpx;
border-radius: 999rpx;
background-color: rgba(0, 0, 0, 0.25);
display: flex;
align-items: center;
box-sizing: border-box;
padding-right: 12rpx;
}
.hero-points-icon {
width: 36rpx;
height: 36rpx;
margin-right: 6rpx;
}
.hero-points-label {
font-size: 22rpx;
color: #fff;
margin-right: 4rpx;
}
.hero-points-value {
font-size: 22rpx;
color: #fff;
font-weight: 600;
}
.hero-rules {
display: flex;
align-items: center;
margin-left: auto;
margin-right: 140rpx;
}
.hero-rules-text {
font-size: 22rpx;
color: #767676;
margin-right: 8rpx;
}
.hero-rules-icon {
width: 28rpx;
height: 28rpx;
}
.advisor-content {
padding: 0 20rpx 20rpx;
box-sizing: border-box;
}
.tool-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
}
.tool-card {
background: #ffffff;
border-radius: 20rpx;
padding: 20rpx 24rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.06);
}
.tool-icon-wrap {
width: 160rpx;
height: 160rpx;
border-radius: 999rpx;
background: rgba(255, 25, 160, 0.08);
display: flex;
align-items: center;
justify-content: center;
}
.tool-icon {
width: 140rpx;
height: 140rpx;
}
.tool-title {
margin-top: 20rpx;
font-size: 24rpx;
color: #515a63;
text-align: center;
}
/* 使用规则弹窗 */
.rules-modal-mask {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.rules-modal {
width: 560rpx;
max-height: 70vh;
background: #ffffff;
border-radius: 32rpx;
padding: 40rpx 40rpx 32rpx;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
}
.rules-title {
font-size: 36rpx;
color: #282828;
font-weight: 500;
text-align: center;
margin-bottom: 24rpx;
}
.rules-content {
max-height: 360rpx;
width: 100%;
}
.rules-text {
font-size: 24rpx;
color: #9b939a;
line-height: 1.6;
}
.rules-btn {
margin-top: 32rpx;
width: 100%;
height: 80rpx;
background: #ff19a0;
border-radius: 999rpx;
display: flex;
align-items: center;
justify-content: center;
}
.rules-btn-text {
font-size: 28rpx;
color: #ffffff;
}
</style>

View File

@ -3,11 +3,8 @@ export default {
appName: "Wagoo", appName: "Wagoo",
appShareName: "Wagoo", appShareName: "Wagoo",
appId: "wx00e2dcdc7c02b23a", appId: "wx00e2dcdc7c02b23a",
// apiBaseUrl: 'https://api.wagoo.cc', // 服务端生产地址 // apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址
apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址 apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
// apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
// apiBaseUrl: "http:192.168.30.79", //本地接口 // apiBaseUrl: "http:192.168.30.79", //本地接口
tencentMapKey: "WSBBZ-7OXK4-46QUC-KFB7B-4N3W7-M2BXM", tencentMapKey: "WSBBZ-7OXK4-46QUC-KFB7B-4N3W7-M2BXM",
tencentSecret: "vb7D0PGj7xUvmOLuJz2Jd7ykTMpjiWRJ", tencentSecret: "vb7D0PGj7xUvmOLuJz2Jd7ykTMpjiWRJ",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
<template>
<view class="ai-advisor-page">
<ai-advisor-view />
</view>
</template>
<script>
import AiAdvisorView from '@/components/ai-advisor/AiAdvisorView.vue';
export default {
name: 'AiAdvisorPage',
components: { AiAdvisorView },
};
</script>
<style lang="scss" scoped>
.ai-advisor-page {
width: 100%;
min-height: 100vh;
background-color: #f7f8fa;
}
</style>

View File

@ -322,14 +322,14 @@
<text v-else class="money">{{ toAmount }}</text> --> <text v-else class="money">{{ toAmount }}</text> -->
<view class="handle-info-cell"> <view class="handle-info-cell">
<view v-if="reservationInfo.estimatePrice != 0"> <view v-if="reservationInfo.estimatePrice != 0">
<text class="money">{{ (estimatedPri - couponMoney2).toFixed(2) }}</text> <text class="money">{{ Math.max(0, estimatedPri - couponMoney2).toFixed(2) }}</text>
<text class="app-fc12">¥</text> <text class="app-fc12">¥</text>
<text class="app-fc1">{{ toAmount3.toFixed(2) || "0.00" }}</text> <text class="app-fc1">{{ Math.max(0, toAmount3).toFixed(2) || "0.00" }}</text>
</view> </view>
<view v-else> <view v-else>
<text class="app-fc-main fs-30">¥</text> <text class="app-fc-main fs-30">¥</text>
<text class="app-fc-main fs-40 app-font-bold">{{ <text class="app-fc-main fs-40 app-font-bold">{{
(toAmount2.toFixed(2) || "0.00") - couponMoney Math.max(0, (toAmount2.toFixed(2) || "0.00") - couponMoney)
}}</text> }}</text>
</view> </view>
</view> </view>

View File

@ -1,7 +1,6 @@
{ {
"easycom": {}, "easycom": {},
"pages": [ "pages": [
//pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{ {
"path": "pages/client/index/index", "path": "pages/client/index/index",
"style": { "style": {
@ -219,6 +218,18 @@
"style": { "style": {
"navigationBarTitleText": "订单详情" "navigationBarTitleText": "订单详情"
} }
},
{
"path": "ai-advisor/index",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "ai-advisor/chat",
"style": {
"navigationStyle": "custom"
}
} }
] ]
}, },

View File

@ -1,5 +1,8 @@
<template> <template>
<view class="home-page"> <view class="home-page">
<!-- 微信复制弹窗 -->
<WeChatCopyModal ref="wechatCopyModal" />
<scroll-view class="homeContainer" scroll-y :show-scrollbar="false" :enhanced="true"> <scroll-view class="homeContainer" scroll-y :show-scrollbar="false" :enhanced="true">
<view class="swiperWrapper"> <view class="swiperWrapper">
<swiper indicator-dots="true" autoplay="true" interval="3000" duration="500" circular="true" <swiper indicator-dots="true" autoplay="true" interval="3000" duration="500" circular="true"
@ -11,9 +14,6 @@
<view class="userInfoWrapper"> <view class="userInfoWrapper">
<view class="userInfo" @click="handleUserInfo"> <view class="userInfo" @click="handleUserInfo">
<image class="avatar-img"
:src="userInfo.avatar ? userInfo.avatar : `${imgPrefix}defaultHeadImg.png`"
mode="aspectFill" />
<view class="userContent"> <view class="userContent">
<view class="userName"> <view class="userName">
{{ userInfo.username ? userInfo.username : "嗨,你好呀" }} {{ userInfo.username ? userInfo.username : "嗨,你好呀" }}
@ -62,12 +62,12 @@
</view> </view>
</view> </view>
<view class="line" /> <view class="line" />
<view class="itemWrapper" @click="toDogTraining"> <view class="itemWrapper" @click="toPublicBenefit" >
<text class="titlWrapper">狗狗训练</text> <text class="titlWrapper">关爱宠物,传递恩情</text>
<view class="content">上门服务</view> <view class="content">公益助理</view>
<view class="tips">上门训犬寄养喂猫遛狗</view> <view class="tips">帮我找个家</view>
<view class="itemImg"> <view class="itemImg">
<image class="menu-img-sm" :src="`${imgPrefix}home-dogTraining.png`" mode="aspectFill" /> <image class="menu-img-sm" :src="`${imgPrefix}h-public.png`" mode="aspectFill" />
</view> </view>
</view> </view>
</view> </view>
@ -99,12 +99,12 @@
</view> </view>
<view class="thirdMenu"> <view class="thirdMenu">
<view class="itemWrapper" @click="toPublicBenefit"> <view class="itemWrapper" @click="toDogTraining">
<view> <view>
<view class="title">公益助力</view> <view class="title">上门服务</view>
<view class="tips">帮我找个家</view> <view class="tips">邀请好友得好礼</view>
</view> </view>
<image class="third-icon" :src="`${imgPrefix}home-publicBenefit.png`" mode="aspectFill" /> <image class="third-icon" :src="`${imgPrefix}h-door.png`" mode="aspectFill" />
</view> </view>
<view class="itemWrapper" @click="toJoin"> <view class="itemWrapper" @click="toJoin">
<view> <view>
@ -136,15 +136,18 @@
<script> <script>
import { import {
imgPrefix, imgPrefix,
jumpToWeChat,
showLoginConfirmModal showLoginConfirmModal
} from "@/utils/common"; } from "@/utils/common";
import { import {
userWllet userWllet
} from "../../../api/login"; } from "../../../api/login";
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
export default { export default {
name: "HomePage", name: "HomePage",
components: {
WeChatCopyModal
},
data() { data() {
return { return {
imgPrefix, imgPrefix,
@ -245,9 +248,15 @@ export default {
}); });
}, },
toDogTraining() { toDogTraining() {
uni.navigateTo({ uni.showToast({
url: '/pageHome/service/index' title: '暂未开放',
icon: 'none',
duration: 2000
}); });
return;
// uni.navigateTo({
// url: '/pageHome/service/index'
// });
}, },
// 我的钱包 // 我的钱包
buyService() { buyService() {
@ -343,10 +352,14 @@ export default {
}); });
}, },
// 跳转微信客服 - 使用自定义弹窗
jumpToWeChat() { jumpToWeChat() {
this.checkTokenAndExecute(() => { if (this.$refs.wechatCopyModal) {
jumpToWeChat(); this.$refs.wechatCopyModal.show({
title: '请添加客服号',
weChatCode: 'Wagoo2025'
}); });
}
}, },
}, },
}; };
@ -363,12 +376,6 @@ export default {
background-color: #ffecf3; background-color: #ffecf3;
overflow: scroll; overflow: scroll;
.avatar-img {
width: 92rpx;
height: 92rpx;
border-radius: 50%;
}
.menu-img-lg { .menu-img-lg {
width: 160rpx; width: 160rpx;
height: 160rpx; height: 160rpx;
@ -383,7 +390,7 @@ export default {
.third-icon, .third-icon,
.service-icon { .service-icon {
width: 96rpx; width: 96rpx;
height: 96rpx; height: 120rpx;
} }
.service-icon { .service-icon {
@ -735,6 +742,7 @@ export default {
} }
} }
} }
} }
.flexClass { .flexClass {

View File

@ -160,24 +160,24 @@
</view> </view>
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image> <image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
</view> </view>
<view class="navItem" @click="jumpTo(`/pages/client/mine/help`)"> <!-- <view class="navItem" @click="jumpTo(`/pages/client/mine/help`)">
<view class="navTitle"> <view class="navTitle">
使用帮助 使用帮助
</view> </view>
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image> <image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
</view> </view> -->
<view class="navItem" @click="jumpTo('/pages/client/news/index')"> <view class="navItem" @click="jumpTo('/pages/client/news/index')">
<view class="navTitle"> <view class="navTitle">
系统消息 系统消息
</view> </view>
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image> <image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
</view> </view>
<view class="navItem" @click="jumpTo(`/pages/client/mine/aboutus`)"> <!-- <view class="navItem" @click="jumpTo(`/pages/client/mine/aboutus`)">
<view class="navTitle"> <view class="navTitle">
关于平台 关于平台
</view> </view>
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image> <image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
</view> </view> -->
<view class="navItem" style="border: none;" v-if="userInfo.phone" @click="showLogoutModal = true"> <view class="navItem" style="border: none;" v-if="userInfo.phone" @click="showLogoutModal = true">
<view class="navTitle"> <view class="navTitle">
退出登录 退出登录
@ -189,6 +189,11 @@
<pop-up-modal v-if="showLogoutModal" content="确定要退出登录吗?" @cancel="showLogoutModal = false" @confirm="logout" /> <pop-up-modal v-if="showLogoutModal" content="确定要退出登录吗?" @cancel="showLogoutModal = false" @confirm="logout" />
<contact-modal v-if="showContactModal" :data="configInfo" @close="showContactModal = false" /> <contact-modal v-if="showContactModal" :data="configInfo" @close="showContactModal = false" />
<!-- 可拖动联系客服组件 -->
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
<WeChatCopyModal ref="wechatCopyModal" />
</view> </view>
</template> </template>
@ -196,6 +201,8 @@
import CommonCell from "@/components/CommonCell.vue"; import CommonCell from "@/components/CommonCell.vue";
import PopUpModal from "../../../components/PopUpModal.vue"; import PopUpModal from "../../../components/PopUpModal.vue";
import ContactModal from "@/components/ContactModal.vue"; import ContactModal from "@/components/ContactModal.vue";
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
import { import {
loginOut, loginOut,
getUserInfo, getUserInfo,
@ -211,6 +218,8 @@
CommonCell, CommonCell,
PopUpModal, PopUpModal,
ContactModal, ContactModal,
WeChatCopyModal,
DraggableContact,
}, },
data() { data() {
return { return {
@ -308,6 +317,15 @@
// this.getConfig(); // this.getConfig();
// this.showContactModal = true; // this.showContactModal = true;
}, },
// 跳转微信客服 - 使用自定义弹窗(与商城页面一致)
handleContactClick() {
if (this.$refs.wechatCopyModal) {
this.$refs.wechatCopyModal.show({
title: '请添加客服号',
weChatCode: 'Wagoo2025'
});
}
},
}, },
}; };
</script> </script>
@ -472,6 +490,8 @@
} }
} }
/* 可拖动联系客服组件无需额外样式 */
.arrowImg { .arrowImg {
width: 11rpx; width: 11rpx;
height: 18rpx; height: 18rpx;

View File

@ -47,9 +47,6 @@
<text class="goods-price">¥{{ item.product_price || item.goods_price }}</text> <text class="goods-price">¥{{ item.product_price || item.goods_price }}</text>
</view> </view>
<view class="goods-row-second"> <view class="goods-row-second">
<!-- <view class="goods-spec">
{{ item.shuxing_name || "" }}{{ item.shuxing_name && item.price_name ? ";" : "" }}{{ item.price_name || "" }}
</view> -->
<text class="goods-count">{{ item.number || 1 }}</text> <text class="goods-count">{{ item.number || 1 }}</text>
</view> </view>
</view> </view>
@ -81,15 +78,6 @@
</view> </view>
</view> </view>
<!-- <view class="flex-row-start info-cell pay-type">
<image class="pay-icon" src="./static/wx_pay.png" />
<view class="fs-30 app-fc-main pay-type-text"> 微信支付 </view>
<image
class="pay-select-icon"
src="@/static/images/cart_checked.png"
mode="widthFix"
/>
</view> -->
<view class="info-cell payment-method-cell"> <view class="info-cell payment-method-cell">
<view class="payment-item" @click.stop="selectOption1('1')"> <view class="payment-item" @click.stop="selectOption1('1')">
<view class="payment-left"> <view class="payment-left">
@ -104,8 +92,6 @@
<view class="payment-left"> <view class="payment-left">
<image class="payment-icon" src="@/static/images/wallet.png" mode="widthFix" /> <image class="payment-icon" src="@/static/images/wallet.png" mode="widthFix" />
<text class="payment-text">钱包支付</text> <text class="payment-text">钱包支付</text>
<!-- <text class="payment-text">钱包支付({{ walletBalance || '0.00' }})</text> -->
</view> </view>
<image class="payment-check" <image class="payment-check"
:src="selected4 ? require('@/static/images/cart_checked.png') : require('@/static/images/unchecked.png')" :src="selected4 ? require('@/static/images/cart_checked.png') : require('@/static/images/unchecked.png')"
@ -113,16 +99,8 @@
</view> </view>
</view> </view>
<!-- 右侧浮动联系客服按钮 --> <!-- 可拖动联系客服组件 -->
<view class="contact-float-btn" <DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
:style="{ right: contactBtnRight + 'rpx', bottom: contactBtnBottom +100 +'rpx' }"
@touchstart="onContactBtnTouchStart" @touchmove="onContactBtnTouchMove" @touchend="onContactBtnTouchEnd"
@click="handleContactBtnClick">
<image class="contact-icon" :src="`${imgPrefix}supportStaff.png`" />
<view class="contact-btn fs-20">
联系客服
</view>
</view>
<view class="place-view"></view> <view class="place-view"></view>
@ -137,7 +115,6 @@
<select-modal v-if="showSliverModal" title="请选择配送方式" @close="showSliverModal = false"> <select-modal v-if="showSliverModal" title="请选择配送方式" @close="showSliverModal = false">
<view class="sliver-content"> <view class="sliver-content">
<!-- :class="{ disabled: !serviceOrderList.length && item.id === 2 }" -->
<view class="flex-row-between sliver-item" v-for="item in sliverTypeList" :key="item.id" <view class="flex-row-between sliver-item" v-for="item in sliverTypeList" :key="item.id"
@click="changeSliverType(item)"> @click="changeSliverType(item)">
<text class="fs-32 app-fc-main">{{ item.name }}</text> <text class="fs-32 app-fc-main">{{ item.name }}</text>
@ -164,6 +141,7 @@
import SelectModal from "@/components/select-modal.vue"; import SelectModal from "@/components/select-modal.vue";
import GoodInfoModal from "./components/GoodInfoModal.vue"; import GoodInfoModal from "./components/GoodInfoModal.vue";
import RechargeCouponModal from "@/components/coupon/RechargeCouponModal.vue"; import RechargeCouponModal from "@/components/coupon/RechargeCouponModal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
import { import {
getCouponListByOrderPrice, getCouponListByOrderPrice,
getOwnCouponData getOwnCouponData
@ -208,6 +186,7 @@
SelectModal, SelectModal,
GoodInfoModal, GoodInfoModal,
RechargeCouponModal, RechargeCouponModal,
DraggableContact,
}, },
data() { data() {
return { return {
@ -223,7 +202,7 @@
showCouponModal: false, showCouponModal: false,
couponList: [], couponList: [],
serviceOrderList: [], serviceOrderList: [],
useCouponInfo: null, // 当前使用的优惠券信息 useCouponInfo: null,
petOrderId: "", petOrderId: "",
petOrderAddressId: "", petOrderAddressId: "",
orderPrice: 0, orderPrice: 0,
@ -231,21 +210,13 @@
selected1: false, selected1: false,
selected2: false, selected2: false,
selected3: false, selected3: false,
selected4: true, // 默认选中钱包支付 selected4: true,
recharge: true, recharge: true,
record: false, record: false,
walletBalance: "1000.00", // 钱包余额,实际应该从接口获取 walletBalance: "1000.00",
imgPrefix, imgPrefix,
WeChat: undefined, WeChat: undefined,
wallet: "2", // 默认选中钱包支付 wallet: "2",
// 联系客服按钮拖拽相关
contactBtnRight: 0, // 默认右侧距离始终为0
contactBtnBottom: 0, // 默认底部距离,需要计算
isDragging: false, // 是否正在拖拽
touchStartX: 0, // 触摸开始X坐标
touchStartY: 0, // 触摸开始Y坐标
initialRight: 0, // 初始右侧距离
initialBottom: 0, // 初始底部距离
}; };
}, },
computed: { computed: {
@ -263,10 +234,6 @@
}, },
}, },
onLoad(option) { onLoad(option) {
// console.log(option,'??')
// console.log(JSON.parse(option.petList))
// console.log( JSON.parse(),'?')
const { const {
type, type,
petOrderId = "", petOrderId = "",
@ -276,15 +243,6 @@
this.petOrderId = petOrderId; this.petOrderId = petOrderId;
this.petOrderAddressId = petOrderAddressId; this.petOrderAddressId = petOrderAddressId;
// 初始化联系客服按钮位置
const systemInfo = uni.getSystemInfoSync();
const windowHeight = systemInfo.windowHeight;
// 计算底部距离calc(35vh - 130rpx - 48rpx) 转换为rpx
// 35vh = windowHeight * 0.35转换为rpx (750rpx = windowHeight px)
const vh35InRpx = (windowHeight * 0.35 / windowHeight) * 750;
this.contactBtnBottom = vh35InRpx - 130 - 48;
// 随车购收货地址id
if (petOrderAddressId) { if (petOrderAddressId) {
getAddressInfo(petOrderAddressId).then((res) => { getAddressInfo(petOrderAddressId).then((res) => {
this.addressInfo = { this.addressInfo = {
@ -306,14 +264,9 @@
this.orderPrice = +price.toFixed(2); this.orderPrice = +price.toFixed(2);
this.confirmPrice = +(this.orderPrice - this.couponFee).toFixed(2); this.confirmPrice = +(this.orderPrice - this.couponFee).toFixed(2);
this.getCouponList(); this.getCouponList();
// this.type === "cart" ? this.creatCartOrder(true) : this.createOrder(true);
}); });
// 查询服务订单
// this.getServiceOrderList();
}, },
methods: { methods: {
// 设置默认使用优惠券
setDefaultCoupon() { setDefaultCoupon() {
let fee = 0; let fee = 0;
let coupon; let coupon;
@ -326,43 +279,28 @@
} }
}); });
this.useCouponInfo = coupon; this.useCouponInfo = coupon;
// 购物车进来的需要预下单
if (coupon?.coupon_id) { if (coupon?.coupon_id) {
this.type === "cart" ? this.type === "cart" ?
this.creatCartOrder(true) : this.creatCartOrder(true) :
this.createOrder(true); this.createOrder(true);
} }
}, },
// 已支付服务订单
getServiceOrderList() { getServiceOrderList() {
getOrderList(1, 1, ORDER_STATUS_COMPLETED).then((res) => { getOrderList(1, 1, ORDER_STATUS_COMPLETED).then((res) => {
this.serviceOrderList = res?.info || []; this.serviceOrderList = res?.info || [];
}); });
}, },
// 获取已领取待使用的优惠券列表
getCouponList() { getCouponList() {
getCouponListByOrderPrice(this.orderPrice, COUPON_TYPE_GOODS).then((res) => { getCouponListByOrderPrice(this.orderPrice, COUPON_TYPE_GOODS).then((res) => {
this.couponList = res?.info || []; this.couponList = res?.info || [];
// 若接口比与下单接口慢,需要再设置下默认优惠券
if (!this.useCouponInfo) { if (!this.useCouponInfo) {
this.setDefaultCoupon(); this.setDefaultCoupon();
} }
}); });
}, },
// 创建订单
createOrder(isPrePay) { createOrder(isPrePay) {
// console.log(this.addressInfo,'--==?')
// const {
// goods_id,
// price_id,
// number,
// shuxing_name
// } = this.orderData?.[0];
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!isPrePay) { if (!isPrePay) {
// 快递配送/随车订单必填收货地址
// if (!this.petOrderId) {
if (!this.addressInfo?.id) { if (!this.addressInfo?.id) {
uni.showToast({ uni.showToast({
title: "请选择收货地址", title: "请选择收货地址",
@ -377,7 +315,6 @@
}); });
return reject(); return reject();
} }
// }
uni.showLoading({ uni.showLoading({
title: "处理中", title: "处理中",
mask: true, mask: true,
@ -397,16 +334,16 @@
createCartOrder({ createCartOrder({
type:this.sliverInfo.id, type:this.sliverInfo.id,
original_price:this.orderData[0].original_price, //付款金额 original_price:this.orderData[0].original_price,
actual_price:this.payPrice + '', //付款金额 actual_price:this.payPrice + '',
reduction_amount:'0', reduction_amount:'0',
pay_amount:this.payPrice +'', //付款金额 pay_amount:this.payPrice +'',
pay_type: Number(this.WeChat) || Number(this.wallet), //微信和钱包type pay_type: Number(this.WeChat) || Number(this.wallet),
address_id:this.addressInfo.id, //地址id address_id:this.addressInfo.id,
address:this.addressInfo.full_address, //地址 address:this.addressInfo.full_address,
name:this.addressInfo.recipient_name, name:this.addressInfo.recipient_name,
phone:this.addressInfo.phone, phone:this.addressInfo.phone,
note:'', //备注 note:'',
items:item items:item
}) })
.then((res) => { .then((res) => {
@ -415,7 +352,6 @@
this.orderPrice = +(res?.info?.price || 0).toFixed(2); this.orderPrice = +(res?.info?.price || 0).toFixed(2);
!this.useCouponInfo && this.setDefaultCoupon(); !this.useCouponInfo && this.setDefaultCoupon();
} else { } else {
if (this.WeChat == 1) { if (this.WeChat == 1) {
this.pay(res?.data); this.pay(res?.data);
} else if (this.wallet == 2) { } else if (this.wallet == 2) {
@ -440,7 +376,6 @@
mask: true, mask: true,
}); });
const value = (this.$store.state && this.$store.state.user && this.$store.state.user.userInfo) || {}; const value = (this.$store.state && this.$store.state.user && this.$store.state.user.userInfo) || {};
// console.log(this.selectService,'---')
const data = { const data = {
wallet_id: value.wallet_id, wallet_id: value.wallet_id,
total_fee: this.payPrice, total_fee: this.payPrice,
@ -457,18 +392,16 @@
uni.requestSubscribeMessage({ uni.requestSubscribeMessage({
tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE', tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE',
'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0' 'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'
], // TEMPLATE_ID替换为选用的模版id ],
success(res) { success(res) {
uni.hideLoading() uni.hideLoading()
if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] === 'accept') { if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] === 'accept') {
// setSubscribeStatus(true, '已订阅')
uni.showToast({ uni.showToast({
title: '订阅成功', title: '订阅成功',
icon: 'success', icon: 'success',
}) })
} }
if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] === 'accept') { if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] === 'accept') {
// setSubscribeStatus(true, '已订阅')
uni.showToast({ uni.showToast({
title: '订阅成功', title: '订阅成功',
icon: 'success', icon: 'success',
@ -482,7 +415,6 @@
}) })
}, },
complete: () => { complete: () => {
// isSubscribing = false
}, },
}) })
if (this.petOrderId) { if (this.petOrderId) {
@ -502,12 +434,9 @@
} }
}); });
}, },
// 创建购物车订单
creatCartOrder(isPrePay) { creatCartOrder(isPrePay) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!isPrePay) { if (!isPrePay) {
// console.log(this.addressInfo,'--=!')
// 快递配送/随车订单必填收货地址
if (!this.petOrderId) { if (!this.petOrderId) {
if (!this.addressInfo?.id) { if (!this.addressInfo?.id) {
uni.showToast({ uni.showToast({
@ -529,21 +458,19 @@
mask: true, mask: true,
}); });
} }
// console.log(this.orderData,'--=')
// console.log(this.sliverInfo,'==--==')
createCartOrder({ createCartOrder({
type:this.sliverInfo.id, type:this.sliverInfo.id,
original_price:this.orderData[0].original_price, //付款金额 original_price:this.orderData[0].original_price,
actual_price:this.payPrice + '', //付款金额 actual_price:this.payPrice + '',
reduction_amount:'0', reduction_amount:'0',
pay_amount:this.payPrice + '', //付款金额 pay_amount:this.payPrice + '',
pay_type: Number(this.WeChat) || Number(this.wallet), //微信和钱包type pay_type: Number(this.WeChat) || Number(this.wallet),
address_id:this.addressInfo.id, //地址id address_id:this.addressInfo.id,
address:this.addressInfo.full_address, //地址 address:this.addressInfo.full_address,
name:this.addressInfo.recipient_name, name:this.addressInfo.recipient_name,
phone:this.addressInfo.phone, phone:this.addressInfo.phone,
note:'', //备注 note:'',
items:this.orderData items:this.orderData
}) })
.then((res) => { .then((res) => {
@ -565,7 +492,6 @@
}); });
}); });
}, },
// 支付订单
pay(orderId) { pay(orderId) {
payOrder({ payOrder({
type:4, type:4,
@ -590,12 +516,11 @@
uni.requestSubscribeMessage({ uni.requestSubscribeMessage({
tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE', tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE',
'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0' 'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'
], // TEMPLATE_ID替换为选用的模版id ],
success(res) { success(res) {
uni.hideLoading() uni.hideLoading()
if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] === if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] ===
'accept') { 'accept') {
// setSubscribeStatus(true, '已订阅')
uni.showToast({ uni.showToast({
title: '订阅成功', title: '订阅成功',
icon: 'success', icon: 'success',
@ -603,7 +528,6 @@
} }
if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] === if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] ===
'accept') { 'accept') {
// setSubscribeStatus(true, '已订阅')
uni.showToast({ uni.showToast({
title: '订阅成功', title: '订阅成功',
icon: 'success', icon: 'success',
@ -617,7 +541,6 @@
}) })
}, },
complete: () => { complete: () => {
// isSubscribing = false
}, },
}) })
@ -670,7 +593,6 @@
this.selected3 = false; this.selected3 = false;
this.selected4 = true; this.selected4 = true;
}, },
// 跳转至宠物订单随车购入口
jumpToPetOrder() { jumpToPetOrder() {
const pages = getCurrentPages(); const pages = getCurrentPages();
const detailsIndex = pages.findIndex((v) => const detailsIndex = pages.findIndex((v) =>
@ -725,7 +647,6 @@
const oldCoupon = { const oldCoupon = {
...this.useCouponInfo ...this.useCouponInfo
}; };
// 购物车进来的需要预下单
if (data.coupon_id) { if (data.coupon_id) {
this.useCouponInfo = { this.useCouponInfo = {
...data ...data
@ -746,60 +667,7 @@
} }
}, },
jumpToWeChat, jumpToWeChat,
// 联系客服按钮触摸开始
onContactBtnTouchStart(e) {
this.isDragging = false;
const touch = e.touches[0];
this.touchStartX = touch.clientX;
this.touchStartY = touch.clientY;
this.initialRight = this.contactBtnRight;
this.initialBottom = this.contactBtnBottom;
},
// 联系客服按钮触摸移动
onContactBtnTouchMove(e) {
const touch = e.touches[0];
const deltaX = touch.clientX - this.touchStartX;
const deltaY = touch.clientY - this.touchStartY;
// 如果移动距离超过10px认为是拖拽
if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) {
this.isDragging = true;
}
if (this.isDragging) {
const systemInfo = uni.getSystemInfoSync();
const windowHeight = systemInfo.windowHeight;
// 只处理上下移动将px转换为rpx
const deltaYRpx = (deltaY / windowHeight) * 750;
// 计算新位置只改变bottomright始终保持为0
// 向上移动时deltaY为负但bottom值应该减小
let newBottom = this.initialBottom - deltaYRpx;
// 限制在屏幕范围内
// 按钮高度约120rpx
const btnHeight = 120;
newBottom = Math.max(0, Math.min(newBottom, windowHeight * 2 - btnHeight));
// right始终保持为0
this.contactBtnRight = 0;
this.contactBtnBottom = newBottom;
}
},
// 联系客服按钮触摸结束
onContactBtnTouchEnd(e) {
// 松手后right重置为0
this.contactBtnRight = 0;
this.isDragging = false;
},
// 联系客服按钮点击
handleContactBtnClick() { handleContactBtnClick() {
// 如果正在拖拽,不触发点击事件
if (this.isDragging) {
return;
}
this.jumpToWeChat(); this.jumpToWeChat();
}, },
cancelOrder() { cancelOrder() {
@ -814,7 +682,6 @@
}); });
}, },
confirmPay() { confirmPay() {
// console.log(this.type, '??')
if (this.WeChat === undefined && this.wallet === undefined) { if (this.WeChat === undefined && this.wallet === undefined) {
uni.showToast({ uni.showToast({
title: '请选择支付方式', title: '请选择支付方式',
@ -825,13 +692,6 @@
this.type === "cart" ? this.creatCartOrder() : this.createOrder(); this.type === "cart" ? this.creatCartOrder() : this.createOrder();
}, },
changeSliverType(item) { changeSliverType(item) {
// if (item.id === 2 && !this.serviceOrderList?.length) {
// uni.showToast({
// title: "您当前不存在服务订单",
// icon: "none",
// });
// return;
// }
this.selectSliverInfo = { this.selectSliverInfo = {
...item ...item
}; };
@ -907,7 +767,7 @@
.address-details { .address-details {
font-size: 24rpx; font-size: 24rpx;
color: #999; color: #999;
margin-left: 36rpx; // 图标宽度24rpx + 间距12rpx margin-left: 36rpx;
} }
.arrow-icon { .arrow-icon {
@ -1220,26 +1080,6 @@
} }
} }
.contact-float-btn {
position: fixed;
text-align: center;
z-index: 100;
.contact-icon {
width: 66rpx;
height: 66rpx;
margin: auto;
}
.contact-btn {
color: #FFFFFF;
background-color: #FF19A0;
border-radius: 257px;
padding: 6rpx 8rpx;
transform: translateY(-8px);
}
}
.sliver-content { .sliver-content {
padding: 16rpx 0; padding: 16rpx 0;

View File

@ -257,16 +257,8 @@
/> />
</view> --> </view> -->
<!-- 右侧浮动联系客服按钮 --> <!-- 可拖动联系客服组件 -->
<view class="contact-float-btn" <DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
:style="{ right: contactBtnRight + 'rpx', bottom: contactBtnBottom + 100 + 'rpx' }"
@touchstart="onContactBtnTouchStart" @touchmove="onContactBtnTouchMove" @touchend="onContactBtnTouchEnd"
@click="handleContactBtnClick">
<image class="contact-icon" :src="`${imgPrefix}supportStaff.png`" />
<view class="contact-btn fs-20">
联系客服
</view>
</view>
<view class="place-view"></view> <view class="place-view"></view>
@ -364,6 +356,7 @@
import SuccessModal from "@/components/SuccessModal.vue"; import SuccessModal from "@/components/SuccessModal.vue";
import SliverInfo from "./components/SliverInfo.vue"; import SliverInfo from "./components/SliverInfo.vue";
import CallModal from "@/components/petOrder/call-modal.vue"; import CallModal from "@/components/petOrder/call-modal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
import { import {
walletTransaction, walletTransaction,
cancelPetOrderRefund, cancelPetOrderRefund,
@ -410,6 +403,7 @@
SuccessModal, SuccessModal,
SliverInfo, SliverInfo,
CallModal, CallModal,
DraggableContact,
}, },
data() { data() {
return { return {

View File

@ -42,15 +42,8 @@
<view v-if="elasticLayer" class="elastic-layer" /> <view v-if="elasticLayer" class="elastic-layer" />
</view> </view>
<!-- 右侧浮动联系客服按钮 --> <!-- 可拖动联系客服组件 -->
<view class="contact-float-btn" :style="{ right: contactBtnRight + 'rpx', bottom: contactBtnBottom + 'rpx' }" <DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
@touchstart="onContactBtnTouchStart" @touchmove="onContactBtnTouchMove" @touchend="onContactBtnTouchEnd"
@click="handleContactBtnClick">
<image class="contact-icon" :src="`${imgPrefix}supportStaff.png`" />
<view class="contact-btn fs-20">
联系客服
</view>
</view>
<view class="additional-bottom" v-if="additionalBom"> <view class="additional-bottom" v-if="additionalBom">
<view class="recharge-method"> <view class="recharge-method">
@ -85,6 +78,7 @@
@cancel="showCancelModal = false" /> @cancel="showCancelModal = false" />
<contact-modal v-if="showConcact" @close="showConcact = false" /> <contact-modal v-if="showConcact" @close="showConcact = false" />
<WeChatCopyModal ref="wechatCopyModal" />
<pop-up-modal v-if="showSliverModal" content="是否要确认收货?" @confirm="confirmReceiveOrder" <pop-up-modal v-if="showSliverModal" content="是否要确认收货?" @confirm="confirmReceiveOrder"
@cancel="showSliverModal = false" /> @cancel="showSliverModal = false" />
@ -105,6 +99,8 @@ import PopUpModal from "@/components/PopUpModal.vue";
import SuccessModal from "@/components/SuccessModal.vue"; import SuccessModal from "@/components/SuccessModal.vue";
import ContactModal from "@/components/ContactModal.vue"; import ContactModal from "@/components/ContactModal.vue";
import SliverInfo from "./components/SliverInfo.vue"; import SliverInfo from "./components/SliverInfo.vue";
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
import { walletTransaction, cancelPetOrderRefund, cancelPetOrderMall } from "../../../api/login"; import { walletTransaction, cancelPetOrderRefund, cancelPetOrderMall } from "../../../api/login";
@ -134,6 +130,8 @@ export default {
ContactModal, ContactModal,
SuccessModal, SuccessModal,
SliverInfo, SliverInfo,
WeChatCopyModal,
DraggableContact,
}, },
data() { data() {
return { return {
@ -163,14 +161,6 @@ export default {
p: 1, p: 1,
num: 10, num: 10,
imgPrefix, imgPrefix,
// 联系客服按钮拖拽相关
contactBtnRight: 0, // 默认右侧距离始终为0
contactBtnBottom: 0, // 默认底部距离,需要计算
isDragging: false, // 是否正在拖拽
touchStartX: 0, // 触摸开始X坐标
touchStartY: 0, // 触摸开始Y坐标
initialRight: 0, // 初始右侧距离
initialBottom: 0, // 初始底部距离
}; };
}, },
computed: { computed: {
@ -208,14 +198,6 @@ export default {
}, },
onLoad() { onLoad() {
this.reloadData(); this.reloadData();
// 初始化联系客服按钮位置
const systemInfo = uni.getSystemInfoSync();
const windowHeight = systemInfo.windowHeight;
// 计算底部距离calc(35vh - 130rpx - 48rpx) 转换为rpx
// 35vh = windowHeight * 0.35转换为rpx (750rpx = windowHeight px)
const vh35InRpx = (windowHeight * 0.35 / windowHeight) * 750;
this.contactBtnBottom = vh35InRpx - 130 - 48;
}, },
methods: { methods: {
jumpToWeChat, jumpToWeChat,
@ -416,10 +398,6 @@ export default {
}, },
// 申请售后 // 申请售后
afterSale() { afterSale() {
// 如果正在拖拽,不触发点击事件
if (this.isDragging) {
return;
}
this.jumpToWeChat(); this.jumpToWeChat();
}, },
// afterSale(data) { // afterSale(data) {
@ -471,61 +449,40 @@ export default {
this.showCancelModal = true; this.showCancelModal = true;
this.orderInfo = data; this.orderInfo = data;
}, },
// 联系客服按钮触摸开始 // 联系客服按钮点击 - 使用自定义弹窗(与首页在线客服功能一致)
onContactBtnTouchStart(e) {
this.isDragging = false;
const touch = e.touches[0];
this.touchStartX = touch.clientX;
this.touchStartY = touch.clientY;
this.initialRight = this.contactBtnRight;
this.initialBottom = this.contactBtnBottom;
},
// 联系客服按钮触摸移动
onContactBtnTouchMove(e) {
const touch = e.touches[0];
const deltaX = touch.clientX - this.touchStartX;
const deltaY = touch.clientY - this.touchStartY;
// 如果移动距离超过10px认为是拖拽
if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) {
this.isDragging = true;
}
if (this.isDragging) {
const systemInfo = uni.getSystemInfoSync();
const windowHeight = systemInfo.windowHeight;
// 只处理上下移动将px转换为rpx
const deltaYRpx = (deltaY / windowHeight) * 750;
// 计算新位置只改变bottomright始终保持为0
// 向上移动时deltaY为负但bottom值应该减小
let newBottom = this.initialBottom - deltaYRpx;
// 限制在屏幕范围内
// 按钮高度约120rpx
const btnHeight = 120;
newBottom = Math.max(0, Math.min(newBottom, windowHeight * 2 - btnHeight));
// right始终保持为0
this.contactBtnRight = 0;
this.contactBtnBottom = newBottom;
}
},
// 联系客服按钮触摸结束
onContactBtnTouchEnd(e) {
// 松手后right重置为0
this.contactBtnRight = 0;
this.isDragging = false;
},
// 联系客服按钮点击
handleContactBtnClick() { handleContactBtnClick() {
// 如果正在拖拽,不触发点击事件 console.log('[list.vue] handleContactBtnClick called')
if (this.isDragging) { console.log('[list.vue] wechatCopyModal ref:', this.$refs.wechatCopyModal)
return; if (this.$refs.wechatCopyModal) {
this.$refs.wechatCopyModal.show({
title: '请添加客服号',
weChatCode: 'Wagoo2025'
});
console.log('[list.vue] wechatCopyModal.show called')
} else {
console.error('[list.vue] wechatCopyModal ref is null')
// 降级方案:直接显示系统弹窗
uni.showModal({
title: '提示',
content: '请添加客服号Wagoo2025',
confirmText: '复制微信号',
showCancel: true,
cancelText: '取消',
success: (res) => {
if (res.confirm) {
uni.setClipboardData({
data: 'Wagoo2025',
success: () => {
uni.showToast({
title: '已复制微信号',
icon: 'success'
})
}
})
}
}
})
} }
this.jumpToWeChat();
}, },
}, },
}; };
@ -673,24 +630,6 @@ export default {
} }
} }
.contact-float-btn { /* 可拖动联系客服组件无需额外样式 */
position: fixed;
text-align: center;
z-index: 100;
.contact-icon {
width: 66rpx;
height: 66rpx;
margin: auto;
}
.contact-btn {
color: #FFFFFF;
background-color: #FF19A0;
border-radius: 257px;
padding: 6rpx 8rpx;
transform: translateY(-8px);
}
}
} }
</style> </style>

View File

@ -65,6 +65,11 @@
@confirm="confirmCancelOrder" @confirm="confirmCancelOrder"
@cancel="isShowCancelModal = false" @cancel="isShowCancelModal = false"
/> />
<!-- 可拖动联系客服组件 -->
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
<WeChatCopyModal ref="wechatCopyModal" />
</view> </view>
</template> </template>
@ -76,6 +81,8 @@ import { showOrderStatus } from "@/pageHome/constants/home";
import { getOrderList, cancelHomeOrder, cancelTrainingOrder } from "@/api/order"; import { getOrderList, cancelHomeOrder, cancelTrainingOrder } from "@/api/order";
import { cancelPetOrderRefund } from "@/api/login"; import { cancelPetOrderRefund } from "@/api/login";
import PopUpModal from "@/components/PopUpModal.vue"; import PopUpModal from "@/components/PopUpModal.vue";
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
export default { export default {
name: 'index', name: 'index',
@ -83,7 +90,9 @@ export default {
Reservation, Reservation,
HomeServiceOrderItem, HomeServiceOrderItem,
HomeTrainingOrderItem, HomeTrainingOrderItem,
PopUpModal PopUpModal,
WeChatCopyModal,
DraggableContact
}, },
data() { data() {
return { return {
@ -305,6 +314,15 @@ export default {
icon: 'none' icon: 'none'
}); });
}, },
// 跳转微信客服 - 使用自定义弹窗(与首页在线客服功能一致)
handleContactClick() {
if (this.$refs.wechatCopyModal) {
this.$refs.wechatCopyModal.show({
title: '请添加客服号',
weChatCode: 'Wagoo2025'
});
}
},
handleGotoEvaluate(orderInfo) { handleGotoEvaluate(orderInfo) {
// 处理去评价 // 处理去评价
const orderId = orderInfo.order_id || orderInfo.home_training_order?.order_id; const orderId = orderInfo.order_id || orderInfo.home_training_order?.order_id;
@ -403,4 +421,6 @@ export default {
right: 0; right: 0;
padding-bottom: 32rpx; padding-bottom: 32rpx;
} }
/* 可拖动联系客服组件无需额外样式 */
</style> </style>

View File

@ -110,18 +110,15 @@
{{ cartShowCount }} {{ cartShowCount }}
</view> </view>
<view class="contact-icon-view"> <!-- 可拖动联系客服组件 -->
<image class="contact-icon" :src="`${imgPrefix}supportStaff.png`" @click="jumpToWeChat" /> <DraggableContact ref="draggableContact" :onClick="handleContactClick" />
<view class="contact-btn fs-20">
联系客服
</view>
</view>
<add-goods-modal v-if="showModal" :data="addGoodInfo" optText="加入购物车" @change="(val) => (showModal = val)" <add-goods-modal v-if="showModal" :data="addGoodInfo" optText="加入购物车" @change="(val) => (showModal = val)"
@optAction="optAction" /> @optAction="optAction" />
<coupon-modal v-if="showCouponModal" :couponList="couponList" @close="onCouponModalClose" <coupon-modal v-if="showCouponModal" :couponList="couponList" @close="onCouponModalClose"
@getCoupon="getCoupon" /> @getCoupon="getCoupon" />
<contact-modal v-if="showContactModal" @close="showContactModal = false" /> <contact-modal v-if="showContactModal" @close="showContactModal = false" />
<WeChatCopyModal ref="wechatCopyModal" />
</view> </view>
</template> </template>
@ -134,6 +131,8 @@
import AddGoodsModal from "@/components/goods/AddGoodsModal.vue"; import AddGoodsModal from "@/components/goods/AddGoodsModal.vue";
import CouponModal from "./components/CouponModal.vue"; import CouponModal from "./components/CouponModal.vue";
import ContactModal from "@/components/ContactModal.vue"; import ContactModal from "@/components/ContactModal.vue";
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
import DraggableContact from "@/components/DraggableContact.vue";
import { import {
getGoodsClassify, getGoodsClassify,
@ -159,6 +158,8 @@
AddGoodsModal, AddGoodsModal,
CouponModal, CouponModal,
ContactModal, ContactModal,
WeChatCopyModal,
DraggableContact,
}, },
data() { data() {
const systemInfo = uni.getSystemInfoSync(); const systemInfo = uni.getSystemInfoSync();
@ -237,6 +238,41 @@
// this.getCouponList(); // this.getCouponList();
}, },
methods: { methods: {
// 跳转微信客服 - 使用自定义弹窗(与首页在线客服功能一致)
handleContactClick() {
console.log('[shop.vue] handleContactClick called')
console.log('[shop.vue] $refs.wechatCopyModal:', this.$refs.wechatCopyModal)
if (this.$refs.wechatCopyModal && this.$refs.wechatCopyModal.show) {
this.$refs.wechatCopyModal.show({
title: '请添加客服号',
weChatCode: 'Wagoo2025'
});
console.log('[shop.vue] wechatCopyModal.show called')
} else {
console.error('[shop.vue] wechatCopyModal not available, using fallback')
// 降级方案:直接显示系统弹窗
uni.showModal({
title: '提示',
content: '请添加客服号Wagoo2025',
confirmText: '复制微信号',
showCancel: true,
cancelText: '取消',
success: (res) => {
if (res.confirm) {
uni.setClipboardData({
data: 'Wagoo2025',
success: () => {
uni.showToast({
title: '已复制微信号',
icon: 'success'
})
}
})
}
}
})
}
},
jumpToWeChat, jumpToWeChat,
onShowFun() { onShowFun() {
this.initData(); this.initData();
@ -710,26 +746,7 @@
} }
} }
.contact-icon-view { /* 可拖动联系客服组件无需额外样式 */
position: fixed;
bottom: calc(35vh - 130rpx - 48rpx);
right: 20rpx;
text-align: center;
.contact-icon {
width: 66rpx;
height: 66rpx;
margin: auto;
}
.contact-btn {
color: #FFFFFF;
background-color: #FF19A0;
border-radius: 257px;
padding: 6rpx 8rpx;
transform: translateY(-8px);
}
}
.cart-count { .cart-count {

View File

@ -31,10 +31,32 @@ export default {
this.getDetail(this.id); this.getDetail(this.id);
}, },
methods: { methods: {
// 清理格式错误的 HTML 属性
cleanHtml(html) {
if (!html) return '';
let cleaned = html;
// 移除格式错误的属性名(包含非法字符如 , = " 等)
// 匹配类似 times="" new="" roman",="" serif;"=" 这样的错误属性
cleaned = cleaned.replace(/\s+[a-zA-Z0-9_-]*\s*=\s*""\s*[a-zA-Z0-9_-]*\s*=\s*""\s*[^>]*?=\s*""/g, '');
// 移除残留的错误属性片段(包含 ="" 的)
cleaned = cleaned.replace(/\s+[^>\s]*=\s*""/g, '');
// 移除孤立的 ="" 片段
cleaned = cleaned.replace(/\s*=\s*""/g, '');
// 移除 <o:p></o:p> 标签Office 专有标签,小程序不支持)
cleaned = cleaned.replace(/<o:p[^>]*>[\s\S]*?<\/o:p>/g, '');
cleaned = cleaned.replace(/<o:p[^>]*\/?>/g, '');
return cleaned;
},
getDetail(id) { getDetail(id) {
getArticleDetail(id).then( getArticleDetail(id).then(
res => { res => {
this.content = res.data.content this.content = this.cleanHtml(res.data.content)
} }
) )
} }

View File

@ -90,19 +90,31 @@ export const getWeekDayName = (weekday) => {
return weekdayName[weekday]; return weekdayName[weekday];
}; };
// 跳转企微客服 /**
export const jumpToWeChat = () => { * 跳转在线客服 - 显示弹窗提示添加企业微信
wx.openCustomerServiceChat({ */
corpId: appConfig.qiWeId, // 企业id,必填 export const jumpToCustomerService = () => {
extInfo: { // 客服信息
url: appConfig.qiWeLink, // 客服链接
},
fail: (err) => {
console.log(err);
uni.showModal({ uni.showModal({
content: err || "跳转客服微信失败", title: "提示",
showCancel: false, content: "请添加客服号Wagoo2025",
confirmText: "复制微信号",
showCancel: true,
cancelText: "取消",
success: (res) => {
if (res.confirm) {
uni.setClipboardData({
data: "Wagoo2025",
success: () => {
uni.showToast({
title: "已复制微信号",
icon: "success"
}); });
} }
}) });
}
}
});
}; };
// 兼容旧版本,保留 jumpToWeChat 别名
export const jumpToWeChat = jumpToCustomerService;

View File

@ -20,6 +20,10 @@ module.exports = {
config.plugin('ignore') config.plugin('ignore')
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)); //忽略/moment/locale下的所有文件 .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)); //忽略/moment/locale下的所有文件
// 忽略 qiun-data-charts 中非小程序平台的文件,减小体积
config.plugin('ignore-qiun-echarts')
.use(new webpack.IgnorePlugin(/echarts\.min\.js$/, /qiun-data-charts[\\/]static/));
// 生产环境优化 // 生产环境优化
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
// 代码压缩 - 移除 console 和 debugger // 代码压缩 - 移除 console 和 debugger