diff --git a/components/LocationListSheet.vue b/components/LocationListSheet.vue index 7657e75..0c57b5a 100644 --- a/components/LocationListSheet.vue +++ b/components/LocationListSheet.vue @@ -40,7 +40,7 @@ import { computed } from 'vue' import { useI18n } from '@/utils/i18n.js' - const { t: $t } = useI18n() + const { t } = useI18n() const props = defineProps({ show: { type: Boolean, default: false }, diff --git a/components/MapComponent.vue b/components/MapComponent.vue index 1bfe736..e36a81a 100644 --- a/components/MapComponent.vue +++ b/components/MapComponent.vue @@ -1,5 +1,5 @@ - @@ -338,4 +320,4 @@ export default { } } } - \ No newline at end of file + \ No newline at end of file diff --git a/pages/device/detail.vue b/pages/device/detail.vue index 1a6b168..57ac843 100644 --- a/pages/device/detail.vue +++ b/pages/device/detail.vue @@ -131,7 +131,9 @@ import { getOrderByOrderNoScore, getOrderByOrderNo, - cancelOrder + cancelOrder, + getInUseOrder, + getUnpaidOrder } from '@/config/api/order.js' import { initiateWeChatScorePayment, @@ -143,7 +145,7 @@ } from '@/utils/i18n.js' const { - t: $t + t } = useI18n() // 响应式状态 @@ -154,7 +156,7 @@ const deviceLocation = ref('一号教学楼大厅') const hasActiveOrder = ref(false) const deviceStatus = reactive({ - text: $t('device.available'), + text: t('device.available'), class: 'available' }) const isLoggedIn = ref(true) @@ -175,7 +177,7 @@ onMounted(async () => { uni.setNavigationBarTitle({ - title: $t('device.deviceInfo') + title: t('device.deviceInfo') }) await checkUserPhone() await fetchDeviceInfo() @@ -219,7 +221,7 @@ // 用户拒绝授权的情况 if (e.detail.errMsg && e.detail.errMsg.includes('deny')) { uni.showToast({ - title: $t('auth.phoneRequired'), + title: t('auth.phoneRequired'), icon: 'none' }) return @@ -228,7 +230,7 @@ // 获取到授权code if (e.detail.code) { uni.showLoading({ - title: $t('auth.getting') + title: t('auth.getting') }) console.log('获取到的授权code:', e.detail.code) @@ -260,15 +262,15 @@ showPhoneAuthPopup.value = false uni.showToast({ - title: $t('auth.phoneSuccess'), + title: t('auth.phoneSuccess'), icon: 'success' }) } else { // 记录详细信息,不抛出错误 console.warn('获取手机号响应异常:', res.msg || '未知错误') uni.showModal({ - title: $t('auth.phoneError'), - content: `${$t('common.statusCode')}: ${res.code}, ${$t('common.message')}: ${res.msg || $t('common.none')}`, + title: t('auth.phoneError'), + content: `${t('common.statusCode')}: ${res.code}, ${t('common.message')}: ${res.msg || t('common.none')}`, showCancel: false }) } @@ -280,8 +282,8 @@ // 显示更详细的错误信息 let errMsg = err.message || err.toString() uni.showModal({ - title: $t('auth.phoneGetFailed'), - content: $t('common.errorInfo') + ': ' + errMsg, + title: t('auth.phoneGetFailed'), + content: t('common.errorInfo') + ': ' + errMsg, showCancel: false }) }) @@ -289,14 +291,14 @@ uni.hideLoading() console.error('获取手机号外部错误:', outerError) uni.showModal({ - title: $t('common.unexpectedError'), - content: $t('common.processException') + ': ' + (outerError.message || outerError), + title: t('common.unexpectedError'), + content: t('common.processException') + ': ' + (outerError.message || outerError), showCancel: false }) } } else { uni.showToast({ - title: $t('auth.authCodeFailed'), + title: t('auth.authCodeFailed'), icon: 'none' }) } @@ -325,10 +327,10 @@ // 更新设备状态 if (deviceInfo.value.status) { if (deviceInfo.value.status === 'online') { - deviceStatus.text = $t('device.available') + deviceStatus.text = t('device.available') deviceStatus.class = 'available' } else if (deviceInfo.value.status === 'offline') { - deviceStatus.text = $t('device.offline') + deviceStatus.text = t('device.offline') deviceStatus.class = 'offline' } } @@ -349,9 +351,9 @@ // 显示登录提示 const showLoginTip = () => { uni.showModal({ - title: $t('common.tips'), - content: $t('common.loginRequired'), - confirmText: $t('auth.goToLogin'), + title: t('common.tips'), + content: t('common.loginRequired'), + confirmText: t('auth.goToLogin'), success: (res) => { if (res.confirm) { uni.navigateTo({ @@ -374,27 +376,29 @@ const checkOrderStatus = async () => { try { // 调用接口检查是否有进行中的订单 - const result = await uni.$api.checkActiveOrder() + const inUseRes = await getInUseOrder() + if (inUseRes && inUseRes.code === 200 && inUseRes.data) { + const order = inUseRes.data + // 如果有正在进行的订单,跳转到归还页面,带上设备ID + uni.redirectTo({ + url: `/pages/device/return?deviceId=${deviceId.value}` + }) + return + } - if (result.hasOrder) { - const order = result.order // 假设后端返回 order 对象 - - // 检查订单状态 - if (order.status === 'waiting_for_payment') { - // 跳转支付页面,带上订单ID - uni.redirectTo({ - url: `/pages/order/payment?orderId=${order.orderId}&deviceId=${deviceId.value}` - }) - } else if (order.status === 'in_used') { - // 如果有正在进行的订单,跳转到归还页面,带上设备ID - uni.redirectTo({ - url: `/pages/device/return?deviceId=${deviceId.value}` - }) - } + // 检查是否有待支付的订单 + const unpaidRes = await getUnpaidOrder() + if (unpaidRes && unpaidRes.code === 200 && unpaidRes.data) { + const order = unpaidRes.data + // 跳转支付页面,带上订单ID + uni.redirectTo({ + url: `/pages/order/payment?orderId=${order.orderId}&deviceId=${deviceId.value}` + }) } } catch (error) { + console.error('检查订单状态失败:', error) uni.showToast({ - title: $t('order.getOrderStatusFailed'), + title: t('order.getOrderStatusFailed'), icon: 'none' }) } @@ -427,7 +431,7 @@ return '30分钟' } // 按小时计费(默认) - return $t('time.hour') + return t('time.hour') } // 计算计费单位时间(分钟) @@ -499,7 +503,7 @@ const submitRentOrder = async (payWay) => { try { uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }) // --- 第一步:先请求订阅消息(必须在用户点击的同步上下文中)--- if (payWay === 'wx-score-pay') { @@ -532,7 +536,7 @@ // 调用设备租借接口 const rentResult = await rentPowerBank(deviceId.value, phoneNumber.value) if (rentResult.code !== 200) { - throw new Error(rentResult.msg || $t('device.rentFailed')) + throw new Error(rentResult.msg || t('device.rentFailed')) } // 获取后端返回的订单信息 @@ -587,7 +591,7 @@ // 用户取消授权,需要取消订单 try { uni.showLoading({ - title: $t('order.cancelling') + title: t('order.cancelling') }); const cancelRes = await cancelOrder({ orderId: order.orderNo @@ -596,7 +600,7 @@ uni.hideLoading(); uni.showToast({ - title: $t('order.orderCancelled'), + title: t('order.orderCancelled'), icon: 'none', duration: 2000 }); @@ -611,7 +615,7 @@ console.error('取消订单失败:', cancelError); uni.hideLoading(); uni.showToast({ - title: $t('order.cancelFailedContactService'), + title: t('order.cancelFailedContactService'), icon: 'none' }); } @@ -622,7 +626,7 @@ // 支付分调用异常,也需要取消订单 try { uni.showLoading({ - title: $t('order.cancelling') + title: t('order.cancelling') }); const cancelRes = await cancelOrder({ orderId: order.orderNo @@ -635,7 +639,7 @@ } uni.showToast({ - title: $t('device.payScoreFailedCancelled'), + title: t('device.payScoreFailedCancelled'), icon: 'none' }); @@ -647,7 +651,7 @@ } } else { uni.showToast({ - title: res?.msg || $t('device.getPayParamsFailed'), + title: res?.msg || t('device.getPayParamsFailed'), icon: 'none' }); } @@ -655,7 +659,7 @@ } catch (error) { uni.hideLoading() uni.showToast({ - title: error.message || $t('device.rentFailedRetry'), + title: error.message || t('device.rentFailedRetry'), icon: 'none' }) } diff --git a/pages/expressReturn/addExpressReturn.vue b/pages/expressReturn/addExpressReturn.vue index 3c3a50d..fe37557 100644 --- a/pages/expressReturn/addExpressReturn.vue +++ b/pages/expressReturn/addExpressReturn.vue @@ -62,11 +62,11 @@ } from '@/config/api/expressReturn.js' import { useI18n } from '@/utils/i18n.js' - const { t: $t } = useI18n() + const { t } = useI18n() onMounted(() => { uni.setNavigationBarTitle({ - title: $t('express.fillExpress') + title: t('express.fillExpress') }) }) @@ -96,7 +96,7 @@ if (!orderId.value) { uni.showToast({ - title: $t('express.orderNoMissing'), + title: t('express.orderNoMissing'), icon: 'none' }) setTimeout(() => { @@ -111,7 +111,7 @@ const loadOrder = async () => { try { uni.showLoading({ - title: $t('common.loading') + title: t('common.loading') }) const res = await queryById(orderId.value) if (res?.code === 200 && res.data) { @@ -121,11 +121,11 @@ // 默认联系电话可回填订单上的手机号(若有) if (res.data.phone && !phone.value) phone.value = res.data.phone } else { - throw new Error(res?.msg || $t('order.getOrderFailed')) + throw new Error(res?.msg || t('order.getOrderFailed')) } } catch (e) { uni.showToast({ - title: e.message || $t('express.loadFailed'), + title: e.message || t('express.loadFailed'), icon: 'none' }) } finally { @@ -136,7 +136,7 @@ const loadRecordAndOrderByRecord = async () => { try { uni.showLoading({ - title: $t('common.loading') + title: t('common.loading') }) const res = await getExpressReturnDetail(recordId.value) if (res?.code === 200 && res.data) { @@ -146,11 +146,11 @@ } if (res.data.userPhone && !phone.value) phone.value = res.data.userPhone } else { - throw new Error(res?.msg || $t('express.getRecordFailed')) + throw new Error(res?.msg || t('express.getRecordFailed')) } } catch (e) { uni.showToast({ - title: e.message || $t('express.loadFailed'), + title: e.message || t('express.loadFailed'), icon: 'none' }) } finally { @@ -166,10 +166,10 @@ if (rec.status === 0) { recordId.value = rec.id uni.showModal({ - title: $t('common.tips'), - content: $t('express.existingReturnNotice'), - confirmText: $t('express.goToFill'), - cancelText: $t('common.cancel'), + title: t('common.tips'), + content: t('express.existingReturnNotice'), + confirmText: t('express.goToFill'), + cancelText: t('common.cancel'), success: (r) => { if (r.confirm) { uni.redirectTo({ @@ -181,7 +181,7 @@ return } else { uni.showToast({ - title: $t('express.alreadyHasRecord'), + title: t('express.alreadyHasRecord'), icon: 'none' }) setTimeout(() => { @@ -201,14 +201,14 @@ const digits = (phone.value || '').replace(/\D/g, '') if (!digits || digits.length < 5) { uni.showToast({ - title: $t('express.pleaseEnterValidPhone'), + title: t('express.pleaseEnterValidPhone'), icon: 'none' }) return false } if (isFillMode.value && !trackingNumber.value) { uni.showToast({ - title: $t('express.pleaseEnterTrackingNo'), + title: t('express.pleaseEnterTrackingNo'), icon: 'none' }) return false @@ -221,7 +221,7 @@ submitting.value = true try { uni.showLoading({ - title: isFillMode.value ? $t('common.filling') : $t('common.submitting') + title: isFillMode.value ? t('common.filling') : t('common.submitting') }) let res if (isFillMode.value) { @@ -238,18 +238,18 @@ } if (res && res.code === 200) { uni.showToast({ - title: isFillMode.value ? '补填成功' : '提交成功', + title: isFillMode.value ? t('express.fillSuccess') : t('express.submitSuccess'), icon: 'success' }) setTimeout(() => { uni.navigateBack() }, 800) } else { - throw new Error(res?.msg || (isFillMode.value ? '补填失败' : '提交失败')) + throw new Error(res?.msg || (isFillMode.value ? t('express.fillFailed') : t('express.submitFailed'))) } } catch (e) { uni.showToast({ - title: e.message || (isFillMode.value ? '补填失败' : '提交失败'), + title: e.message || (isFillMode.value ? t('express.fillFailed') : t('express.submitFailed')), icon: 'none' }) } finally { diff --git a/pages/expressReturn/detail.vue b/pages/expressReturn/detail.vue index 6ab9c27..fa12904 100644 --- a/pages/expressReturn/detail.vue +++ b/pages/expressReturn/detail.vue @@ -91,7 +91,7 @@ import { getExpressReturnDetail } from '@/config/api/expressReturn.js' import { getCustomerPhone } from '@/util/index.js' import { useI18n } from '@/utils/i18n.js' -const { t: $t } = useI18n() +const { t } = useI18n() // 详情数据 const detailData = ref({ @@ -131,21 +131,21 @@ const getStatusIcon = (status) => { // 获取状态文本 const getStatusText = (status) => { const textMap = { - 'completed': $t('express.returnCompleted'), - 'processing': $t('express.processing'), - 'pending': $t('express.pending') + 'completed': t('express.returnCompleted'), + 'processing': t('express.processing'), + 'pending': t('express.pending') } - return textMap[status] || $t('express.pending') + return textMap[status] || t('express.pending') } // 获取状态描述 const getStatusDesc = (status) => { const descMap = { - 'completed': $t('express.returnCompletedDesc'), - 'processing': $t('express.processingDesc'), - 'pending': $t('express.pendingDesc') + 'completed': t('express.returnCompletedDesc'), + 'processing': t('express.processingDesc'), + 'pending': t('express.pendingDesc') } - return descMap[status] || $t('express.pendingDesc') + return descMap[status] || t('express.pendingDesc') } // 复制运单号 @@ -154,7 +154,7 @@ const handleCopyTracking = () => { data: detailData.value.trackingNumber, success: () => { uni.showToast({ - title: $t('express.trackingNoCopied'), + title: t('express.trackingNoCopied'), icon: 'success' }) } @@ -165,10 +165,10 @@ const handleCopyTracking = () => { const handleContactService = () => { const customerPhone = getCustomerPhone() uni.showModal({ - title: $t('user.customerService'), - content: `${$t('help.phone')}:${customerPhone}\n${$t('help.workingHours')}:${$t('express.workingHours')}`, - confirmText: $t('express.call'), - cancelText: $t('common.cancel'), + title: t('user.customerService'), + content: `${t('help.phone')}:${customerPhone}\n${t('help.workingHours')}:${t('express.workingHours')}`, + confirmText: t('express.call'), + cancelText: t('common.cancel'), success: (res) => { if (res.confirm) { uni.makePhoneCall({ @@ -182,7 +182,7 @@ const handleContactService = () => { // 页面加载时获取详情数据 onMounted(async () => { uni.setNavigationBarTitle({ - title: $t('express.returnDetail') + title: t('express.returnDetail') }) const pages = getCurrentPages() @@ -190,7 +190,7 @@ onMounted(async () => { const options = currentPage.options || {} if (!options.id) return try { - uni.showLoading({ title: $t('common.loading') }) + uni.showLoading({ title: t('common.loading') }) const res = await getExpressReturnDetail(options.id) if (res && res.code === 200 && res.data) { const r = res.data @@ -208,10 +208,10 @@ onMounted(async () => { remark: r.remark || '' } } else { - throw new Error(res?.msg || $t('express.getDetailFailed')) + throw new Error(res?.msg || t('express.getDetailFailed')) } } catch (e) { - uni.showToast({ title: e.message || $t('express.loadFailed'), icon: 'none' }) + uni.showToast({ title: e.message || t('express.loadFailed'), icon: 'none' }) } finally { uni.hideLoading() } diff --git a/pages/expressReturn/index.vue b/pages/expressReturn/index.vue index e0935b7..f18c75e 100644 --- a/pages/expressReturn/index.vue +++ b/pages/expressReturn/index.vue @@ -54,7 +54,7 @@ import { ref, onMounted } from 'vue' import { getExpressReturnList } from '@/config/api/expressReturn.js' import { useI18n } from '@/utils/i18n.js' -const { t: $t } = useI18n() +const { t } = useI18n() const returnList = ref([]) const loading = ref(false) @@ -62,7 +62,7 @@ const query = ref({ pageNum: 1, pageSize: 20 }) onMounted(() => { uni.setNavigationBarTitle({ - title: $t('express.returnRecord') + title: t('express.returnRecord') }) loadList() }) @@ -80,12 +80,12 @@ const loadList = async () => { const rows = (res.data && (res.data.rows || res.data)) || [] returnList.value = rows.map(r => ({ id: r.id, - expressCompany: r.expressCompany || r.company || '待填写', - trackingNumber: r.logisticsTrackingNumber || r.trackingNumber || '待填写', - returnAddress: r.returnAddress || r.address || '待填写', - returnTime: r.expressFillTime || r.createTime || r.returnTime || '待填写', - packageType: r.packageType || '待填写', - weight: r.weight || '待填写', + expressCompany: r.expressCompany || r.company || t('express.toFill'), + trackingNumber: r.logisticsTrackingNumber || r.trackingNumber || t('express.toFill'), + returnAddress: r.returnAddress || r.address || t('express.toFill'), + returnTime: r.expressFillTime || r.createTime || r.returnTime || t('express.toFill'), + packageType: r.packageType || t('express.toFill'), + weight: r.weight || t('express.toFill'), status: mapStatus(r.status), rawStatus: r.status, userPhone: r.userPhone, @@ -93,10 +93,10 @@ const loadList = async () => { remark: r.remark })) } else { - throw new Error(res?.msg || $t('express.getListFailed')) + throw new Error(res?.msg || t('express.getListFailed')) } } catch (e) { - uni.showToast({ title: e.message || $t('express.loadFailed'), icon: 'none' }) + uni.showToast({ title: e.message || t('express.loadFailed'), icon: 'none' }) } finally { loading.value = false } @@ -118,34 +118,33 @@ const getStatusClass = (status) => ({ }[status] || 'status-pending') const getStatusText = (status) => ({ - 'completed': $t('express.billingPaused'), - 'processing': $t('express.billingPaused'), - 'pending': $t('express.billingPaused') -}[status] || $t('express.billingPaused')) + 'completed': t('express.billingPaused'), + 'processing': t('express.billingPaused'), + 'pending': t('express.billingPaused') +}[status] || t('express.billingPaused')) const getStatusBadge = (status) => ({ - 'completed': $t('express.completed'), - 'processing': $t('express.processing'), - 'pending': $t('express.pending') -}[status] || $t('express.pending')) + 'completed': t('express.completed'), + 'processing': t('express.processing'), + 'pending': t('express.pending') +}[status] || t('express.pending')) // 一键复制全部信息 const copyAllInfo = () => { - const allInfo = `${$t('express.recipient')}:${recipientName}\n${$t('express.recipientAddressLabel')}:${recipientAddress}` + const allInfo = `${t('express.recipient')}:${recipientName}\n${t('express.recipientAddressLabel')}:${recipientAddress}` uni.setClipboardData({ data: allInfo, success: () => { - uni.showToast({ title: $t('express.copySuccess'), icon: 'success' }) + uni.showToast({ title: t('express.copySuccess'), icon: 'success' }) }, fail: () => { - uni.showToast({ title: $t('express.copyFailed'), icon: 'none' }) + uni.showToast({ title: t('express.copyFailed'), icon: 'none' }) } }) } // 点击列表项 const handleItemClick = (item) => { - console.log('点击了归还记录:', item) // 未填写(status=0 -> mapped 'pending')时跳转到补填页,其它跳详情 if (item && item.rawStatus === 0) { uni.navigateTo({ url: `/pages/expressReturn/addExpressReturn?id=${item.id}` }) diff --git a/pages/feedback/detail.vue b/pages/feedback/detail.vue index 0dfa2f9..09282ca 100644 --- a/pages/feedback/detail.vue +++ b/pages/feedback/detail.vue @@ -98,13 +98,13 @@ } from '@/utils/i18n.js' const { - t: $t + t } = useI18n() // 设置页面标题 onMounted(() => { uni.setNavigationBarTitle({ - title: $t('feedback.detail') + title: t('feedback.detail') }) }) @@ -126,7 +126,7 @@ await loadDetail(); } else { uni.showToast({ - title: $t('feedback.idRequired'), + title: t('feedback.idRequired'), icon: 'none' }); setTimeout(() => { @@ -170,7 +170,7 @@ try { if (shouldShowLoading) { uni.showLoading({ - title: $t('common.loading') + title: t('common.loading') }); } @@ -180,7 +180,7 @@ await loadMessages(res.data.messages); } else { uni.showToast({ - title: res.msg || $t('feedback.getDetailFailed'), + title: res.msg || t('feedback.getDetailFailed'), icon: 'none' }); setTimeout(() => { @@ -190,7 +190,7 @@ } catch (error) { console.error('获取投诉详情失败:', error); uni.showToast({ - title: $t('feedback.getDetailFailed'), + title: t('feedback.getDetailFailed'), icon: 'none' }); setTimeout(() => { @@ -207,7 +207,7 @@ const submitReply = async () => { if (!replyContent.value.trim()) { uni.showToast({ - title: $t('feedback.pleaseEnterReply'), + title: t('feedback.pleaseEnterReply'), icon: 'none' }); return; @@ -215,7 +215,7 @@ try { uni.showLoading({ - title: $t('common.submitting') + title: t('common.submitting') }); const res = await sendFeedbackMessage(feedbackId.value, { @@ -224,7 +224,7 @@ if (res.code === 200) { uni.showToast({ - title: $t('feedback.replySuccess'), + title: t('feedback.replySuccess'), icon: 'success' }); replyContent.value = ''; @@ -234,14 +234,14 @@ }); } else { uni.showToast({ - title: res.msg || $t('feedback.replyFailed'), + title: res.msg || t('feedback.replyFailed'), icon: 'none' }); } } catch (error) { console.error('提交回复失败:', error); uni.showToast({ - title: $t('feedback.replyFailed'), + title: t('feedback.replyFailed'), icon: 'none' }); } finally { @@ -252,11 +252,11 @@ // 获取状态文本 const getStatusText = (status) => { const statusMap = { - 'pending': $t('feedback.pending'), - 'in_progress': $t('feedback.processing'), - 'resolved': $t('feedback.completed') + 'pending': t('feedback.pending'), + 'in_progress': t('feedback.processing'), + 'resolved': t('feedback.completed') }; - return statusMap[status] || $t('feedback.pending'); + return statusMap[status] || t('feedback.pending'); }; // 获取状态样式类 @@ -272,8 +272,8 @@ // 获取类型文本 const getTypeText = (type) => { const typeMap = { - 'complain': $t('feedback.complain'), - 'suggestion': $t('feedback.suggestion') + 'complain': t('feedback.complain'), + 'suggestion': t('feedback.suggestion') }; return typeMap[type] || type || '-'; }; diff --git a/pages/feedback/index.vue b/pages/feedback/index.vue index 5b16dc3..48ea427 100644 --- a/pages/feedback/index.vue +++ b/pages/feedback/index.vue @@ -80,7 +80,7 @@ useI18n } from '@/utils/i18n.js' const { - t: $t + t } = useI18n() // 跳转到投诉记录列表 @@ -92,7 +92,7 @@ onMounted(() => { uni.setNavigationBarTitle({ - title: $t('feedback.title') + title: t('feedback.title') }) }) @@ -137,7 +137,7 @@ const submitFeedback = async () => { if (selectedType.value === -1) { uni.showToast({ - title: $t('feedback.pleaseSelectType'), + title: t('feedback.pleaseSelectType'), icon: 'none' }) return @@ -145,7 +145,7 @@ if (!description.value.trim()) { uni.showToast({ - title: $t('feedback.pleaseDescribe'), + title: t('feedback.pleaseDescribe'), icon: 'none' }) return @@ -153,7 +153,7 @@ if (!contact.value) { uni.showToast({ - title: $t('feedback.pleaseContact'), + title: t('feedback.pleaseContact'), icon: 'none' }) return @@ -169,7 +169,7 @@ try { // 显示上传进度 uni.showLoading({ - title: $t('feedback.uploading') || '上传中...', + title: t('feedback.uploading') || '上传中...', mask: true }) @@ -185,7 +185,7 @@ console.error(`文件 ${i + 1} 上传失败:`, err) uni.hideLoading() uni.showToast({ - title: $t('feedback.imageUploadFailed'), + title: t('feedback.imageUploadFailed'), icon: 'none' }) return @@ -208,7 +208,7 @@ // 处理响应 if (res && (res.code === 200 || res === true || res?.success === true)) { uni.showToast({ - title: $t('feedback.submitSuccess'), + title: t('feedback.submitSuccess'), icon: 'success' }) setTimeout(() => { @@ -216,7 +216,7 @@ }, 1500); } else { uni.showToast({ - title: (res && (res.msg || res.message)) || $t('feedback.submitFailed'), + title: (res && (res.msg || res.message)) || t('feedback.submitFailed'), icon: 'none' }) } @@ -224,7 +224,7 @@ console.error('feedback submit failed:', err) uni.hideLoading() uni.showToast({ - title: $t('error.networkError') || '网络错误,请重试', + title: t('error.networkError') || '网络错误,请重试', icon: 'none' }) } diff --git a/pages/feedback/list.vue b/pages/feedback/list.vue index 6906097..526ae78 100644 --- a/pages/feedback/list.vue +++ b/pages/feedback/list.vue @@ -78,13 +78,13 @@ } from '@/utils/i18n.js' const { - t: $t + t } = useI18n() // 设置页面标题 onMounted(() => { uni.setNavigationBarTitle({ - title: $t('feedback.recordList') + title: t('feedback.recordList') }) }) @@ -100,25 +100,25 @@ // 状态标签 const statusTabs = reactive([{ get text() { - return $t('common.all') + return t('common.all') }, status: '' }, { get text() { - return $t('feedback.pending') + return t('feedback.pending') }, status: 'pending' }, { get text() { - return $t('feedback.processing') + return t('feedback.processing') }, status: 'in_progress' }, { get text() { - return $t('feedback.completed') + return t('feedback.completed') }, status: 'resolved' } @@ -176,14 +176,14 @@ } } else { uni.showToast({ - title: res.msg || $t('feedback.getListFailed'), + title: res.msg || t('feedback.getListFailed'), icon: 'none' }); } } catch (error) { console.error('获取投诉列表失败:', error); uni.showToast({ - title: $t('feedback.getListFailed'), + title: t('feedback.getListFailed'), icon: 'none' }); } finally { @@ -211,11 +211,11 @@ // 获取状态文本 const getStatusText = (status) => { const statusMap = { - 'pending': $t('feedback.pending'), - 'in_progress': $t('feedback.processing'), - 'resolved': $t('feedback.completed') + 'pending': t('feedback.pending'), + 'in_progress': t('feedback.processing'), + 'resolved': t('feedback.completed') }; - return statusMap[status] || $t('feedback.pending'); + return statusMap[status] || t('feedback.pending'); }; // 获取状态样式类 @@ -231,8 +231,8 @@ // 获取类型文本 const getTypeText = (type) => { const typeMap = { - 'complain': $t('feedback.complain'), - 'suggestion': $t('feedback.suggestion') + 'complain': t('feedback.complain'), + 'suggestion': t('feedback.suggestion') }; return typeMap[type] || type || '-'; }; diff --git a/pages/help/index.vue b/pages/help/index.vue index 8bd8bbf..3ebf058 100644 --- a/pages/help/index.vue +++ b/pages/help/index.vue @@ -26,40 +26,36 @@ {{ $t('help.workingHours') }} - {{ HELP_CONTENT.CONTACT.SERVICE_TIME.VALUE }} + {{ $t('help.workingHoursValue') }} - diff --git a/pages/index/index.vue b/pages/index/index.vue index efd35bd..8e9dd28 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -198,10 +198,13 @@ transformDeviceData } from '../../config/api/device.js' import { - getPotionsDetail + getInUseOrder, + getUnpaidOrder } from '../../config/api/order.js' import { - getActiveActivity + getActiveActivity, + getCurrentAnnouncement, + getCurrentAdvertisement } from '../../config/api/system.js' // 导入地图工具函数 import { @@ -227,7 +230,7 @@ // #endif const { - t: $t + t } = useI18n() // 响应式数据 @@ -294,39 +297,21 @@ const bannerImages = ref([]) // 首页广告图片列表 const bannerImageList = ref([]) // 完整的广告配置列表(包含链接信息) - // 将语言代码转换为后端接受的格式 - const convertLanguageCode = (lang) => { - // zh-CN -> zh_CN (转换下划线) - // en-US -> en_US (转换下划线) - return lang.replace(/-/g, '_') - } - // 获取公告内容(支持多语言) const getNoticeText = async () => { try { - // 获取当前语言设置 - const currentLang = uni.getStorageSync('language') || 'zh-CN' - const languageCode = convertLanguageCode(currentLang) - - console.log('加载公告,语言:', currentLang, '转换后:', languageCode) + console.log('加载公告') // 调用接口获取公告内容 - const res = await uni.request({ - url: `${URL}/device/announcementConfig/current`, - method: 'GET', - header: { - 'Content-Language': languageCode - }, - data: { - type: 'wx_user_type' // 微信小程序用户端 - } + const res = await getCurrentAnnouncement({ + type: 'wx_user_type' // 微信小程序用户端 }) console.log('公告响应:', res) - if (res.statusCode === 200 && res.data.code === 200 && res.data.data) { + if (res && res.code === 200 && res.data) { // 使用后端自动解析的 announcement 字段 - const announcement = res.data.data.announcement || '' + const announcement = res.data.announcement || '' noticeText.value = announcement // 设置通知栏高度 @@ -342,7 +327,7 @@ console.warn('缓存通知内容失败:', e) } } else { - console.warn('获取公告失败:', res.data?.msg || '未知错误') + console.warn('获取公告失败:', res?.msg || '未知错误') } } catch (error) { console.error('获取公告失败:', error) @@ -352,31 +337,20 @@ // 获取首页广告图片(支持多语言) const getBannerImages = async () => { try { - // 获取当前语言设置 - const currentLang = uni.getStorageSync('language') || 'zh-CN' - const languageCode = convertLanguageCode(currentLang) - - console.log('加载首页广告,语言:', currentLang, '转换后:', languageCode) + console.log('加载首页广告') // 调用接口获取广告内容 - const res = await uni.request({ - url: `${URL}/device/advertisementConfig/current`, - method: 'GET', - header: { - 'Content-Language': languageCode - }, - data: { - appPlatform: 'wechat', // 微信平台 - appType: 'user' ,// 用户端 - pictureLocation:'home_banner' - } + const res = await getCurrentAdvertisement({ + appPlatform: 'wechat', // 微信平台 + appType: 'user' ,// 用户端 + pictureLocation:'home_banner' }) console.log('首页广告响应:', res) - if (res.statusCode === 200 && res.data.code === 200 && res.data.data) { + if (res && res.code === 200 && res.data) { // 使用 imageList 字段(包含图片和链接信息) - const imageList = res.data.data.imageList || [] + const imageList = res.data.imageList || [] if (imageList.length > 0) { bannerImageList.value = imageList // 提取图片URL用于展示 @@ -385,7 +359,7 @@ console.warn('未获取到广告图片') } } else { - console.warn('获取首页广告失败:', res.data?.msg || '未知错误') + console.warn('获取首页广告失败:', res?.msg || '未知错误') } } catch (error) { console.error('获取首页广告失败:', error) @@ -415,7 +389,7 @@ fail: (err) => { console.error('跳转小程序失败:', err) uni.showToast({ - title: '跳转失败', + title: t('common.loadFailed'), icon: 'none' }) } @@ -423,7 +397,7 @@ // #endif // #ifndef MP-WEIXIN uni.showToast({ - title: '请在微信小程序中使用', + title: t('auth.pleaseUseInWechat'), icon: 'none' }) // #endif @@ -568,10 +542,10 @@ console.warn('清理旧缓存失败:', e); } - // 开发环境测试距离计算 - if (process.env.NODE_ENV === 'development') { - testDistanceCalculation() - } + // // 开发环境测试距离计算 + // if (process.env.NODE_ENV === 'development') { + // testDistanceCalculation() + // } // 并行加载公告和广告(不依赖定位) await Promise.all([ @@ -586,12 +560,12 @@ await loadPositions() // 3. 查询活动并显示弹窗 - await checkActiveActivity() + // await checkActiveActivity() } catch (error) { console.error('初始化失败:', error) uni.showToast({ - title: $t('home.getLocationFailed'), + title: t('home.getLocationFailed'), icon: 'none' }) } finally { @@ -787,12 +761,16 @@ isRelocating.value = true uni.showLoading({ - title: $t('home.relocating'), + title: t('home.relocating'), mask: true }) - // 重新获取用户真实位置(不使用缓存) + // 重新获取用户真实位置 const loc = await getUserLocation() + if (!loc || !loc.longitude || !loc.latitude) { + throw new Error('location failed') + } + const newLocation = { longitude: Number(loc.longitude), latitude: Number(loc.latitude) @@ -827,7 +805,7 @@ uni.hideLoading() uni.showToast({ - title: $t('home.locateSuccess'), + title: t('home.locateSuccess'), icon: 'success', duration: 1500 }) @@ -836,7 +814,7 @@ uni.hideLoading() uni.showToast({ - title: e.errMsg || $t('home.locateFailed'), + title: e.errMsg || t('home.locateFailed'), icon: 'none', duration: 2000 }) @@ -868,7 +846,7 @@ const selectPosition = (position) => { uni.showActionSheet({ - itemList: ['扫码使用', '导航前往'], + itemList: [t('home.scanToUse'), t('home.navigate')], success: (res) => { switch (res.tapIndex) { case 0: @@ -948,27 +926,17 @@ if (!deviceNo) { uni.showToast({ - title: $t('home.invalidQRCode'), + title: t('home.invalidQRCode'), icon: 'none' }) return } // 检查是否有使用中的订单 - const inUseRes = await uni.request({ - url: `${URL}/app/order/inUse`, - method: 'GET', - header: { - 'Authorization': "Bearer " + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }) + const inUseRes = await getInUseOrder() - if (inUseRes.statusCode === 401 || inUseRes.data?.code === 401 || inUseRes.data?.code === 40101) { - redirectToLogin() - return - } else if (inUseRes.statusCode == 200 && inUseRes.data.code == 200 && inUseRes.data.data) { - const inUseOrder = inUseRes.data.data + if (inUseRes && inUseRes.code === 200 && inUseRes.data) { + const inUseOrder = inUseRes.data uni.reLaunch({ url: `/pages/order/detail?orderId=${inUseOrder.orderId}&deviceId=${deviceNo || inUseOrder.deviceNo}` }) @@ -976,20 +944,10 @@ } // 检查是否有待支付订单 - const orderRes = await uni.request({ - url: `${URL}/app/order/unpaid`, - method: 'GET', - header: { - 'Authorization': "Bearer " + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }) + const orderRes = await getUnpaidOrder() - if (orderRes.statusCode === 401 || orderRes.data?.code === 401 || orderRes.data?.code === 40101) { - redirectToLogin() - return - } else if (orderRes.statusCode == 200 && orderRes.data.code == 200 && orderRes.data.data) { - const unpaidOrder = orderRes.data.data + if (orderRes && orderRes.code === 200 && orderRes.data) { + const unpaidOrder = orderRes.data uni.navigateTo({ url: `/pages/order/payment?orderId=${unpaidOrder.orderId}` }) @@ -1018,7 +976,7 @@ } } else { uni.showToast({ - title: '获取设备信息失败', + title: t('device.getDeviceInfoFailed'), icon: 'none' }) uni.navigateTo({ diff --git a/pages/join/index.vue b/pages/join/index.vue index 4497c9f..ee9a95c 100644 --- a/pages/join/index.vue +++ b/pages/join/index.vue @@ -12,7 +12,7 @@ } from 'vue' import { useI18n } from '@/utils/i18n.js' - const { t: $t } = useI18n() + const { t } = useI18n() // 外部网页地址 const webUrl = ref('https://joininvestment.gxfs123.com/') @@ -27,7 +27,7 @@ const handleError = (e) => { console.error('web-view 加载错误:', e) uni.showToast({ - title: $t('join.pageLoadFailed'), + title: t('join.pageLoadFailed'), icon: 'none', duration: 2000 }) @@ -35,7 +35,7 @@ onMounted(() => { uni.setNavigationBarTitle({ - title: $t('join.title') + title: t('join.title') }) console.log('招商页面加载,外部网址:', webUrl.value) }) diff --git a/pages/legal/agreement.vue b/pages/legal/agreement.vue index 5a3ffc5..ab2e3fd 100644 --- a/pages/legal/agreement.vue +++ b/pages/legal/agreement.vue @@ -36,9 +36,9 @@ diff --git a/pages/my/card.vue b/pages/my/card.vue index 6622f2c..320a679 100644 --- a/pages/my/card.vue +++ b/pages/my/card.vue @@ -2,30 +2,63 @@ - - - {{ card.name }} - - {{ getStatusText(card.status) }} + + + + + {{ card.name }} + + {{ card.endDate }}{{ + $t('myCard.expire') }} + {{ $t('myCard.expiredOn') }}{{ card.endDate }} + + + + + + {{ $t('myCard.onlyForRegionBefore') }}{{ card.positionName }}{{ $t('myCard.onlyForRegionAfter') }} + + + {{ $t('myCard.toUse') }} + + + + {{ getStatusText(card.status) }} + - - {{ $t('myCard.type') }}: - {{ card.cardType === 'COUNT' ? $t('myCard.timesCard') : - $t('myCard.durationCard') }} - - - {{ $t('myCard.remainingTimes') }}: - {{ card.remainingTimes }}/{{ card.totalTimes }} - - - {{ $t('myCard.remainingDuration') }}: - {{ card.remainingDuration }}{{ $t('myCard.hours') }} - - - {{ $t('myCard.validPeriod') }}: - {{ card.startDate }} - {{ card.endDate }} + + + + + + {{ $t('myCard.remainingTimes') }}{{ card.remainingCount }}{{ + $t('myCard.times') }} + + + + {{ $t('myCard.durationCard') }} + + + + + + + {{ $t('myCard.renew') }} + + + + + + + @@ -41,202 +74,403 @@ + + .card-actions { + display: flex; + align-items: center; + gap: 16rpx; + } + + // 续卡按钮 + .renew-btn { + display: flex; + align-items: center; + gap: 4rpx; + padding: 8rpx 16rpx; + // background-color: #FFF9F0; + border-radius: 8rpx; + + .renew-text { + font-size: 24rpx; + color: #D4A574; + line-height: 34rpx; + } + + .arrow { + font-size: 24rpx; + color: #D4A574; + } + } + + // 状态标签 + .status-tag { + padding: 8rpx 20rpx; + border-radius: 8rpx; + + .status-text { + font-size: 24rpx; + line-height: 34rpx; + } + + &.active { + // background-color: #FFF9F0; + + .status-text { + color: #D4A574; + } + } + + &.expired { + // background-color: #F5F5F5; + + .status-text { + color: #999999; + } + } + + &.used { + // background-color: #F5F5F5; + + .status-text { + color: #999999; + } + } + } + + .empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 120rpx 0; + + .empty-icon { + width: 200rpx; + height: 200rpx; + margin-bottom: 40rpx; + opacity: 0.5; + } + + .empty-text { + font-size: 28rpx; + color: #999; + margin-bottom: 40rpx; + } + + .buy-btn { + padding: 20rpx 60rpx; + background-color: #B8741A; + border-radius: 48rpx; + + .buy-text { + font-size: 28rpx; + color: #ffffff; + font-weight: 500; + } + } + } + \ No newline at end of file diff --git a/pages/my/coupon.vue b/pages/my/coupon.vue index 393cd53..b36d49e 100644 --- a/pages/my/coupon.vue +++ b/pages/my/coupon.vue @@ -1,7 +1,7 @@ diff --git a/pages/my/index.vue b/pages/my/index.vue index 2c94bd0..f241ad2 100644 --- a/pages/my/index.vue +++ b/pages/my/index.vue @@ -155,13 +155,12 @@ import { uploadUserAvatar } from '../../config/api/user.js' - import { - URL - } from '../../config/url.js' + import { getCurrentAdvertisement } from '@/config/api/system.js' + import { getInUseOrder } from '@/config/api/order.js' import { useI18n } from '@/utils/i18n.js' // 设置页执行退出登录,此页不再直接调用 - const { t: $t } = useI18n() + const { t } = useI18n() // 响应式状态 const userInfo = ref({}); @@ -175,48 +174,25 @@ import { const bannerImages = ref([]) // 广告图片列表 const bannerImageList = ref([]) // 完整的广告配置列表(包含链接信息) - // 将语言代码转换为后端接受的格式 - const convertLanguageCode = (lang) => { - // zh-CN -> zh_CN (转换下划线) - // en-US -> en_US (转换下划线) - return lang.replace(/-/g, '_') - } - // 获取广告图片 const getBannerImages = async () => { try { - // 获取当前语言设置 - const currentLang = uni.getStorageSync('language') || 'zh-CN' - const languageCode = convertLanguageCode(currentLang) - - console.log('加载个人中心广告,语言:', currentLang, '转换后:', languageCode) - // 调用接口获取广告内容 - const res = await uni.request({ - url: `${URL}/device/advertisementConfig/current`, - method: 'GET', - header: { - 'Content-Language': languageCode - }, - data: { - appPlatform: 'wechat', // 微信平台 - appType: 'user' // 用户端 - } + const res = await getCurrentAdvertisement({ + appPlatform: 'wechat', // 微信平台 + appType: 'user' // 用户端 }) - console.log('个人中心广告响应:', res) - - if (res.statusCode === 200 && res.data.code === 200 && res.data.data) { + if (res && res.code === 200 && res.data) { // 使用 imageList 字段(包含图片和链接信息) - const imageList = res.data.data.imageList || [] + const imageList = res.data.imageList || [] if (imageList.length > 0) { bannerImageList.value = imageList // 提取图片URL用于展示 bannerImages.value = imageList.map(item => item.imageUrl) - console.log('个人中心广告加载成功,图片数量:', imageList.length) } } else { - console.warn('获取个人中心广告失败:', res.data?.msg || '未知错误') + console.warn('获取个人中心广告失败:', res?.msg || '未知错误') } } catch (error) { console.error('获取个人中心广告失败:', error) @@ -226,12 +202,10 @@ import { // 处理广告点击 const handleBannerClick = (index) => { if (!bannerImageList.value || !bannerImageList.value[index]) { - console.warn('未找到对应的广告配置') return } const config = bannerImageList.value[index] - console.log('点击广告:', index, config) // 根据链接类型进行跳转 if (config.linkType === 'miniapp' && config.appId) { @@ -241,12 +215,11 @@ import { appId: config.appId, path: config.linkUrl || '', success: () => { - console.log('跳转小程序成功') }, fail: (err) => { console.error('跳转小程序失败:', err) uni.showToast({ - title: '跳转失败', + title: t('common.loadFailed'), icon: 'none' }) } @@ -254,7 +227,7 @@ import { // #endif // #ifndef MP-WEIXIN uni.showToast({ - title: '请在微信小程序中使用', + title: t('auth.pleaseUseInWechat'), icon: 'none' }) // #endif @@ -268,15 +241,13 @@ import { uni.navigateTo({ url: config.linkUrl }) - } else { - console.log('无有效的跳转配置') } } // 页面加载时初始化 onMounted(() => { uni.setNavigationBarTitle({ - title: $t('user.personalCenter') + title: t('user.personalCenter') }) getInfo(); initVersion(); @@ -293,7 +264,6 @@ import { const getInfo = async () => { try { const res = await getUserInfo(); - console.log('User info response:', res); if (res.code == 401 || res.code == 40101) { redirectToLogin() @@ -317,9 +287,8 @@ import { deposit.value = res.data.balanceAmount || '0.00'; } } catch (error) { - console.error('获取用户信息失败:', error); uni.showToast({ - title: $t('user.getUserInfoFailed'), + title: t('user.getUserInfoFailed'), icon: 'none' }); } @@ -374,43 +343,29 @@ import { const handleQuickReturn = async () => { try { uni.showLoading({ - title: $t('common.loading') + title: t('common.loading') }); // 获取使用中的订单 - const res = await uni.request({ - url: `${URL}/app/order/inUse`, - method: 'GET', - header: { - 'Authorization': "Bearer " + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }); + const res = await getInUseOrder(); uni.hideLoading(); - if (res.statusCode === 401 || res.data?.code === 401 || res.data?.code === 40101) { - redirectToLogin(); - return; - } - - if (res.statusCode === 200 && res.data.code === 200 && res.data.data) { - const inUseOrder = res.data.data; + if (res && res.code === 200 && res.data) { + const inUseOrder = res.data; // 跳转到统一订单详情页面 uni.navigateTo({ url: `/pages/order/detail?orderId=${inUseOrder.orderId}&deviceId=${inUseOrder.deviceNo}` }); } else { uni.showToast({ - title: $t('order.noOrder'), + title: t('order.noOrder'), icon: 'none' }); } } catch (error) { - uni.hideLoading(); - console.error('获取使用中订单失败:', error); uni.showToast({ - title: $t('order.getOrderFailed'), + title: t('order.getOrderFailed'), icon: 'none' }); } @@ -433,7 +388,7 @@ import { // #endif // #ifndef MP-WEIXIN uni.showToast({ - title: $t('auth.pleaseUseInWechat'), + title: t('auth.pleaseUseInWechat'), icon: 'none' }) // #endif @@ -450,13 +405,13 @@ import { const avatarLocalPath = e?.detail?.avatarUrl if (!avatarLocalPath) { uni.showToast({ - title: '未选择头像', + title: t('user.noAvatar'), icon: 'none' }) return } uni.showLoading({ - title: $t('common.uploading'), + title: t('common.uploading'), mask: true }) const uploadRes = await uploadUserAvatar(avatarLocalPath) @@ -469,14 +424,13 @@ import { uni.setStorageSync('userInfo', userInfo.value) } uni.showToast({ - title: '头像已更新', + title: t('user.avatarUpdated'), icon: 'success' }) await getInfo() } catch (err) { - console.error('选择/上传头像失败:', err) uni.showToast({ - title: '头像更新失败', + title: t('user.avatarUploadFailed'), icon: 'none' }) } finally { @@ -494,14 +448,12 @@ import { // 弹窗打开事件处理 const onPopupOpen = () => { - console.log('授权弹窗已打开'); isPopupVisible.value = true; // 这里可以添加弹窗打开后的逻辑 }; // 弹窗关闭事件处理 const onPopupClose = () => { - console.log('授权弹窗已关闭'); isPopupVisible.value = false; // 这里可以添加弹窗关闭后的逻辑 }; @@ -510,7 +462,7 @@ import { const getUserProfile = () => { // #ifdef MP-WEIXIN uni.showLoading({ - title: $t('common.getting'), + title: t('common.getting'), mask: true }); @@ -524,7 +476,7 @@ import { fail: (err) => { console.error('获取用户信息失败:', err); uni.showToast({ - title: '获取用户信息失败', + title: t('user.getUserInfoFailed'), icon: 'none' }); }, @@ -537,7 +489,7 @@ import { // #ifndef MP-WEIXIN uni.showToast({ - title: $t('auth.pleaseUseInWechat'), + title: t('auth.pleaseUseInWechat'), icon: 'none' }); closeAuthPopup(); @@ -566,7 +518,7 @@ import { // }); uni.showToast({ - title: $t('user.updateSuccess'), + title: t('user.updateSuccess'), icon: 'success' }); @@ -575,7 +527,7 @@ import { } catch (error) { console.error('更新用户信息失败:', error); uni.showToast({ - title: $t('user.updateFailed'), + title: t('user.updateFailed'), icon: 'none' }); } @@ -587,7 +539,7 @@ import { const avatarUrl = wxUserInfo?.avatarUrl if (!avatarUrl) { uni.showToast({ - title: '未获取到头像地址', + title: t('user.noAvatarUrl'), icon: 'none' }) return @@ -601,7 +553,7 @@ import { resolve(res.tempFilePath) return } - reject(new Error('头像下载失败')) + reject(new Error(t('user.avatarDownloadFailed'))) }, fail: reject }) @@ -618,14 +570,13 @@ import { uni.setStorageSync('userInfo', userInfo.value) } uni.showToast({ - title: '头像已更新', + title: t('user.avatarUpdated'), icon: 'success' }) await getInfo() } catch (error) { - console.error('头像上传失败:', error) uni.showToast({ - title: '头像上传失败', + title: t('user.avatarUploadFailed'), icon: 'none' }) } finally { @@ -644,7 +595,7 @@ import { // 关于我们 const handleAboutUs = () => { uni.showToast({ - title: $t('help.functionDeveloping'), + title: t('help.functionDeveloping'), icon: 'none' }); }; @@ -652,7 +603,7 @@ import { // 隐私政策 const handlePrivacyPolicy = () => { uni.showToast({ - title: $t('help.functionDeveloping'), + title: t('help.functionDeveloping'), icon: 'none' }); }; diff --git a/pages/order/detail.vue b/pages/order/detail.vue index 0285a42..9ce1f6c 100644 --- a/pages/order/detail.vue +++ b/pages/order/detail.vue @@ -4,7 +4,13 @@ - {{ getOrderStatusText() }} + + {{ getOrderStatusText() }} + + + {{ $t('order.canUsePromotion') }} + + {{ getStatusDesc() }} @@ -78,6 +84,14 @@ {{ $t('order.paymentMethod') }} {{ getPayWayText() }} + + + {{ $t('order.usedPromotion') }} + + + {{ orderInfo.discountTypeName }} + + {{ $t('order.returnTime') }} {{ orderInfo.endTime }} @@ -94,7 +108,7 @@ - 产品归还入仓后,订单仍未结束,请前往客服中心联系工作人员。 + {{ $t('order.returnProblemTip') }}{{ $t('user.customerService') }}{{ $t('order.contactStaff') }} @@ -209,8 +223,12 @@ cancelOrder, reportDeviceNoEject, convertToOwned, - closeWithMaxFee + closeWithMaxFee, + getInUseOrder } from '@/config/api/order.js' + import { + withdrawDeposit + } from '@/config/api/user.js' import { addUserFeedback } from '@/config/api/feedback.js' @@ -222,7 +240,7 @@ } from "@/config/url.js" import { useI18n } from '@/utils/i18n.js' - const { t: $t } = useI18n() + const { t } = useI18n() const instance = getCurrentInstance() const $orderMonitor = instance?.proxy?.$orderMonitor || null @@ -251,7 +269,12 @@ isSupportExpressReturn: 'yes', freeRentTime: '', unitPrice: '', - orderType: '' + orderType: '', + canUseMember: false, + canUseCoupon: false, + userMemberCardId: '', + userPurchaseId: '', + discountTypeName: '' }) const timer = ref(null) const statusCheckTimer = ref(null) @@ -264,8 +287,28 @@ const countdownRemaining = ref(0) const showExpressAction = ref(false) const countdownTimer = ref(null) - const feeRuleText = ref('5.0元/60分钟 前15分钟内归还免费 不足60分钟按60分钟计费 封顶99元 持续计费至99元视为买断') + const feeRuleText = ref('') const convertToOwnPopup = ref(null) + + // 计算属性:是否显示优惠券/会员卡可用提示 + const canUsePromotionTag = computed(() => { + return orderInfo.value.canUseMember === true || orderInfo.value.canUseCoupon === true + }) + + // 计算属性:是否使用了优惠 + const hasUsedPromotion = computed(() => { + return !!(orderInfo.value.userMemberCardId || orderInfo.value.userPurchaseId) + }) + // 获取已使用优惠的文本 + const getUsedPromotionText = () => { + if (orderInfo.value.userMemberCardId) { + return t('user.myCards') + } else if (orderInfo.value.userPurchaseId) { + return t('user.myCoupons') + } + return '-' + } + // 判断订单是否已完成 const isOrderCompleted = () => { return orderInfo.value.orderStatus === 'used_done' || @@ -275,27 +318,27 @@ // 获取订单状态文字 const getOrderStatusText = () => { const statusMap = { - 'waiting_for_payment': $t('order.waitingForPayment'), - 'payment_in_progress': $t('order.paymentInProgress'), - 'payment_successful': $t('order.paymentSuccess'), - 'in_used': $t('order.inUse'), - 'payment_failed': $t('order.paymentFailed'), - 'order_cancelled': $t('order.cancelled'), - 'used_done': $t('order.finished'), - 'used_down': $t('order.finished') + 'waiting_for_payment': t('order.waitingForPayment'), + 'payment_in_progress': t('order.paymentInProgress'), + 'payment_successful': t('order.paymentSuccess'), + 'in_used': t('order.inUse'), + 'payment_failed': t('order.paymentFailed'), + 'order_cancelled': t('order.cancelled'), + 'used_done': t('order.finished'), + 'used_down': t('order.finished') } - return statusMap[orderInfo.value.orderStatus] || $t('order.orderDetail') + return statusMap[orderInfo.value.orderStatus] || t('order.orderDetail') } // 获取状态描述 const getStatusDesc = () => { const descMap = { - 'waiting_for_payment': $t('order.pleasePaySoon'), - 'in_used': $t('order.pleaseReturnInTime'), - 'used_done': $t('order.returnedThankYou'), - 'used_down': $t('order.returnedThankYou'), - 'order_cancelled': $t('order.orderCancelled'), - 'payment_failed': $t('order.paymentFailedRetry') + 'waiting_for_payment': t('order.pleasePaySoon'), + 'in_used': t('order.pleaseReturnInTime'), + 'used_done': t('order.returnedThankYou'), + 'used_down': t('order.returnedThankYou'), + 'order_cancelled': t('order.orderCancelled'), + 'payment_failed': t('order.paymentFailedRetry') } return descMap[orderInfo.value.orderStatus] || '' } @@ -303,11 +346,11 @@ // 获取支付方式文本 const getPayWayText = () => { const payWayMap = { - 'wx_score_pay': $t('order.depositFree'), - 'wx_member_pay': $t('order.memberOrder'), - 'wx_pay': $t('order.depositPay') + 'wx_score_pay': t('order.depositFree'), + 'wx_member_pay': t('order.memberOrder'), + 'wx_pay': t('order.depositPay') } - return payWayMap[orderInfo.value.payWay] || $t('order.depositFree') + return payWayMap[orderInfo.value.payWay] || t('order.depositFree') } // 获取免费时长显示 @@ -321,13 +364,13 @@ if (!orderInfo.value.unitPrice || !orderInfo.value.orderType) return '-' const orderTypeMap = { - 'hours': $t('time.hours'), - 'minutes': $t('time.minutes'), - 'halfhours': $t('time.halfHours') + 'hours': t('time.hours'), + 'minutes': t('time.minutes'), + 'halfhours': t('time.halfHours') } const orderTypeText = orderTypeMap[orderInfo.value.orderType] || orderInfo.value.orderType - return `${orderInfo.value.unitPrice}${$t('unit.yuan')}/${orderTypeText}` + return `${orderInfo.value.unitPrice}${t('unit.yuan')}/${orderTypeText}` } // 格式化倒计时(显示为 HH:MM:SS 格式) @@ -378,21 +421,21 @@ if (totalMinutes >= 60) { const hours = Math.floor(totalMinutes / 60) const minutes = totalMinutes % 60 - usedTime = minutes > 0 ? `${hours}小时${minutes}分钟` : `${hours}小时` + usedTime = minutes > 0 ? `${hours}${t('time.hour')}${minutes}${t('time.minute')}` : `${hours}${t('time.hour')}` } else { - usedTime = `${totalMinutes}分钟` + usedTime = `${totalMinutes}${t('time.minute')}` } } } // 如果还是没有值,使用默认值 if (!usedTime) { - usedTime = '0分钟' + usedTime = `0${t('time.minute')}` } // 解析时长字符串,例如 "1小时5分钟" 或 "5分钟" - const hourMatch = usedTime.match(/(\d+)小时/) - const minuteMatch = usedTime.match(/(\d+)分钟/) + const hourMatch = usedTime.match(new RegExp(`(\\d+)${t('time.hour')}`)) + const minuteMatch = usedTime.match(new RegExp(`(\\d+)${t('time.minute')}`)) let displayNumber = '' let displayUnit = '' @@ -400,19 +443,19 @@ if (hourMatch && minuteMatch) { // 有小时也有分钟,如 "1小时5分钟" displayNumber = `${hourMatch[1]}` - displayUnit = `小时${minuteMatch[1]}分钟` + displayUnit = `${t('time.hour')}${minuteMatch[1]}${t('time.minute')}` } else if (hourMatch) { // 只有小时,如 "1小时" displayNumber = hourMatch[1] - displayUnit = '小时' + displayUnit = t('time.hour') } else if (minuteMatch) { // 只有分钟,如 "5分钟" displayNumber = minuteMatch[1] - displayUnit = '分钟' + displayUnit = t('time.minute') } else { // 默认情况 displayNumber = '0' - displayUnit = '分钟' + displayUnit = t('time.minute') } return { @@ -424,7 +467,7 @@ // 获取使用时长标签文本 const getUsedTimeLabel = () => { // 使用中状态显示"已使用",已完成状态显示"使用时长" - return orderInfo.value.orderStatus === 'in_used' ? $t('order.used') : $t('order.duration') + return orderInfo.value.orderStatus === 'in_used' ? t('order.used') : t('order.duration') } // 获取订单费用(不含单位) @@ -663,7 +706,7 @@ if (currentStatusChecks.value >= maxStatusChecks.value) { clearStatusCheckTimer() uni.showToast({ - title: $t('order.pleaseRefreshManually'), + title: t('order.pleaseRefreshManually'), icon: 'none', duration: 3000 }) @@ -709,6 +752,13 @@ orderInfo.value.unitPrice = orderData.unitPrice || '' orderInfo.value.orderType = orderData.orderType || '' + // 保存优惠券/会员卡相关信息 + orderInfo.value.canUseMember = orderData.canUseMember === true + orderInfo.value.canUseCoupon = orderData.canUseCoupon === true + orderInfo.value.userMemberCardId = orderData.userMemberCardId || '' + orderInfo.value.userPurchaseId = orderData.userPurchaseId || '' + orderInfo.value.discountTypeName = orderData.discountTypeName || '' + // 保存快递归还开始时间(小时为单位) orderInfo.value.expressReturnStart = orderData.expressReturnStart || null @@ -741,7 +791,7 @@ // 显示订单完成提示 if (orderInfo.value.orderStatus === 'used_done' || orderInfo.value.orderStatus === 'used_down') { uni.showToast({ - title: $t('order.orderCompleted'), + title: t('order.orderCompleted'), icon: 'success' }) } @@ -763,7 +813,7 @@ try { if (!orderInfo.value.orderId) { - throw new Error($t('order.orderIdRequired')) + throw new Error(t('order.orderIdRequired')) } isLoadingOrder.value = true @@ -813,12 +863,12 @@ } } } else { - throw new Error(result.msg || $t('order.getOrderFailed')) + throw new Error(result.msg || t('order.getOrderFailed')) } } catch (error) { console.error('获取订单详情错误:', error) uni.showToast({ - title: error.message || $t('order.getOrderFailed'), + title: error.message || t('order.getOrderFailed'), icon: 'none' }) setTimeout(() => { @@ -834,22 +884,15 @@ const getOrderByDevice = async () => { try { if (!deviceId.value) { - throw new Error($t('device.deviceNoRequired')) + throw new Error(t('device.deviceNoRequired')) } - const inUseRes = await uni.request({ - url: `${URL || 'http://127.0.0.1:8080'}/app/order/inUse`, - method: 'GET', - header: { - 'Authorization': "Bearer " + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }) + const inUseRes = await getInUseOrder() console.log('通过设备号查询订单结果:', JSON.stringify(inUseRes)) - if (inUseRes.statusCode === 200 && inUseRes.data.code === 200 && inUseRes.data.data) { - const inUseOrder = inUseRes.data.data + if (inUseRes && inUseRes.code === 200 && inUseRes.data) { + const inUseOrder = inUseRes.data console.log('使用中的订单:', inUseOrder) orderInfo.value.orderId = inUseOrder.orderId @@ -859,12 +902,12 @@ getOrderDetails() } else { - throw new Error($t('order.noOrderInUse')) + throw new Error(t('order.noOrderInUse')) } } catch (error) { console.error('通过设备号查询订单失败:', error) uni.showToast({ - title: error.message || $t('order.getOrderFailed'), + title: error.message || t('order.getOrderFailed'), icon: 'none' }) setTimeout(() => { @@ -885,13 +928,13 @@ // 取消订单 const handleCancelOrder = () => { uni.showModal({ - title: $t('order.confirmCancel'), - content: $t('order.confirmCancelContent'), + title: t('order.confirmCancel'), + content: t('order.confirmCancelContent'), success: async (res) => { if (res.confirm) { try { uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }) const result = await cancelOrder({ orderId: orderInfo.value.orderId @@ -899,17 +942,17 @@ if (result.code === 200) { uni.hideLoading() uni.showToast({ - title: $t('order.cancelSuccess'), + title: t('order.cancelSuccess'), icon: 'success' }) await getOrderDetails() } else { - throw new Error(result.msg || $t('order.cancelFailed')) + throw new Error(result.msg || t('order.cancelFailed')) } } catch (error) { uni.hideLoading() uni.showToast({ - title: error.message || $t('order.cancelFailed'), + title: error.message || t('order.cancelFailed'), icon: 'none' }) } @@ -929,22 +972,14 @@ const handleWithdraw = async () => { try { uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }) - const res = await uni.request({ - url: `${URL || 'http://127.0.0.1:8080'}/app/withdraw/add/${orderInfo.value.orderNo}`, - method: 'GET', - header: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }) + const res = await withdrawDeposit(orderInfo.value.orderNo) - if (res.statusCode === 200 && res.data.code === 200) { + if (res && res.code === 200) { uni.showToast({ - title: $t('order.refundSuccess'), + title: t('order.refundSuccess'), icon: 'success' }) @@ -955,12 +990,12 @@ getOrderDetails() }, 1500) } else { - throw new Error(res.data.msg || $t('order.refundFailed')) + throw new Error(res?.msg || t('order.refundFailed')) } } catch (error) { - console.error('退款申请错误:', error) + console.error('退款申请失败:', error) uni.showToast({ - title: error.message || $t('order.refundFailed'), + title: error.message || t('order.refundFailed'), icon: 'none' }) } finally { @@ -1002,14 +1037,14 @@ }) uni.showToast({ - title: '订阅成功', + title: t('payment.subscriptionSuccess'), icon: 'success', duration: 2000 }) } catch (error) { console.log('订阅消息异常', error) uni.showToast({ - title: '订阅失败,请稍后重试', + title: t('payment.subscriptionFailed'), icon: 'none', duration: 2000 }) @@ -1040,7 +1075,7 @@ try { closeConvertToOwnPopup() uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }) const result = await closeWithMaxFee(orderInfo.value.orderNo) @@ -1048,7 +1083,7 @@ if (result.code === 200) { uni.hideLoading() uni.showToast({ - title: $t('order.convertToOwnWithMaxFeeSuccess'), + title: t('order.convertToOwnWithMaxFeeSuccess'), icon: 'success', duration: 2000 }) @@ -1058,12 +1093,12 @@ getOrderDetails() }, 2000) } else { - throw new Error(result.msg || $t('order.convertToOwnWithMaxFeeFailed')) + throw new Error(result.msg || t('order.convertToOwnWithMaxFeeFailed')) } } catch (error) { uni.hideLoading() uni.showToast({ - title: error.message || $t('order.convertToOwnWithMaxFeeFailed'), + title: error.message || t('order.convertToOwnWithMaxFeeFailed'), icon: 'none', duration: 2000 }) @@ -1076,7 +1111,7 @@ // 设置页面标题 uni.setNavigationBarTitle({ - title: $t('order.orderDetail') + title: t('order.orderDetail') }) isPageActive.value = true @@ -1101,7 +1136,7 @@ getOrderDetails() } else { uni.showToast({ - title: $t('order.orderInfoMissing'), + title: t('order.orderInfoMissing'), icon: 'none' }) setTimeout(() => { @@ -1161,12 +1196,18 @@ .header-left { flex: 1; } + + .header-title-row { + display: flex; + align-items: center; + gap: 12rpx; + margin-bottom: 12rpx; + } .header-title { font-size: 48rpx; font-weight: bold; color: #333; - margin-bottom: 12rpx; } .header-desc { @@ -1210,6 +1251,18 @@ } } } + + .promotion-tag { + padding: 6rpx 16rpx; + background: linear-gradient(135deg, #FFF4E6 0%, #FFE9CC 100%); + border-radius: 10rpx; + border: 1rpx solid #FFB84D; + font-size: 22rpx; + color: #FF8C00; + font-weight: 500; + white-space: nowrap; + flex-shrink: 0; + } // 订单信息卡片 .info-card { @@ -1355,6 +1408,20 @@ color: #333; text-align: right; max-width: 400rpx; + + &.promotion-value { + display: flex; + align-items: center; + justify-content: flex-end; + color: #FF8C00; + font-weight: 500; + + .promotion-icon { + width: 32rpx; + height: 32rpx; + margin-right: 8rpx; + } + } } } diff --git a/pages/order/index.vue b/pages/order/index.vue index 5e3c046..a5d95e4 100644 --- a/pages/order/index.vue +++ b/pages/order/index.vue @@ -46,7 +46,8 @@ getOrderList, queryById, getOrderByOrderNoScorePayStatus, - cancelOrder + cancelOrder, + createWxPayment } from '../../config/api/order.js'; import { confirmPaymentAndRent @@ -59,7 +60,7 @@ } from '../../config/url.js'; import { useI18n } from '@/utils/i18n.js' - const { t: $t } = useI18n() + const { t } = useI18n() // 初始化状态 const currentTab = ref(0); @@ -68,62 +69,62 @@ // 订单状态映射 const orderStatusMap = reactive({ '0': { - get text() { return $t('order.waitingForPayment') }, + get text() { return t('order.waitingForPayment') }, class: 'status-waiting' }, '1': { - get text() { return $t('order.inUse') }, + get text() { return t('order.inUse') }, class: 'status-using' }, '2': { - get text() { return $t('order.finished') }, + get text() { return t('order.finished') }, class: 'status-finished' }, '3': { - get text() { return $t('order.cancelled') }, + get text() { return t('order.cancelled') }, class: 'status-cancelled' }, 'waiting_for_payment': { - get text() { return $t('order.waitingForPayment') }, + get text() { return t('order.waitingForPayment') }, class: 'status-waiting' }, 'in_used': { - get text() { return $t('order.inUse') }, + get text() { return t('order.inUse') }, class: 'status-using' }, 'used_done': { - get text() { return $t('order.finished') }, + get text() { return t('order.finished') }, class: 'status-finished' }, 'order_cancelled': { - get text() { return $t('order.cancelled') }, + get text() { return t('order.cancelled') }, class: 'status-cancelled' }, 'express_return': { - get text() { return $t('express.title') }, + get text() { return t('express.title') }, class: 'status-express-return' } }); // 订单状态标签 const orderStatusTabs = reactive([{ - get text() { return $t('common.all') }, + get text() { return t('common.all') }, status: [] }, { - get text() { return $t('order.waitingForPayment') }, + get text() { return t('order.waitingForPayment') }, status: ['waiting_for_payment'] }, { - get text() { return $t('order.inUse') }, + get text() { return t('order.inUse') }, status: ['in_used'] }, { - get text() { return $t('order.finished') }, + get text() { return t('order.finished') }, status: ['used_done'] }, { - get text() { return $t('order.cancelled') }, + get text() { return t('order.cancelled') }, status: ['order_cancelled'] } ]); @@ -216,7 +217,7 @@ } catch (error) { console.error('获取订单列表失败:', error); uni.showToast({ - title: $t('order.getOrderListFailed'), + title: t('order.getOrderListFailed'), icon: 'none' }); } @@ -233,7 +234,7 @@ // 设置页面标题并监听订单完成事件 onMounted(() => { uni.setNavigationBarTitle({ - title: $t('order.myOrders') + title: t('order.myOrders') }) // 监听订单完成事件 @@ -251,14 +252,14 @@ const res = await getOrderByOrderNoScorePayStatus(order.orderNo); if (res.code === 200) { uni.showToast({ - title: $t('order.syncSuccess'), + title: t('order.syncSuccess'), icon: 'success' }); await loadOrderList(orderStatusTabs[currentTab.value].status); } } catch (error) { uni.showToast({ - title: $t('order.syncFailed'), + title: t('order.syncFailed'), icon: 'none' }); } @@ -285,28 +286,21 @@ const handlePayment = async (order) => { try { uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }); // 调用后端创建微信支付订单接口 - const res = await uni.request({ - url: `${URL || 'http://127.0.0.1:8080'}/app/wx-payment/create/${order.orderNo}`, - method: 'GET', - header: { - 'Authorization': "Bearer " + uni.getStorageSync('token'), - 'Clientid': uni.getStorageSync('client_id') - } - }); + const res = await createWxPayment(order.orderNo); - if (res.statusCode === 200 && res.data.code === 200) { - const payParams = res.data.data; + if (res && res.code === 200) { + const payParams = res.data; // 调用微信支付 await uni.requestPayment({ ...payParams, success: async () => { uni.showToast({ - title: $t('payment.paymentSuccess'), + title: t('payment.paymentSuccess'), icon: 'success' }); @@ -322,18 +316,18 @@ }, fail: (err) => { console.error('支付失败:', err); - throw new Error($t('payment.paymentFailedRetry')); + throw new Error(t('payment.paymentFailedRetry')); } }); } else { - throw new Error(res.data.msg || '创建支付订单失败'); + throw new Error(res?.msg || '创建支付订单失败'); } uni.hideLoading(); } catch (error) { uni.hideLoading(); uni.showToast({ - title: error.message || $t('payment.paymentFailed'), + title: error.message || t('payment.paymentFailed'), icon: 'none' }); } @@ -343,12 +337,12 @@ const handleCancelOrder = async (order) => { try { uni.showModal({ - title: $t('order.confirmCancel'), - content: $t('order.confirmCancelContent'), + title: t('order.confirmCancel'), + content: t('order.confirmCancelContent'), success: async (res) => { if (res.confirm) { uni.showLoading({ - title: $t('common.processing') + title: t('common.processing') }); const result = await cancelOrder({ @@ -358,14 +352,14 @@ if (result) { uni.hideLoading(); uni.showToast({ - title: $t('order.cancelSuccess'), + title: t('order.cancelSuccess'), icon: 'success' }); // 刷新订单列表 await loadOrderList(); } else { - throw new Error(result.msg || $t('order.cancelFailed')); + throw new Error(result.msg || t('order.cancelFailed')); } } } @@ -373,7 +367,7 @@ } catch (error) { uni.hideLoading(); uni.showToast({ - title: error.message || $t('order.cancelFailed'), + title: error.message || t('order.cancelFailed'), icon: 'none' }); } diff --git a/pages/order/payment.vue b/pages/order/payment.vue index 9f1b8f7..014a76f 100644 --- a/pages/order/payment.vue +++ b/pages/order/payment.vue @@ -59,345 +59,219 @@ - \ No newline at end of file diff --git a/pages/return/index.vue b/pages/return/index.vue index 4229387..273eb7a 100644 --- a/pages/return/index.vue +++ b/pages/return/index.vue @@ -143,7 +143,8 @@