提交
This commit is contained in:
6831
package-lock.json
generated
6831
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,9 @@
|
||||
"core-js": "^3.6.5",
|
||||
"crypto-js": "^4.2.0",
|
||||
"flyio": "^0.6.2",
|
||||
"marked": "^4.3.0",
|
||||
"moment": "^2.29.3",
|
||||
"mp-html": "^2.5.2",
|
||||
"node-sass": "4.14.1",
|
||||
"sass": "1.26.2",
|
||||
"sass-loader": "8.0.2",
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -304,5 +304,23 @@ export const HOMETRAINING_ORDERS_CANCEL = '/hometraining/orders/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'
|
||||
|
||||
|
||||
|
||||
|
||||
188
src/components/ContactPopupModal.vue
Normal file
188
src/components/ContactPopupModal.vue
Normal 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>
|
||||
159
src/components/DraggableContact.vue
Normal file
159
src/components/DraggableContact.vue
Normal 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>
|
||||
208
src/components/WeChatCopyModal.vue
Normal file
208
src/components/WeChatCopyModal.vue
Normal 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>
|
||||
343
src/components/ai-advisor/AiAdvisorView.vue
Normal file
343
src/components/ai-advisor/AiAdvisorView.vue
Normal 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>
|
||||
@ -3,11 +3,8 @@ export default {
|
||||
appName: "Wagoo",
|
||||
appShareName: "Wagoo",
|
||||
appId: "wx00e2dcdc7c02b23a",
|
||||
// apiBaseUrl: 'https://api.wagoo.cc', // 服务端生产地址
|
||||
apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址
|
||||
// apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
|
||||
|
||||
|
||||
// apiBaseUrl: "https://api.wagoo.me/api/v1", // 服务端测试地址
|
||||
apiBaseUrl: "https://api.wagoo.pet/api/v1", // 服务端生产地址
|
||||
// apiBaseUrl: "http:192.168.30.79", //本地接口
|
||||
tencentMapKey: "WSBBZ-7OXK4-46QUC-KFB7B-4N3W7-M2BXM",
|
||||
tencentSecret: "vb7D0PGj7xUvmOLuJz2Jd7ykTMpjiWRJ",
|
||||
|
||||
1376
src/pageHome/ai-advisor/chat.vue
Normal file
1376
src/pageHome/ai-advisor/chat.vue
Normal file
File diff suppressed because it is too large
Load Diff
22
src/pageHome/ai-advisor/index.vue
Normal file
22
src/pageHome/ai-advisor/index.vue
Normal 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>
|
||||
@ -322,14 +322,14 @@
|
||||
<text v-else class="money">¥{{ toAmount }}</text> -->
|
||||
<view class="handle-info-cell">
|
||||
<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-fc1">{{ toAmount3.toFixed(2) || "0.00" }}</text>
|
||||
<text class="app-fc1">{{ Math.max(0, toAmount3).toFixed(2) || "0.00" }}</text>
|
||||
</view>
|
||||
<view v-else>
|
||||
<text class="app-fc-main fs-30">¥</text>
|
||||
<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>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
{
|
||||
"easycom": {},
|
||||
"pages": [
|
||||
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/client/index/index",
|
||||
"style": {
|
||||
@ -219,6 +218,18 @@
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单详情"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "ai-advisor/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "ai-advisor/chat",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<view class="home-page">
|
||||
<!-- 微信复制弹窗 -->
|
||||
<WeChatCopyModal ref="wechatCopyModal" />
|
||||
|
||||
<scroll-view class="homeContainer" scroll-y :show-scrollbar="false" :enhanced="true">
|
||||
<view class="swiperWrapper">
|
||||
<swiper indicator-dots="true" autoplay="true" interval="3000" duration="500" circular="true"
|
||||
@ -9,12 +12,9 @@
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<view class="userInfoWrapper">
|
||||
<view class="userInfo" @click="handleUserInfo">
|
||||
<image class="avatar-img"
|
||||
:src="userInfo.avatar ? userInfo.avatar : `${imgPrefix}defaultHeadImg.png`"
|
||||
mode="aspectFill" />
|
||||
<view class="userContent">
|
||||
<view class="userInfoWrapper">
|
||||
<view class="userInfo" @click="handleUserInfo">
|
||||
<view class="userContent">
|
||||
<view class="userName">
|
||||
{{ userInfo.username ? userInfo.username : "嗨,你好呀" }}
|
||||
</view>
|
||||
@ -62,12 +62,12 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="line" />
|
||||
<view class="itemWrapper" @click="toDogTraining">
|
||||
<text class="titlWrapper">狗狗训练</text>
|
||||
<view class="content">上门服务</view>
|
||||
<view class="tips">上门训犬、寄养、喂猫、遛狗</view>
|
||||
<view class="itemWrapper" @click="toPublicBenefit" >
|
||||
<text class="titlWrapper">关爱宠物,传递恩情</text>
|
||||
<view class="content">公益助理</view>
|
||||
<view class="tips">帮我找个家</view>
|
||||
<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>
|
||||
@ -99,12 +99,12 @@
|
||||
</view>
|
||||
|
||||
<view class="thirdMenu">
|
||||
<view class="itemWrapper" @click="toPublicBenefit">
|
||||
<view class="itemWrapper" @click="toDogTraining">
|
||||
<view>
|
||||
<view class="title">公益助力</view>
|
||||
<view class="tips">帮我找个家</view>
|
||||
<view class="title">上门服务</view>
|
||||
<view class="tips">邀请好友得好礼</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 class="itemWrapper" @click="toJoin">
|
||||
<view>
|
||||
@ -136,15 +136,18 @@
|
||||
<script>
|
||||
import {
|
||||
imgPrefix,
|
||||
jumpToWeChat,
|
||||
showLoginConfirmModal
|
||||
} from "@/utils/common";
|
||||
import {
|
||||
userWllet
|
||||
} from "../../../api/login";
|
||||
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
|
||||
|
||||
export default {
|
||||
name: "HomePage",
|
||||
components: {
|
||||
WeChatCopyModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgPrefix,
|
||||
@ -245,9 +248,15 @@ export default {
|
||||
});
|
||||
},
|
||||
toDogTraining() {
|
||||
uni.navigateTo({
|
||||
url: '/pageHome/service/index'
|
||||
});
|
||||
uni.showToast({
|
||||
title: '暂未开放',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return;
|
||||
// uni.navigateTo({
|
||||
// url: '/pageHome/service/index'
|
||||
// });
|
||||
},
|
||||
// 我的钱包
|
||||
buyService() {
|
||||
@ -343,10 +352,14 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转微信客服 - 使用自定义弹窗
|
||||
jumpToWeChat() {
|
||||
this.checkTokenAndExecute(() => {
|
||||
jumpToWeChat();
|
||||
});
|
||||
if (this.$refs.wechatCopyModal) {
|
||||
this.$refs.wechatCopyModal.show({
|
||||
title: '请添加客服号',
|
||||
weChatCode: 'Wagoo2025'
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -358,18 +371,12 @@ export default {
|
||||
background-color: #ffecf3;
|
||||
}
|
||||
|
||||
.homeContainer {
|
||||
height: calc(100vh - #{$app_tabbar_height + 36});
|
||||
background-color: #ffecf3;
|
||||
overflow: scroll;
|
||||
.homeContainer {
|
||||
height: calc(100vh - #{$app_tabbar_height + 36});
|
||||
background-color: #ffecf3;
|
||||
overflow: scroll;
|
||||
|
||||
.avatar-img {
|
||||
width: 92rpx;
|
||||
height: 92rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.menu-img-lg {
|
||||
.menu-img-lg {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
@ -383,7 +390,7 @@ export default {
|
||||
.third-icon,
|
||||
.service-icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.service-icon {
|
||||
@ -735,6 +742,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.flexClass {
|
||||
|
||||
@ -160,24 +160,24 @@
|
||||
</view>
|
||||
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
|
||||
</view>
|
||||
<view class="navItem" @click="jumpTo(`/pages/client/mine/help`)">
|
||||
<!-- <view class="navItem" @click="jumpTo(`/pages/client/mine/help`)">
|
||||
<view class="navTitle">
|
||||
使用帮助
|
||||
</view>
|
||||
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="navItem" @click="jumpTo('/pages/client/news/index')">
|
||||
<view class="navTitle">
|
||||
系统消息
|
||||
</view>
|
||||
<image class="navArrow" :src="`${imgPrefix}right-arrow.png`"></image>
|
||||
</view>
|
||||
<view class="navItem" @click="jumpTo(`/pages/client/mine/aboutus`)">
|
||||
<!-- <view class="navItem" @click="jumpTo(`/pages/client/mine/aboutus`)">
|
||||
<view class="navTitle">
|
||||
关于平台
|
||||
</view>
|
||||
<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="navTitle">
|
||||
退出登录
|
||||
@ -186,16 +186,23 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<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" />
|
||||
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
|
||||
|
||||
<WeChatCopyModal ref="wechatCopyModal" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonCell from "@/components/CommonCell.vue";
|
||||
import PopUpModal from "../../../components/PopUpModal.vue";
|
||||
import ContactModal from "@/components/ContactModal.vue";
|
||||
import CommonCell from "@/components/CommonCell.vue";
|
||||
import PopUpModal from "../../../components/PopUpModal.vue";
|
||||
import ContactModal from "@/components/ContactModal.vue";
|
||||
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
import {
|
||||
loginOut,
|
||||
getUserInfo,
|
||||
@ -207,10 +214,12 @@
|
||||
} from "@/utils/common";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
components: {
|
||||
CommonCell,
|
||||
PopUpModal,
|
||||
ContactModal,
|
||||
WeChatCopyModal,
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -303,11 +312,20 @@
|
||||
url: "/pages/client/auth/index",
|
||||
});
|
||||
},
|
||||
showContact() {
|
||||
showContact() {
|
||||
jumpToWeChat();
|
||||
// this.getConfig();
|
||||
// this.showContactModal = true;
|
||||
},
|
||||
// 跳转微信客服 - 使用自定义弹窗(与商城页面一致)
|
||||
handleContactClick() {
|
||||
if (this.$refs.wechatCopyModal) {
|
||||
this.$refs.wechatCopyModal.show({
|
||||
title: '请添加客服号',
|
||||
weChatCode: 'Wagoo2025'
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -452,7 +470,7 @@
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 26rpx;
|
||||
|
||||
.navItem {
|
||||
.navItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@ -472,6 +490,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 可拖动联系客服组件无需额外样式 */
|
||||
|
||||
.arrowImg {
|
||||
width: 11rpx;
|
||||
height: 18rpx;
|
||||
|
||||
@ -47,9 +47,6 @@
|
||||
<text class="goods-price">¥{{ item.product_price || item.goods_price }}</text>
|
||||
</view>
|
||||
<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>
|
||||
</view>
|
||||
</view>
|
||||
@ -81,15 +78,6 @@
|
||||
</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="payment-item" @click.stop="selectOption1('1')">
|
||||
<view class="payment-left">
|
||||
@ -104,8 +92,6 @@
|
||||
<view class="payment-left">
|
||||
<image class="payment-icon" src="@/static/images/wallet.png" mode="widthFix" />
|
||||
<text class="payment-text">钱包支付</text>
|
||||
<!-- <text class="payment-text">钱包支付(¥{{ walletBalance || '0.00' }})</text> -->
|
||||
|
||||
</view>
|
||||
<image class="payment-check"
|
||||
:src="selected4 ? require('@/static/images/cart_checked.png') : require('@/static/images/unchecked.png')"
|
||||
@ -113,16 +99,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 右侧浮动联系客服按钮 -->
|
||||
<view class="contact-float-btn"
|
||||
: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>
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
|
||||
|
||||
<view class="place-view"></view>
|
||||
|
||||
@ -137,7 +115,6 @@
|
||||
|
||||
<select-modal v-if="showSliverModal" title="请选择配送方式" @close="showSliverModal = false">
|
||||
<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"
|
||||
@click="changeSliverType(item)">
|
||||
<text class="fs-32 app-fc-main">{{ item.name }}</text>
|
||||
@ -164,6 +141,7 @@
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
import GoodInfoModal from "./components/GoodInfoModal.vue";
|
||||
import RechargeCouponModal from "@/components/coupon/RechargeCouponModal.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
import {
|
||||
getCouponListByOrderPrice,
|
||||
getOwnCouponData
|
||||
@ -208,6 +186,7 @@
|
||||
SelectModal,
|
||||
GoodInfoModal,
|
||||
RechargeCouponModal,
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -223,7 +202,7 @@
|
||||
showCouponModal: false,
|
||||
couponList: [],
|
||||
serviceOrderList: [],
|
||||
useCouponInfo: null, // 当前使用的优惠券信息
|
||||
useCouponInfo: null,
|
||||
petOrderId: "",
|
||||
petOrderAddressId: "",
|
||||
orderPrice: 0,
|
||||
@ -231,21 +210,13 @@
|
||||
selected1: false,
|
||||
selected2: false,
|
||||
selected3: false,
|
||||
selected4: true, // 默认选中钱包支付
|
||||
selected4: true,
|
||||
recharge: true,
|
||||
record: false,
|
||||
walletBalance: "1000.00", // 钱包余额,实际应该从接口获取
|
||||
walletBalance: "1000.00",
|
||||
imgPrefix,
|
||||
WeChat: undefined,
|
||||
wallet: "2", // 默认选中钱包支付
|
||||
// 联系客服按钮拖拽相关
|
||||
contactBtnRight: 0, // 默认右侧距离,始终为0
|
||||
contactBtnBottom: 0, // 默认底部距离,需要计算
|
||||
isDragging: false, // 是否正在拖拽
|
||||
touchStartX: 0, // 触摸开始X坐标
|
||||
touchStartY: 0, // 触摸开始Y坐标
|
||||
initialRight: 0, // 初始右侧距离
|
||||
initialBottom: 0, // 初始底部距离
|
||||
wallet: "2",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -263,10 +234,6 @@
|
||||
},
|
||||
},
|
||||
onLoad(option) {
|
||||
// console.log(option,'??')
|
||||
// console.log(JSON.parse(option.petList))
|
||||
|
||||
// console.log( JSON.parse(),'?')
|
||||
const {
|
||||
type,
|
||||
petOrderId = "",
|
||||
@ -276,15 +243,6 @@
|
||||
this.petOrderId = petOrderId;
|
||||
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) {
|
||||
getAddressInfo(petOrderAddressId).then((res) => {
|
||||
this.addressInfo = {
|
||||
@ -306,14 +264,9 @@
|
||||
this.orderPrice = +price.toFixed(2);
|
||||
this.confirmPrice = +(this.orderPrice - this.couponFee).toFixed(2);
|
||||
this.getCouponList();
|
||||
// this.type === "cart" ? this.creatCartOrder(true) : this.createOrder(true);
|
||||
});
|
||||
|
||||
// 查询服务订单
|
||||
// this.getServiceOrderList();
|
||||
},
|
||||
methods: {
|
||||
// 设置默认使用优惠券
|
||||
setDefaultCoupon() {
|
||||
let fee = 0;
|
||||
let coupon;
|
||||
@ -326,58 +279,42 @@
|
||||
}
|
||||
});
|
||||
this.useCouponInfo = coupon;
|
||||
// 购物车进来的需要预下单
|
||||
if (coupon?.coupon_id) {
|
||||
this.type === "cart" ?
|
||||
this.creatCartOrder(true) :
|
||||
this.createOrder(true);
|
||||
}
|
||||
},
|
||||
// 已支付服务订单
|
||||
getServiceOrderList() {
|
||||
getOrderList(1, 1, ORDER_STATUS_COMPLETED).then((res) => {
|
||||
this.serviceOrderList = res?.info || [];
|
||||
});
|
||||
},
|
||||
// 获取已领取待使用的优惠券列表
|
||||
getCouponList() {
|
||||
getCouponListByOrderPrice(this.orderPrice, COUPON_TYPE_GOODS).then((res) => {
|
||||
this.couponList = res?.info || [];
|
||||
// 若接口比与下单接口慢,需要再设置下默认优惠券
|
||||
if (!this.useCouponInfo) {
|
||||
this.setDefaultCoupon();
|
||||
}
|
||||
});
|
||||
},
|
||||
// 创建订单
|
||||
createOrder(isPrePay) {
|
||||
// console.log(this.addressInfo,'--==?')
|
||||
// const {
|
||||
// goods_id,
|
||||
// price_id,
|
||||
// number,
|
||||
// shuxing_name
|
||||
// } = this.orderData?.[0];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isPrePay) {
|
||||
// 快递配送/随车订单必填收货地址
|
||||
// if (!this.petOrderId) {
|
||||
if (!this.addressInfo?.id) {
|
||||
uni.showToast({
|
||||
title: "请选择收货地址",
|
||||
icon: "none",
|
||||
});
|
||||
return reject();
|
||||
}
|
||||
if (!this.sliverInfo?.id) {
|
||||
uni.showToast({
|
||||
title: "请选择配送方式",
|
||||
icon: "none",
|
||||
});
|
||||
return reject();
|
||||
}
|
||||
// }
|
||||
if (!this.addressInfo?.id) {
|
||||
uni.showToast({
|
||||
title: "请选择收货地址",
|
||||
icon: "none",
|
||||
});
|
||||
return reject();
|
||||
}
|
||||
if (!this.sliverInfo?.id) {
|
||||
uni.showToast({
|
||||
title: "请选择配送方式",
|
||||
icon: "none",
|
||||
});
|
||||
return reject();
|
||||
}
|
||||
uni.showLoading({
|
||||
title: "处理中",
|
||||
mask: true,
|
||||
@ -397,16 +334,16 @@
|
||||
|
||||
createCartOrder({
|
||||
type:this.sliverInfo.id,
|
||||
original_price:this.orderData[0].original_price, //付款金额
|
||||
actual_price:this.payPrice + '', //付款金额
|
||||
original_price:this.orderData[0].original_price,
|
||||
actual_price:this.payPrice + '',
|
||||
reduction_amount:'0',
|
||||
pay_amount:this.payPrice +'', //付款金额
|
||||
pay_type: Number(this.WeChat) || Number(this.wallet), //微信和钱包type
|
||||
address_id:this.addressInfo.id, //地址id
|
||||
address:this.addressInfo.full_address, //地址
|
||||
pay_amount:this.payPrice +'',
|
||||
pay_type: Number(this.WeChat) || Number(this.wallet),
|
||||
address_id:this.addressInfo.id,
|
||||
address:this.addressInfo.full_address,
|
||||
name:this.addressInfo.recipient_name,
|
||||
phone:this.addressInfo.phone,
|
||||
note:'', //备注
|
||||
note:'',
|
||||
items:item
|
||||
})
|
||||
.then((res) => {
|
||||
@ -415,7 +352,6 @@
|
||||
this.orderPrice = +(res?.info?.price || 0).toFixed(2);
|
||||
!this.useCouponInfo && this.setDefaultCoupon();
|
||||
} else {
|
||||
|
||||
if (this.WeChat == 1) {
|
||||
this.pay(res?.data);
|
||||
} else if (this.wallet == 2) {
|
||||
@ -440,7 +376,6 @@
|
||||
mask: true,
|
||||
});
|
||||
const value = (this.$store.state && this.$store.state.user && this.$store.state.user.userInfo) || {};
|
||||
// console.log(this.selectService,'---')
|
||||
const data = {
|
||||
wallet_id: value.wallet_id,
|
||||
total_fee: this.payPrice,
|
||||
@ -457,18 +392,16 @@
|
||||
uni.requestSubscribeMessage({
|
||||
tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE',
|
||||
'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'
|
||||
], // TEMPLATE_ID替换为选用的模版id
|
||||
],
|
||||
success(res) {
|
||||
uni.hideLoading()
|
||||
if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] === 'accept') {
|
||||
// setSubscribeStatus(true, '已订阅')
|
||||
uni.showToast({
|
||||
title: '订阅成功',
|
||||
icon: 'success',
|
||||
})
|
||||
}
|
||||
if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] === 'accept') {
|
||||
// setSubscribeStatus(true, '已订阅')
|
||||
uni.showToast({
|
||||
title: '订阅成功',
|
||||
icon: 'success',
|
||||
@ -482,7 +415,6 @@
|
||||
})
|
||||
},
|
||||
complete: () => {
|
||||
// isSubscribing = false
|
||||
},
|
||||
})
|
||||
if (this.petOrderId) {
|
||||
@ -502,12 +434,9 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
// 创建购物车订单
|
||||
creatCartOrder(isPrePay) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!isPrePay) {
|
||||
// console.log(this.addressInfo,'--=!')
|
||||
// 快递配送/随车订单必填收货地址
|
||||
if (!this.petOrderId) {
|
||||
if (!this.addressInfo?.id) {
|
||||
uni.showToast({
|
||||
@ -529,21 +458,19 @@
|
||||
mask: true,
|
||||
});
|
||||
}
|
||||
// console.log(this.orderData,'--=')
|
||||
// console.log(this.sliverInfo,'==--==')
|
||||
|
||||
createCartOrder({
|
||||
type:this.sliverInfo.id,
|
||||
original_price:this.orderData[0].original_price, //付款金额
|
||||
actual_price:this.payPrice + '', //付款金额
|
||||
original_price:this.orderData[0].original_price,
|
||||
actual_price:this.payPrice + '',
|
||||
reduction_amount:'0',
|
||||
pay_amount:this.payPrice + '', //付款金额
|
||||
pay_type: Number(this.WeChat) || Number(this.wallet), //微信和钱包type
|
||||
address_id:this.addressInfo.id, //地址id
|
||||
address:this.addressInfo.full_address, //地址
|
||||
pay_amount:this.payPrice + '',
|
||||
pay_type: Number(this.WeChat) || Number(this.wallet),
|
||||
address_id:this.addressInfo.id,
|
||||
address:this.addressInfo.full_address,
|
||||
name:this.addressInfo.recipient_name,
|
||||
phone:this.addressInfo.phone,
|
||||
note:'', //备注
|
||||
note:'',
|
||||
items:this.orderData
|
||||
})
|
||||
.then((res) => {
|
||||
@ -565,7 +492,6 @@
|
||||
});
|
||||
});
|
||||
},
|
||||
// 支付订单
|
||||
pay(orderId) {
|
||||
payOrder({
|
||||
type:4,
|
||||
@ -590,12 +516,11 @@
|
||||
uni.requestSubscribeMessage({
|
||||
tmplIds: ['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE',
|
||||
'GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'
|
||||
], // TEMPLATE_ID替换为选用的模版id
|
||||
],
|
||||
success(res) {
|
||||
uni.hideLoading()
|
||||
if (res['QoTeQwj4xw2UQMK5jI67MzAVOo6og76oqZ7BDIJW7cE'] ===
|
||||
'accept') {
|
||||
// setSubscribeStatus(true, '已订阅')
|
||||
uni.showToast({
|
||||
title: '订阅成功',
|
||||
icon: 'success',
|
||||
@ -603,7 +528,6 @@
|
||||
}
|
||||
if (res['GPWlTkaNbi7JqvxltLKuZZMtKedSZfEKlirV7yOUu-0'] ===
|
||||
'accept') {
|
||||
// setSubscribeStatus(true, '已订阅')
|
||||
uni.showToast({
|
||||
title: '订阅成功',
|
||||
icon: 'success',
|
||||
@ -617,7 +541,6 @@
|
||||
})
|
||||
},
|
||||
complete: () => {
|
||||
// isSubscribing = false
|
||||
},
|
||||
})
|
||||
|
||||
@ -670,7 +593,6 @@
|
||||
this.selected3 = false;
|
||||
this.selected4 = true;
|
||||
},
|
||||
// 跳转至宠物订单随车购入口
|
||||
jumpToPetOrder() {
|
||||
const pages = getCurrentPages();
|
||||
const detailsIndex = pages.findIndex((v) =>
|
||||
@ -725,7 +647,6 @@
|
||||
const oldCoupon = {
|
||||
...this.useCouponInfo
|
||||
};
|
||||
// 购物车进来的需要预下单
|
||||
if (data.coupon_id) {
|
||||
this.useCouponInfo = {
|
||||
...data
|
||||
@ -746,60 +667,7 @@
|
||||
}
|
||||
},
|
||||
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;
|
||||
|
||||
// 计算新位置(只改变bottom,right始终保持为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() {
|
||||
// 如果正在拖拽,不触发点击事件
|
||||
if (this.isDragging) {
|
||||
return;
|
||||
}
|
||||
this.jumpToWeChat();
|
||||
},
|
||||
cancelOrder() {
|
||||
@ -814,7 +682,6 @@
|
||||
});
|
||||
},
|
||||
confirmPay() {
|
||||
// console.log(this.type, '??')
|
||||
if (this.WeChat === undefined && this.wallet === undefined) {
|
||||
uni.showToast({
|
||||
title: '请选择支付方式',
|
||||
@ -825,13 +692,6 @@
|
||||
this.type === "cart" ? this.creatCartOrder() : this.createOrder();
|
||||
},
|
||||
changeSliverType(item) {
|
||||
// if (item.id === 2 && !this.serviceOrderList?.length) {
|
||||
// uni.showToast({
|
||||
// title: "您当前不存在服务订单",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
this.selectSliverInfo = {
|
||||
...item
|
||||
};
|
||||
@ -907,7 +767,7 @@
|
||||
.address-details {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 36rpx; // 图标宽度24rpx + 间距12rpx
|
||||
margin-left: 36rpx;
|
||||
}
|
||||
|
||||
.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 {
|
||||
padding: 16rpx 0;
|
||||
|
||||
|
||||
@ -257,16 +257,8 @@
|
||||
/>
|
||||
</view> -->
|
||||
|
||||
<!-- 右侧浮动联系客服按钮 -->
|
||||
<view class="contact-float-btn"
|
||||
: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>
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
|
||||
|
||||
<view class="place-view"></view>
|
||||
|
||||
@ -363,8 +355,9 @@
|
||||
import PopUpModal from "@/components/PopUpModal.vue";
|
||||
import SuccessModal from "@/components/SuccessModal.vue";
|
||||
import SliverInfo from "./components/SliverInfo.vue";
|
||||
import CallModal from "@/components/petOrder/call-modal.vue";
|
||||
import {
|
||||
import CallModal from "@/components/petOrder/call-modal.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
import {
|
||||
walletTransaction,
|
||||
cancelPetOrderRefund,
|
||||
cancelPetOrderMall
|
||||
@ -410,6 +403,7 @@
|
||||
SuccessModal,
|
||||
SliverInfo,
|
||||
CallModal,
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@ -42,15 +42,8 @@
|
||||
<view v-if="elasticLayer" class="elastic-layer" />
|
||||
</view>
|
||||
|
||||
<!-- 右侧浮动联系客服按钮 -->
|
||||
<view class="contact-float-btn" :style="{ right: contactBtnRight + 'rpx', bottom: contactBtnBottom + '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>
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactBtnClick" />
|
||||
|
||||
<view class="additional-bottom" v-if="additionalBom">
|
||||
<view class="recharge-method">
|
||||
@ -84,7 +77,8 @@
|
||||
<pop-up-modal v-if="showCancelModal" content="确定要取消该订单吗?" @confirm="orderCancel"
|
||||
@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"
|
||||
@cancel="showSliverModal = false" />
|
||||
@ -105,6 +99,8 @@ import PopUpModal from "@/components/PopUpModal.vue";
|
||||
import SuccessModal from "@/components/SuccessModal.vue";
|
||||
import ContactModal from "@/components/ContactModal.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";
|
||||
|
||||
|
||||
@ -134,6 +130,8 @@ export default {
|
||||
ContactModal,
|
||||
SuccessModal,
|
||||
SliverInfo,
|
||||
WeChatCopyModal,
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -163,14 +161,6 @@ export default {
|
||||
p: 1,
|
||||
num: 10,
|
||||
imgPrefix,
|
||||
// 联系客服按钮拖拽相关
|
||||
contactBtnRight: 0, // 默认右侧距离,始终为0
|
||||
contactBtnBottom: 0, // 默认底部距离,需要计算
|
||||
isDragging: false, // 是否正在拖拽
|
||||
touchStartX: 0, // 触摸开始X坐标
|
||||
touchStartY: 0, // 触摸开始Y坐标
|
||||
initialRight: 0, // 初始右侧距离
|
||||
initialBottom: 0, // 初始底部距离
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -208,14 +198,6 @@ export default {
|
||||
},
|
||||
onLoad() {
|
||||
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: {
|
||||
jumpToWeChat,
|
||||
@ -416,10 +398,6 @@ export default {
|
||||
},
|
||||
// 申请售后
|
||||
afterSale() {
|
||||
// 如果正在拖拽,不触发点击事件
|
||||
if (this.isDragging) {
|
||||
return;
|
||||
}
|
||||
this.jumpToWeChat();
|
||||
},
|
||||
// afterSale(data) {
|
||||
@ -471,61 +449,40 @@ export default {
|
||||
this.showCancelModal = true;
|
||||
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;
|
||||
|
||||
// 计算新位置(只改变bottom,right始终保持为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() {
|
||||
// 如果正在拖拽,不触发点击事件
|
||||
if (this.isDragging) {
|
||||
return;
|
||||
console.log('[list.vue] handleContactBtnClick called')
|
||||
console.log('[list.vue] wechatCopyModal ref:', this.$refs.wechatCopyModal)
|
||||
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>
|
||||
|
||||
@ -58,13 +58,18 @@
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 取消预约确认弹窗 - 放在父组件中避免被 overflow: hidden 裁剪 -->
|
||||
<!-- 取消预约确认弹窗 - 放在父组件中避免被 overflow: hidden 裁剪 -->
|
||||
<pop-up-modal
|
||||
v-if="isShowCancelModal"
|
||||
content="确定要取消预约吗?"
|
||||
@confirm="confirmCancelOrder"
|
||||
@cancel="isShowCancelModal = false"
|
||||
/>
|
||||
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
|
||||
|
||||
<WeChatCopyModal ref="wechatCopyModal" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -76,6 +81,8 @@ import { showOrderStatus } from "@/pageHome/constants/home";
|
||||
import { getOrderList, cancelHomeOrder, cancelTrainingOrder } from "@/api/order";
|
||||
import { cancelPetOrderRefund } from "@/api/login";
|
||||
import PopUpModal from "@/components/PopUpModal.vue";
|
||||
import WeChatCopyModal from "@/components/WeChatCopyModal.vue";
|
||||
import DraggableContact from "@/components/DraggableContact.vue";
|
||||
|
||||
export default {
|
||||
name: 'index',
|
||||
@ -83,7 +90,9 @@ export default {
|
||||
Reservation,
|
||||
HomeServiceOrderItem,
|
||||
HomeTrainingOrderItem,
|
||||
PopUpModal
|
||||
PopUpModal,
|
||||
WeChatCopyModal,
|
||||
DraggableContact
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -305,6 +314,15 @@ export default {
|
||||
icon: 'none'
|
||||
});
|
||||
},
|
||||
// 跳转微信客服 - 使用自定义弹窗(与首页在线客服功能一致)
|
||||
handleContactClick() {
|
||||
if (this.$refs.wechatCopyModal) {
|
||||
this.$refs.wechatCopyModal.show({
|
||||
title: '请添加客服号',
|
||||
weChatCode: 'Wagoo2025'
|
||||
});
|
||||
}
|
||||
},
|
||||
handleGotoEvaluate(orderInfo) {
|
||||
// 处理去评价
|
||||
const orderId = orderInfo.order_id || orderInfo.home_training_order?.order_id;
|
||||
@ -401,6 +419,8 @@ export default {
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding-bottom: 32rpx;
|
||||
padding-bottom: 32rpx;
|
||||
}
|
||||
|
||||
/* 可拖动联系客服组件无需额外样式 */
|
||||
</style>
|
||||
|
||||
@ -110,18 +110,15 @@
|
||||
{{ cartShowCount }}
|
||||
</view>
|
||||
|
||||
<view class="contact-icon-view">
|
||||
<image class="contact-icon" :src="`${imgPrefix}supportStaff.png`" @click="jumpToWeChat" />
|
||||
<view class="contact-btn fs-20">
|
||||
联系客服
|
||||
</view>
|
||||
</view>
|
||||
<!-- 可拖动联系客服组件 -->
|
||||
<DraggableContact ref="draggableContact" :onClick="handleContactClick" />
|
||||
|
||||
<add-goods-modal v-if="showModal" :data="addGoodInfo" optText="加入购物车" @change="(val) => (showModal = val)"
|
||||
@optAction="optAction" />
|
||||
<coupon-modal v-if="showCouponModal" :couponList="couponList" @close="onCouponModalClose"
|
||||
@getCoupon="getCoupon" />
|
||||
<contact-modal v-if="showContactModal" @close="showContactModal = false" />
|
||||
<contact-modal v-if="showContactModal" @close="showContactModal = false" />
|
||||
<WeChatCopyModal ref="wechatCopyModal" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -133,7 +130,9 @@
|
||||
import GoodItem from "./components/GoodItem.vue";
|
||||
import AddGoodsModal from "@/components/goods/AddGoodsModal.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 {
|
||||
getGoodsClassify,
|
||||
@ -153,12 +152,14 @@
|
||||
jumpToWeChat
|
||||
} from "@/utils/common";
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
GoodItem,
|
||||
AddGoodsModal,
|
||||
CouponModal,
|
||||
ContactModal,
|
||||
WeChatCopyModal,
|
||||
DraggableContact,
|
||||
},
|
||||
data() {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
@ -236,7 +237,42 @@
|
||||
|
||||
// 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,
|
||||
onShowFun() {
|
||||
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 {
|
||||
|
||||
@ -31,10 +31,32 @@ export default {
|
||||
this.getDetail(this.id);
|
||||
},
|
||||
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) {
|
||||
getArticleDetail(id).then(
|
||||
res => {
|
||||
this.content = res.data.content
|
||||
this.content = this.cleanHtml(res.data.content)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -90,19 +90,31 @@ export const getWeekDayName = (weekday) => {
|
||||
return weekdayName[weekday];
|
||||
};
|
||||
|
||||
// 跳转企微客服
|
||||
export const jumpToWeChat = () => {
|
||||
wx.openCustomerServiceChat({
|
||||
corpId: appConfig.qiWeId, // 企业id,必填
|
||||
extInfo: { // 客服信息
|
||||
url: appConfig.qiWeLink, // 客服链接
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log(err);
|
||||
uni.showModal({
|
||||
content: err || "跳转客服微信失败",
|
||||
showCancel: false,
|
||||
});
|
||||
/**
|
||||
* 跳转在线客服 - 显示弹窗提示添加企业微信
|
||||
*/
|
||||
export const jumpToCustomerService = () => {
|
||||
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 别名
|
||||
export const jumpToWeChat = jumpToCustomerService;
|
||||
|
||||
@ -19,6 +19,10 @@ module.exports = {
|
||||
// 忽略 moment.js 的 locale 文件,减小体积
|
||||
config.plugin('ignore')
|
||||
.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') {
|
||||
|
||||
Reference in New Issue
Block a user