feat:国际化多语言适配
This commit is contained in:
+24
-20
@@ -2,27 +2,27 @@
|
||||
<view class="deposit-container">
|
||||
<!-- 押金金额卡片 -->
|
||||
<view class="deposit-card">
|
||||
<view class="title">押金余额</view>
|
||||
<view class="title">{{ $t('deposit.depositBalance') }}</view>
|
||||
<view class="amount">¥{{ depositAmount }}</view>
|
||||
<button class="withdraw-btn" @click="handleWithdraw" :disabled="depositAmount <= 0">提现</button>
|
||||
<button class="withdraw-btn" @click="handleWithdraw" :disabled="depositAmount <= 0">{{ $t('deposit.withdraw') }}</button>
|
||||
</view>
|
||||
|
||||
<!-- 提现说明 -->
|
||||
<view class="notice-card">
|
||||
<view class="notice-title">
|
||||
<view class="dot"></view>
|
||||
<text>提现说明</text>
|
||||
<text>{{ $t('deposit.withdrawNotice') }}</text>
|
||||
</view>
|
||||
<view class="notice-content">
|
||||
<view class="notice-item">1. 提现金额将原路退回支付账户</view>
|
||||
<view class="notice-item">2. 提现申请提交后预计0-7个工作日到账</view>
|
||||
<view class="notice-item">3. 如超时未收到,请联系客服处理</view>
|
||||
<view class="notice-item">1. {{ $t('deposit.withdrawNotice1') }}</view>
|
||||
<view class="notice-item">2. {{ $t('deposit.withdrawNotice2') }}</view>
|
||||
<view class="notice-item">3. {{ $t('deposit.withdrawNotice3') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 押金记录 -->
|
||||
<view class="record-card" v-if="records.length > 0">
|
||||
<view class="record-title">押金记录</view>
|
||||
<view class="record-title">{{ $t('deposit.depositRecord') }}</view>
|
||||
<view class="record-list">
|
||||
<view class="record-item" v-for="(item, index) in records" :key="index">
|
||||
<view class="record-info">
|
||||
@@ -53,6 +53,10 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('deposit.title')
|
||||
})
|
||||
// this.loadUserInfo()
|
||||
},
|
||||
onShow() {
|
||||
@@ -84,7 +88,7 @@ export default {
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
title: this.$t('user.getUserInfoFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -92,7 +96,7 @@ export default {
|
||||
async handleWithdraw() {
|
||||
if (parseFloat(this.depositAmount) <= 0) {
|
||||
uni.showToast({
|
||||
title: '无可提现余额',
|
||||
title: this.$t('deposit.noBalance'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -111,12 +115,12 @@ export default {
|
||||
// }
|
||||
|
||||
uni.showModal({
|
||||
title: '确认提现',
|
||||
content: '押金将原路退回,预计0-7个工作日到账',
|
||||
title: this.$t('deposit.confirmWithdraw'),
|
||||
content: this.$t('deposit.withdrawDesc'),
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '提现中...'
|
||||
title: this.$t('deposit.withdrawing')
|
||||
})
|
||||
|
||||
try {
|
||||
@@ -127,7 +131,7 @@ export default {
|
||||
if (result.code === 200) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '提现申请已提交',
|
||||
title: this.$t('deposit.withdrawSubmitted'),
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
@@ -144,26 +148,26 @@ export default {
|
||||
this.loadUserInfo()
|
||||
}, 1500)
|
||||
} else {
|
||||
throw new Error(result.msg || '提现失败')
|
||||
throw new Error(result.msg || this.$t('deposit.withdrawFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提现失败:', error)
|
||||
uni.hideLoading()
|
||||
|
||||
// 更详细的错误处理
|
||||
let errorMessage = '提现失败,请稍后再试';
|
||||
let errorMessage = this.$t('deposit.withdrawFailed');
|
||||
|
||||
// 如果有具体错误信息,使用它
|
||||
if (error.message) {
|
||||
// 常见错误消息处理
|
||||
if (error.message.includes('尚未归还')) {
|
||||
errorMessage = '当前订单尚未归还,请归还后再提现';
|
||||
errorMessage = this.$t('deposit.orderNotReturned');
|
||||
} else if (error.message.includes('已退还')) {
|
||||
errorMessage = '押金已退还,无需重复提现';
|
||||
errorMessage = this.$t('deposit.alreadyRefunded');
|
||||
} else if (error.message.includes('处理中')) {
|
||||
errorMessage = '押金退还处理中,请耐心等待';
|
||||
errorMessage = this.$t('deposit.refundProcessing');
|
||||
} else if (error.message.includes('余额为0')) {
|
||||
errorMessage = '账户余额为0,无法提现';
|
||||
errorMessage = this.$t('deposit.noBalance');
|
||||
} else {
|
||||
// 使用后端返回的具体错误消息
|
||||
errorMessage = error.message;
|
||||
@@ -172,7 +176,7 @@ export default {
|
||||
|
||||
// 显示错误提示
|
||||
uni.showModal({
|
||||
title: '提现失败',
|
||||
title: this.$t('deposit.withdrawFailed'),
|
||||
content: errorMessage,
|
||||
showCancel: false
|
||||
})
|
||||
|
||||
+55
-49
@@ -12,7 +12,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="device-id">
|
||||
<text class="id-label">设备号:</text>
|
||||
<text class="id-label">{{ $t('device.deviceNo') }}:</text>
|
||||
<text class="id-value">{{ deviceId }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -20,17 +20,17 @@
|
||||
<!-- 计费规则 -->
|
||||
<view class="card pricing-card">
|
||||
<view class="card-header">
|
||||
<text class="card-title">计费规则</text>
|
||||
<text class="card-title">{{ $t('device.pricingRules') }}</text>
|
||||
</view>
|
||||
|
||||
<view class="pricing-banner">
|
||||
<view class="pricing-main">
|
||||
<text class="price-symbol">¥</text>
|
||||
<text class="price">{{ deviceFeeConfig.maxHourPrice || '5.00' }}</text>
|
||||
<text class="unit">/小时</text>
|
||||
<text class="unit">/{{ $t('time.hour') }}</text>
|
||||
</view>
|
||||
<view class="cap-badge">
|
||||
<text class="cap-text">{{ deviceInfo.depositAmount || '99' }}元封顶</text>
|
||||
<text class="cap-text">{{ deviceInfo.depositAmount || '99' }}{{ $t('device.capLimit') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -51,20 +51,20 @@
|
||||
<!-- 使用说明 -->
|
||||
<view class="card notice-card">
|
||||
<view class="card-header">
|
||||
<text class="card-title">使用说明</text>
|
||||
<text class="card-title">{{ $t('device.usageInstructions') }}</text>
|
||||
</view>
|
||||
<view class="notice-items">
|
||||
<view class="notice-item">
|
||||
<view class="notice-dot"></view>
|
||||
<text class="notice-text">请在使用前检查设备是否完好</text>
|
||||
<text class="notice-text">{{ $t('device.checkBeforeUse') }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="notice-dot"></view>
|
||||
<text class="notice-text">超出使用时间将自动按小时计费</text>
|
||||
<text class="notice-text">{{ $t('device.autoChargeOvertime') }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="notice-dot"></view>
|
||||
<text class="notice-text">请在指定区域内使用设备</text>
|
||||
<text class="notice-text">{{ $t('device.useInDesignatedArea') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -73,11 +73,11 @@
|
||||
<view class="footer">
|
||||
<button class="rent-button" :class="{ 'return-button': hasActiveOrder }"
|
||||
@click="handleRent('wx-score-pay')">
|
||||
<text>{{ hasActiveOrder ? '归还设备' : '免押金租借' }}</text>
|
||||
<text>{{ hasActiveOrder ? $t('order.returnDevice') : $t('device.rentDepositFree') }}</text>
|
||||
</button>
|
||||
<view class="wechat-credit">
|
||||
<image src="/static/images/wxpayflag.png" mode="aspectFit" class="wx-icon"></image>
|
||||
<text class="credit-text">微信支付分 <text class="divider">|</text> 550分以上优享</text>
|
||||
<text class="credit-text">{{ $t('device.wxPayScoreDesc') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -86,17 +86,17 @@
|
||||
<view class="popup-mask" @click.stop></view>
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">授权获取手机号</text>
|
||||
<text class="popup-title">{{ $t('auth.authTitle') }}</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="auth-desc">
|
||||
<text>为了提供更好的服务,需要授权获取您的手机号</text>
|
||||
<text>{{ $t('auth.authDescShort') }}</text>
|
||||
</view>
|
||||
<button class="auth-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
|
||||
一键获取手机号
|
||||
{{ $t('auth.getPhoneNumber') }}
|
||||
</button>
|
||||
<view class="auth-cancel" @click="showPhoneAuthPopup = false">
|
||||
<text>暂不授权</text>
|
||||
<text>{{ $t('auth.notNow') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -133,6 +133,9 @@
|
||||
getUserInfo,
|
||||
getUserPhoneNumber
|
||||
} from '@/util/index.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 响应式状态
|
||||
const deviceInfo = ref({})
|
||||
@@ -143,7 +146,7 @@
|
||||
const batteryLevel = ref(95)
|
||||
const hasActiveOrder = ref(false)
|
||||
const deviceStatus = reactive({
|
||||
text: '可使用',
|
||||
get text() { return $t('device.available') },
|
||||
class: 'available'
|
||||
})
|
||||
const isLoggedIn = ref(true)
|
||||
@@ -164,6 +167,9 @@
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('device.deviceInfo')
|
||||
})
|
||||
await checkUserPhone()
|
||||
await fetchDeviceInfo()
|
||||
})
|
||||
@@ -195,7 +201,7 @@
|
||||
// 用户拒绝授权的情况
|
||||
if (e.detail.errMsg && e.detail.errMsg.includes('deny')) {
|
||||
uni.showToast({
|
||||
title: '需要授权手机号才能使用设备',
|
||||
title: $t('auth.phoneRequired'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -204,7 +210,7 @@
|
||||
// 获取到授权code
|
||||
if (e.detail.code) {
|
||||
uni.showLoading({
|
||||
title: '获取中...'
|
||||
title: $t('auth.getting')
|
||||
})
|
||||
|
||||
console.log('获取到的授权code:', e.detail.code)
|
||||
@@ -236,15 +242,15 @@
|
||||
showPhoneAuthPopup.value = false
|
||||
|
||||
uni.showToast({
|
||||
title: '手机号获取成功',
|
||||
title: $t('auth.phoneSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
// 记录详细信息,不抛出错误
|
||||
console.warn('获取手机号响应异常:', res.msg || '未知错误')
|
||||
uni.showModal({
|
||||
title: '获取手机号异常',
|
||||
content: `状态码: ${res.code}, 消息: ${res.msg || '无'}`,
|
||||
title: $t('auth.phoneError'),
|
||||
content: `${$t('common.statusCode')}: ${res.code}, ${$t('common.message')}: ${res.msg || $t('common.none')}`,
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
@@ -256,8 +262,8 @@
|
||||
// 显示更详细的错误信息
|
||||
let errMsg = err.message || err.toString()
|
||||
uni.showModal({
|
||||
title: '获取手机号失败',
|
||||
content: '错误信息: ' + errMsg,
|
||||
title: $t('auth.phoneGetFailed'),
|
||||
content: $t('common.errorInfo') + ': ' + errMsg,
|
||||
showCancel: false
|
||||
})
|
||||
})
|
||||
@@ -265,14 +271,14 @@
|
||||
uni.hideLoading()
|
||||
console.error('获取手机号外部错误:', outerError)
|
||||
uni.showModal({
|
||||
title: '意外错误',
|
||||
content: '处理过程发生异常: ' + (outerError.message || outerError),
|
||||
title: $t('common.unexpectedError'),
|
||||
content: $t('common.processException') + ': ' + (outerError.message || outerError),
|
||||
showCancel: false
|
||||
})
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '获取授权码失败',
|
||||
title: $t('auth.authCodeFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -296,16 +302,16 @@
|
||||
deviceLocation.value = res.data.position.name
|
||||
}
|
||||
|
||||
// 更新设备状态
|
||||
if (deviceInfo.value.status) {
|
||||
if (deviceInfo.value.status === 'online') {
|
||||
deviceStatus.text = '可使用'
|
||||
deviceStatus.class = 'available'
|
||||
} else if (deviceInfo.value.status === 'offline') {
|
||||
deviceStatus.text = '离线'
|
||||
deviceStatus.class = 'offline'
|
||||
}
|
||||
// 更新设备状态
|
||||
if (deviceInfo.value.status) {
|
||||
if (deviceInfo.value.status === 'online') {
|
||||
deviceStatus.text = $t('device.available')
|
||||
deviceStatus.class = 'available'
|
||||
} else if (deviceInfo.value.status === 'offline') {
|
||||
deviceStatus.text = $t('device.offline')
|
||||
deviceStatus.class = 'offline'
|
||||
}
|
||||
}
|
||||
if (deviceInfo.value.feeConfig) {
|
||||
deviceFeeConfig.value = JSON.parse(deviceInfo.value.feeConfig)[0] || {}
|
||||
} else {
|
||||
@@ -321,9 +327,9 @@
|
||||
// 显示登录提示
|
||||
const showLoginTip = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '请先登录后再操作',
|
||||
confirmText: '去登录',
|
||||
title: $t('common.tips'),
|
||||
content: $t('common.loginRequired'),
|
||||
confirmText: $t('auth.goToLogin'),
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.navigateTo({
|
||||
@@ -358,7 +364,7 @@
|
||||
}
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '订单状态查询失败',
|
||||
title: $t('order.getOrderStatusFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -444,6 +450,9 @@
|
||||
// 提交租借订单
|
||||
const submitRentOrder = async (payWay) => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: $t('common.processing')
|
||||
})
|
||||
// --- 第一步:先请求订阅消息(必须在用户点击的同步上下文中)---
|
||||
if (payWay === 'wx-score-pay') {
|
||||
console.log('准备请求订阅消息(在异步操作之前),时间:', new Date().toLocaleTimeString());
|
||||
@@ -471,14 +480,11 @@
|
||||
}
|
||||
// --- 订阅消息请求完成 ---
|
||||
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
})
|
||||
console.log(deviceId.value);
|
||||
// 调用设备租借接口
|
||||
const rentResult = await rentPowerBank(deviceId.value, phoneNumber.value)
|
||||
if (rentResult.code !== 200) {
|
||||
throw new Error(rentResult.msg || '设备租借失败')
|
||||
throw new Error(rentResult.msg || $t('device.rentFailed'))
|
||||
}
|
||||
|
||||
// 获取后端返回的订单信息
|
||||
@@ -556,14 +562,14 @@
|
||||
// 用户取消授权,需要取消订单
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '取消订单中'
|
||||
title: $t('order.cancelling')
|
||||
});
|
||||
const cancelRes = await cancelOrder({ orderId: order.orderNo });
|
||||
console.log('订单取消结果:', cancelRes);
|
||||
uni.hideLoading();
|
||||
|
||||
uni.showToast({
|
||||
title: '已取消订单',
|
||||
title: $t('order.orderCancelled'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
@@ -578,7 +584,7 @@
|
||||
console.error('取消订单失败:', cancelError);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '取消订单失败,请联系客服',
|
||||
title: $t('order.cancelFailedContactService'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -589,7 +595,7 @@
|
||||
// 支付分调用异常,也需要取消订单
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '取消订单中'
|
||||
title: $t('order.cancelling')
|
||||
});
|
||||
const cancelRes = await cancelOrder({ orderId: order.orderNo });
|
||||
console.log('订单取消结果:', cancelRes);
|
||||
@@ -600,7 +606,7 @@
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: '支付分调用失败,订单已取消',
|
||||
title: $t('device.payScoreFailedCancelled'),
|
||||
icon: 'none'
|
||||
});
|
||||
|
||||
@@ -612,7 +618,7 @@
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取支付参数失败',
|
||||
title: res?.msg || $t('device.getPayParamsFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -620,7 +626,7 @@
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '租借失败,请重试',
|
||||
title: error.message || $t('device.rentFailedRetry'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,32 +3,32 @@
|
||||
<!-- 订单摘要卡片 -->
|
||||
<view class="order-summary-card" v-if="orderInfo.orderNo">
|
||||
<view class="summary-row">
|
||||
<view class="label">订单号</view>
|
||||
<view class="label">{{ $t('order.orderNo') }}</view>
|
||||
<view class="value">{{ orderInfo.orderNo }}</view>
|
||||
</view>
|
||||
<view class="summary-row" v-if="orderInfo.deviceNo">
|
||||
<view class="label">设备号</view>
|
||||
<view class="label">{{ $t('order.deviceNo') }}</view>
|
||||
<view class="value">{{ orderInfo.deviceNo }}</view>
|
||||
</view>
|
||||
<view class="summary-row" v-if="orderInfo.startTime">
|
||||
<view class="label">开放时间</view>
|
||||
<view class="label">{{ $t('express.openTime') }}</view>
|
||||
<view class="value">{{ orderInfo.startTime }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单区域 -->
|
||||
<view class="form-section">
|
||||
<view class="form-title">填写快递归还信息</view>
|
||||
<view class="form-title">{{ $t('express.fillExpressInfo') }}</view>
|
||||
|
||||
<view class="input-wrapper">
|
||||
<view class="input-label">联系电话</view>
|
||||
<view class="input-label">{{ $t('express.contactPhone') }}</view>
|
||||
<input class="input-field" type="number" v-model="phone" maxlength="20" />
|
||||
</view>
|
||||
|
||||
<view class="input-wrapper">
|
||||
<view class="input-label">快递单号</view>
|
||||
<view class="input-label">{{ $t('express.expressNo') }}</view>
|
||||
<input class="input-field" type="text" v-model="trackingNumber"
|
||||
:placeholder="isFillMode ? '请输入需要补填的快递单号' : '请输入快递单号(可先留空)'" maxlength="40" />
|
||||
:placeholder="isFillMode ? $t('express.fillTrackingPlaceholder') : $t('express.trackingPlaceholder')" maxlength="40" />
|
||||
</view>
|
||||
|
||||
<view class="tips" v-if="tipsText">{{ tipsText }}</view>
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-btn" :class="{ disabled: submitting }" @click="!submitting && handleSubmit()">
|
||||
{{ isFillMode ? '确认补填' : '提交信息' }}
|
||||
{{ isFillMode ? $t('express.confirmFill') : $t('express.submitInfo') }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -44,7 +44,9 @@
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive
|
||||
reactive,
|
||||
getCurrentInstance,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad
|
||||
@@ -58,6 +60,15 @@
|
||||
getExpressReturnDetail,
|
||||
fillExpressTrackingNumber
|
||||
} from '@/config/api/expressReturn.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('express.fillExpress')
|
||||
})
|
||||
})
|
||||
|
||||
const orderId = ref('')
|
||||
const recordId = ref('')
|
||||
@@ -85,7 +96,7 @@
|
||||
|
||||
if (!orderId.value) {
|
||||
uni.showToast({
|
||||
title: '缺少订单号',
|
||||
title: $t('express.orderNoMissing'),
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
@@ -100,7 +111,7 @@
|
||||
const loadOrder = async () => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
title: $t('common.loading')
|
||||
})
|
||||
const res = await queryById(orderId.value)
|
||||
if (res?.code === 200 && res.data) {
|
||||
@@ -110,11 +121,11 @@
|
||||
// 默认联系电话可回填订单上的手机号(若有)
|
||||
if (res.data.phone && !phone.value) phone.value = res.data.phone
|
||||
} else {
|
||||
throw new Error(res?.msg || '获取订单失败')
|
||||
throw new Error(res?.msg || $t('order.getOrderFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: e.message || '加载失败',
|
||||
title: e.message || $t('express.loadFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
@@ -125,7 +136,7 @@
|
||||
const loadRecordAndOrderByRecord = async () => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
title: $t('common.loading')
|
||||
})
|
||||
const res = await getExpressReturnDetail(recordId.value)
|
||||
if (res?.code === 200 && res.data) {
|
||||
@@ -135,11 +146,11 @@
|
||||
}
|
||||
if (res.data.userPhone && !phone.value) phone.value = res.data.userPhone
|
||||
} else {
|
||||
throw new Error(res?.msg || '获取记录失败')
|
||||
throw new Error(res?.msg || $t('express.getRecordFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: e.message || '加载失败',
|
||||
title: e.message || $t('express.loadFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
@@ -155,10 +166,10 @@
|
||||
if (rec.status === 0) {
|
||||
recordId.value = rec.id
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '已存在快递归还申请,是否前往补填快递单号?',
|
||||
confirmText: '去补填',
|
||||
cancelText: '取消',
|
||||
title: $t('common.tips'),
|
||||
content: $t('express.existingReturnNotice'),
|
||||
confirmText: $t('express.goToFill'),
|
||||
cancelText: $t('common.cancel'),
|
||||
success: (r) => {
|
||||
if (r.confirm) {
|
||||
uni.redirectTo({
|
||||
@@ -170,7 +181,7 @@
|
||||
return
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '已有归还记录',
|
||||
title: $t('express.alreadyHasRecord'),
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
@@ -190,14 +201,14 @@
|
||||
const digits = (phone.value || '').replace(/\D/g, '')
|
||||
if (!digits || digits.length < 5) {
|
||||
uni.showToast({
|
||||
title: '请填写有效联系电话',
|
||||
title: $t('express.pleaseEnterValidPhone'),
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
}
|
||||
if (isFillMode.value && !trackingNumber.value) {
|
||||
uni.showToast({
|
||||
title: '请填写快递单号',
|
||||
title: $t('express.pleaseEnterTrackingNo'),
|
||||
icon: 'none'
|
||||
})
|
||||
return false
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
<!-- 快递信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">
|
||||
<text class="title-text">快递信息</text>
|
||||
<text class="title-text">{{ $t('express.expressInfo') }}</text>
|
||||
</view>
|
||||
<view class="info-list">
|
||||
<view class="info-item">
|
||||
<text class="label">快递公司</text>
|
||||
<text class="label">{{ $t('express.expressCompany') }}</text>
|
||||
<text class="value">{{ detailData.expressCompany }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">运单号</text>
|
||||
<text class="label">{{ $t('express.trackingNo') }}</text>
|
||||
<text class="value tracking-number">{{ detailData.trackingNumber }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">包裹类型</text>
|
||||
<text class="label">{{ $t('express.packageType') }}</text>
|
||||
<text class="value">{{ detailData.packageType }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">包裹重量</text>
|
||||
<text class="label">{{ $t('express.packageWeight') }}</text>
|
||||
<text class="value">{{ detailData.weight }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -41,23 +41,23 @@
|
||||
<!-- 归还信息卡片 -->
|
||||
<view class="info-card">
|
||||
<view class="card-title">
|
||||
<text class="title-text">归还信息</text>
|
||||
<text class="title-text">{{ $t('express.returnInfo') }}</text>
|
||||
</view>
|
||||
<view class="info-list">
|
||||
<view class="info-item">
|
||||
<text class="label">归还地址</text>
|
||||
<text class="label">{{ $t('express.returnAddress') }}</text>
|
||||
<text class="value address">{{ detailData.returnAddress }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">归还时间</text>
|
||||
<text class="label">{{ $t('express.returnTime') }}</text>
|
||||
<text class="value">{{ detailData.returnTime }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">处理时间</text>
|
||||
<text class="label">{{ $t('express.processTime') }}</text>
|
||||
<text class="value">{{ detailData.processTime || '--' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">完成时间</text>
|
||||
<text class="label">{{ $t('express.completeTime') }}</text>
|
||||
<text class="value">{{ detailData.completeTime || '--' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -66,7 +66,7 @@
|
||||
<!-- 备注信息卡片 -->
|
||||
<view class="info-card" v-if="detailData.remark">
|
||||
<view class="card-title">
|
||||
<text class="title-text">备注信息</text>
|
||||
<text class="title-text">{{ $t('express.remarkInfo') }}</text>
|
||||
</view>
|
||||
<view class="remark-content">
|
||||
<text class="remark-text">{{ detailData.remark }}</text>
|
||||
@@ -76,10 +76,10 @@
|
||||
<!-- 操作按钮 -->
|
||||
<view class="action-buttons">
|
||||
<button class="action-btn primary" @click="handleCopyTracking">
|
||||
<text class="btn-text">复制运单号</text>
|
||||
<text class="btn-text">{{ $t('express.copyTrackingNo') }}</text>
|
||||
</button>
|
||||
<button class="action-btn secondary" @click="handleContactService">
|
||||
<text class="btn-text">联系客服</text>
|
||||
<text class="btn-text">{{ $t('user.customerService') }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -89,6 +89,9 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getExpressReturnDetail } from '@/config/api/expressReturn.js'
|
||||
import { getCustomerPhone } from '@/util/index.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 详情数据
|
||||
const detailData = ref({
|
||||
@@ -128,21 +131,21 @@ const getStatusIcon = (status) => {
|
||||
// 获取状态文本
|
||||
const getStatusText = (status) => {
|
||||
const textMap = {
|
||||
'completed': '归还完成',
|
||||
'processing': '处理中',
|
||||
'pending': '待处理'
|
||||
'completed': $t('express.returnCompleted'),
|
||||
'processing': $t('express.processing'),
|
||||
'pending': $t('express.pending')
|
||||
}
|
||||
return textMap[status] || '待处理'
|
||||
return textMap[status] || $t('express.pending')
|
||||
}
|
||||
|
||||
// 获取状态描述
|
||||
const getStatusDesc = (status) => {
|
||||
const descMap = {
|
||||
'completed': '您的快递已成功归还',
|
||||
'processing': '正在处理您的归还请求',
|
||||
'pending': '等待处理归还申请'
|
||||
'completed': $t('express.returnCompletedDesc'),
|
||||
'processing': $t('express.processingDesc'),
|
||||
'pending': $t('express.pendingDesc')
|
||||
}
|
||||
return descMap[status] || '等待处理归还申请'
|
||||
return descMap[status] || $t('express.pendingDesc')
|
||||
}
|
||||
|
||||
// 复制运单号
|
||||
@@ -151,7 +154,7 @@ const handleCopyTracking = () => {
|
||||
data: detailData.value.trackingNumber,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '运单号已复制',
|
||||
title: $t('express.trackingNoCopied'),
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
@@ -162,10 +165,10 @@ const handleCopyTracking = () => {
|
||||
const handleContactService = () => {
|
||||
const customerPhone = getCustomerPhone()
|
||||
uni.showModal({
|
||||
title: '联系客服',
|
||||
content: `客服电话:${customerPhone}\n工作时间:周一至周日 09:00-22:00`,
|
||||
confirmText: '拨打',
|
||||
cancelText: '取消',
|
||||
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({
|
||||
@@ -178,12 +181,16 @@ const handleContactService = () => {
|
||||
|
||||
// 页面加载时获取详情数据
|
||||
onMounted(async () => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('express.returnDetail')
|
||||
})
|
||||
|
||||
const pages = getCurrentPages()
|
||||
const currentPage = pages[pages.length - 1]
|
||||
const options = currentPage.options || {}
|
||||
if (!options.id) return
|
||||
try {
|
||||
uni.showLoading({ title: '加载中' })
|
||||
uni.showLoading({ title: $t('common.loading') })
|
||||
const res = await getExpressReturnDetail(options.id)
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const r = res.data
|
||||
@@ -201,10 +208,10 @@ onMounted(async () => {
|
||||
remark: r.remark || ''
|
||||
}
|
||||
} else {
|
||||
throw new Error(res?.msg || '获取详情失败')
|
||||
throw new Error(res?.msg || $t('express.getDetailFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({ title: e.message || '加载失败', icon: 'none' })
|
||||
uni.showToast({ title: e.message || $t('express.loadFailed'), icon: 'none' })
|
||||
} finally {
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
<view class="express-return-container">
|
||||
<!-- 收件信息卡片 -->
|
||||
<view class="recipient-info-card">
|
||||
<view class="info-header">收件信息</view>
|
||||
<view class="info-header">{{ $t('express.recipientInfo') }}</view>
|
||||
<view class="info-content">
|
||||
<text class="recipient-name">风电者 18163601305</text>
|
||||
<text class="recipient-address">湖南省长沙市岳麓区麓谷街道新长海尖科技园A2栋623</text>
|
||||
<text class="recipient-name">{{ $t('express.recipientName') }}</text>
|
||||
<text class="recipient-address">{{ $t('express.recipientAddress') }}</text>
|
||||
</view>
|
||||
<view class="copy-all-btn" @click="copyAllInfo">
|
||||
<text class="btn-text">一键复制全部信息</text>
|
||||
<text class="btn-text">{{ $t('express.copyAllInfo') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
<text class="status-label">{{ getStatusText(item.status) }}</text>
|
||||
</view>
|
||||
<view class="content-body">
|
||||
<text class="info-text">订单号:{{ item.orderId || '' }}</text>
|
||||
<text class="info-text">快递单号:{{ item.trackingNumber || '待填写' }}</text>
|
||||
<text class="info-text">用户电话:{{ item.userPhone || '' }}</text>
|
||||
<text class="info-text">{{ $t('order.orderNo') }}:{{ item.orderId || '' }}</text>
|
||||
<text class="info-text">{{ $t('express.expressNo') }}:{{ item.trackingNumber || $t('express.toFill') }}</text>
|
||||
<text class="info-text">{{ $t('express.userPhone') }}:{{ item.userPhone || '' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="returnList.length === 0">
|
||||
<view class="empty-icon">📦</view>
|
||||
<text class="empty-text">暂无归还记录</text>
|
||||
<text class="empty-text">{{ $t('express.noReturnRecord') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -52,11 +52,21 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getExpressReturnList } from '@/config/api/expressReturn.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
const returnList = ref([])
|
||||
const loading = ref(false)
|
||||
const query = ref({ pageNum: 1, pageSize: 20 })
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('express.returnRecord')
|
||||
})
|
||||
loadList()
|
||||
})
|
||||
|
||||
// 收件信息
|
||||
const recipientName = '风电者 18163601305'
|
||||
const recipientAddress = '湖南省长沙市岳麓区麓谷街道新长海尖科技园A2栋623'
|
||||
@@ -83,10 +93,10 @@ const loadList = async () => {
|
||||
remark: r.remark
|
||||
}))
|
||||
} else {
|
||||
throw new Error(res?.msg || '获取列表失败')
|
||||
throw new Error(res?.msg || $t('express.getListFailed'))
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({ title: e.message || '加载失败', icon: 'none' })
|
||||
uni.showToast({ title: e.message || $t('express.loadFailed'), icon: 'none' })
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
@@ -108,27 +118,27 @@ const getStatusClass = (status) => ({
|
||||
}[status] || 'status-pending')
|
||||
|
||||
const getStatusText = (status) => ({
|
||||
'completed': '暂停计费中',
|
||||
'processing': '暂停计费中',
|
||||
'pending': '暂停计费中'
|
||||
}[status] || '暂停计费中')
|
||||
'completed': $t('express.billingPaused'),
|
||||
'processing': $t('express.billingPaused'),
|
||||
'pending': $t('express.billingPaused')
|
||||
}[status] || $t('express.billingPaused'))
|
||||
|
||||
const getStatusBadge = (status) => ({
|
||||
'completed': '已完成',
|
||||
'processing': '处理中',
|
||||
'pending': '待处理'
|
||||
}[status] || '待处理')
|
||||
'completed': $t('express.completed'),
|
||||
'processing': $t('express.processing'),
|
||||
'pending': $t('express.pending')
|
||||
}[status] || $t('express.pending'))
|
||||
|
||||
// 一键复制全部信息
|
||||
const copyAllInfo = () => {
|
||||
const allInfo = `收件人:${recipientName}\n收件地址:${recipientAddress}`
|
||||
const allInfo = `${$t('express.recipient')}:${recipientName}\n${$t('express.recipientAddressLabel')}:${recipientAddress}`
|
||||
uni.setClipboardData({
|
||||
data: allInfo,
|
||||
success: () => {
|
||||
uni.showToast({ title: '全部信息已复制', icon: 'success' })
|
||||
uni.showToast({ title: $t('express.copySuccess'), icon: 'success' })
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '复制失败', icon: 'none' })
|
||||
uni.showToast({ title: $t('express.copyFailed'), icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -144,7 +154,6 @@ const handleItemClick = (item) => {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadList)
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
+51
-41
@@ -1,58 +1,59 @@
|
||||
<template>
|
||||
<view class="feedback-container">
|
||||
<!-- <form> -->
|
||||
<!-- 问题类型选择 -->
|
||||
<view class="type-section">
|
||||
<view class="section-title">问题类型</view>
|
||||
<view class="type-grid">
|
||||
<view v-for="(type, index) in types" :key="index" class="type-item"
|
||||
:class="{ active: selectedType === index }" @click="selectType(index)">
|
||||
{{ type }}
|
||||
</view>
|
||||
<!-- 问题类型选择 -->
|
||||
<view class="type-section">
|
||||
<view class="section-title">{{ $t('feedback.issueType') }}</view>
|
||||
<view class="type-grid">
|
||||
<view v-for="(type, index) in types" :key="index" class="type-item"
|
||||
:class="{ active: selectedType === index }" @click="selectType(index)">
|
||||
{{ type }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 问题描述 -->
|
||||
<view class="description-section">
|
||||
<view class="section-title">问题描述</view>
|
||||
<textarea class="description-input" v-model="description" placeholder="请详细描述您遇到的问题,以便我们更好地为您解决"
|
||||
maxlength="500" name="description" />
|
||||
<view class="word-count">{{ description.length }}/500</view>
|
||||
</view>
|
||||
<!-- 问题描述 -->
|
||||
<view class="description-section">
|
||||
<view class="section-title">{{ $t('feedback.issueDescription') }}</view>
|
||||
<textarea class="description-input" v-model="description" :placeholder="$t('feedback.placeholder')"
|
||||
maxlength="500" name="description" />
|
||||
<view class="word-count">{{ description.length }}/500</view>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="upload-section">
|
||||
<view class="section-title">图片上传(选填)</view>
|
||||
<!-- 图片上传 -->
|
||||
<view class="upload-section">
|
||||
<view class="section-title">{{ $t('feedback.imageUpload') }}</view>
|
||||
<view class="upload-grid">
|
||||
<view class="upload-item" v-for="(img, index) in images" :key="index">
|
||||
<image :src="img" mode="aspectFill" />
|
||||
<view class="delete-btn" @click="deleteImage(index)">×</view>
|
||||
</view>
|
||||
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
|
||||
<text class="plus">+</text>
|
||||
<text class="tip">上传图片</text>
|
||||
</view>
|
||||
<view class="upload-btn" @click="chooseImage" v-if="images.length < 3">
|
||||
<text class="plus">+</text>
|
||||
<text class="tip">{{ $t('feedback.uploadImage') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">联系方式</view>
|
||||
<input class="contact-input" v-model="contact" placeholder="请留下您的手机号,方便我们联系您" type="number"
|
||||
maxlength="11" name="contact" />
|
||||
</view>
|
||||
<!-- 联系方式 -->
|
||||
<view class="contact-section">
|
||||
<view class="section-title">{{ $t('feedback.contactInfo') }}</view>
|
||||
<input class="contact-input" v-model="contact" :placeholder="$t('feedback.contactPlaceholder')" type="number"
|
||||
maxlength="11" name="contact" />
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<view class="submit-btn" @click="submitFeedback">提交反馈</view>
|
||||
</view>
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<view class="submit-btn" @click="submitFeedback">{{ $t('feedback.submit') }}</view>
|
||||
</view>
|
||||
<!-- </form> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import {
|
||||
URL,
|
||||
@@ -64,9 +65,18 @@
|
||||
import {
|
||||
addUserFeedback
|
||||
} from '../../config/api/feedback'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('feedback.title')
|
||||
})
|
||||
})
|
||||
|
||||
// 响应式数据
|
||||
const types = ref(['设备故障', '收费问题', '使用建议', '其他'])
|
||||
const types = ref([$t('feedback.deviceFault'), $t('feedback.chargingIssue'), $t('feedback.usageSuggestion'), $t('feedback.other')])
|
||||
const selectedType = ref(-1)
|
||||
const paramsType = ref('')
|
||||
const description = ref('')
|
||||
@@ -113,7 +123,7 @@
|
||||
const submitFeedback = async () => {
|
||||
if (selectedType.value === -1) {
|
||||
uni.showToast({
|
||||
title: '请选择问题类型',
|
||||
title: $t('feedback.pleaseSelectType'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -121,7 +131,7 @@
|
||||
|
||||
if (!description.value.trim()) {
|
||||
uni.showToast({
|
||||
title: '请描述您的问题',
|
||||
title: $t('feedback.pleaseDescribe'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -129,13 +139,13 @@
|
||||
|
||||
if (!contact.value) {
|
||||
uni.showToast({
|
||||
title: '请留下联系方式',
|
||||
title: $t('feedback.pleaseContact'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (types.value[selectedType.value] == '设备故障' || types.value[selectedType.value] == '收费问题') {
|
||||
if (types.value[selectedType.value] == $t('feedback.deviceFault') || types.value[selectedType.value] == $t('feedback.chargingIssue')) {
|
||||
paramsType.value = 'complain'
|
||||
} else {
|
||||
paramsType.value = 'suggestion'
|
||||
@@ -164,7 +174,7 @@
|
||||
// 兼容后端返回 { code: 200 } 或 HTTP 200 情况
|
||||
if ((res.statusCode === 200) && ((res.data && res.data.code === 200) || res.data === true || res.data?.success === true)) {
|
||||
uni.showToast({
|
||||
title: '反馈成功',
|
||||
title: $t('feedback.submitSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
setTimeout(() => {
|
||||
@@ -173,14 +183,14 @@
|
||||
return
|
||||
}
|
||||
uni.showToast({
|
||||
title: (res.data && (res.data.msg || res.data.message)) || '反馈失败',
|
||||
title: (res.data && (res.data.msg || res.data.message)) || $t('feedback.submitFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('feedback request failed:', err)
|
||||
uni.showToast({
|
||||
title: '网络错误,请稍后重试',
|
||||
title: $t('error.networkError'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
|
||||
<!-- 联系客服 -->
|
||||
<view class="contact-card">
|
||||
<view class="contact-title">{{ HELP_CONTENT.CONTACT.TITLE }}</view>
|
||||
<view class="contact-title">{{ $t('help.contactUs') }}</view>
|
||||
<view class="contact-content">
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.PHONE.LABEL }}</text>
|
||||
<text class="label">{{ $t('help.phone') }}</text>
|
||||
<text class="value" @click="makePhoneCall">{{ customerPhone }}</text>
|
||||
</view>
|
||||
<view class="contact-item">
|
||||
<text class="label">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.LABEL }}</text>
|
||||
<text class="label">{{ $t('help.workingHours') }}</text>
|
||||
<text class="value">{{ HELP_CONTENT.CONTACT.SERVICE_TIME.VALUE }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -51,6 +51,10 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('help.title')
|
||||
})
|
||||
// 从缓存读取客服电话
|
||||
this.customerPhone = getCustomerPhone()
|
||||
},
|
||||
|
||||
+60
-34
@@ -1,19 +1,23 @@
|
||||
<template>
|
||||
<view class="container fullscreen">
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="navbar-content" :style="{ height: navBarHeight + 'px' }">
|
||||
<text class="navbar-title">风电者共享风扇&暖手充电宝</text>
|
||||
</view>
|
||||
<!-- 自定义导航栏 -->
|
||||
<view class="custom-navbar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="navbar-content" :style="{ height: navBarHeight + 'px' }">
|
||||
<text class="navbar-title">{{ $t('home.title') }}</text>
|
||||
</view>
|
||||
|
||||
<view class="map-notice" v-if="noticeText" @click="openNoticePopup">
|
||||
</view>
|
||||
|
||||
<!-- 顶部信息区域(通知、招商等) -->
|
||||
<view class="top-info-section" :style="{ top: (statusBarHeight + navBarHeight) + 'px' }">
|
||||
<!-- 通知栏 -->
|
||||
<view class="notice-wrapper" v-if="noticeText" @click="openNoticePopup">
|
||||
<uv-notice-bar :text="noticeText" :speed="50" :show-icon="true" color="#07c160" bg-color="#E8F8EF"
|
||||
icon="volume"></uv-notice-bar>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<view class="main-content" :style="{ paddingTop: (statusBarHeight) + 'px' }">
|
||||
<!-- 内容区域 -->
|
||||
<view class="main-content" :style="{ paddingTop: (statusBarHeight + navBarHeight + noticeHeight) + 'px' }">
|
||||
<!-- 全屏地图组件 -->
|
||||
<MapComponent v-if="!isLoading && userLocation" ref="mapRef" :userLocation="userLocation"
|
||||
:positionList="positionList" :filteredPositions="filteredPositions" :searchKeyword="searchKeyword"
|
||||
@@ -25,7 +29,7 @@
|
||||
<view v-if="isLoading || !userLocation" class="map-loading-placeholder">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>正在获取位置信息...</text>
|
||||
<text>{{ $t('common.loadingLocation') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -36,28 +40,28 @@
|
||||
<view class="icon-wrap">
|
||||
<image class="action-icon" src="/static/map.png" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="action-label">附近设备</text>
|
||||
<text class="action-label">{{ $t('home.nearbyDevices') }}</text>
|
||||
</view> -->
|
||||
|
||||
<view class="action-btn secondary small btn-nearby" @click="openPopup">
|
||||
<view class="icon-wrap">
|
||||
<image src="/static/use_help.png" class="action-icon" mode="aspectFit"></image>
|
||||
</view>
|
||||
<text class="action-label">使用指南</text>
|
||||
<text class="action-label">{{ $t('home.useGuide') }}</text>
|
||||
</view>
|
||||
|
||||
<view class="action-btn primary btn-scan" @click="handleScan">
|
||||
<view class="icon-wrap">
|
||||
<image class="action-icon" src="/static/scan-icon.png" mode="aspectFill" />
|
||||
</view>
|
||||
<text class="primary-label">扫码使用</text>
|
||||
<text class="primary-label">{{ $t('home.scanToUse') }}</text>
|
||||
</view>
|
||||
|
||||
<view class="action-btn secondary small btn-my" @click="goMy">
|
||||
<view class="icon-wrap">
|
||||
<image class="action-icon" src="/static/user.png" mode="aspectFit" />
|
||||
</view>
|
||||
<text class="action-label">个人中心</text>
|
||||
<text class="action-label">{{ $t('home.personalCenter') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -67,7 +71,7 @@
|
||||
:expanded="isExpanded"
|
||||
:positions="filteredPositions"
|
||||
:isLoading="isLoading"
|
||||
title="附近设备场地"
|
||||
:title="$t('home.nearbyDeviceLocation')"
|
||||
@close="hideLocationList"
|
||||
@select="selectPositionFromPopup"
|
||||
@navigate="navigateToPosition"
|
||||
@@ -77,7 +81,7 @@
|
||||
<view class="loading-overlay" v-if="isLoading">
|
||||
<view class="loading-content">
|
||||
<view class="loading-spinner"></view>
|
||||
<text>正在获取场地信息...</text>
|
||||
<text>{{ $t('common.loadingPosition') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -86,17 +90,17 @@
|
||||
<view class="popup-mask" @click.stop="showPhoneAuthPopup = false"></view>
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">授权获取手机号</text>
|
||||
<text class="popup-title">{{ $t('auth.authTitle') }}</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="auth-desc">
|
||||
<text>为了提供更好的服务和紧急联系,需要授权获取您的手机号</text>
|
||||
<text>{{ $t('auth.authDesc') }}</text>
|
||||
</view>
|
||||
<button class="auth-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
|
||||
<text>一键获取手机号</text>
|
||||
<text>{{ $t('auth.getPhoneNumber') }}</text>
|
||||
</button>
|
||||
<view class="auth-cancel" @click="showPhoneAuthPopup = false">
|
||||
<text>暂不授权</text>
|
||||
<text>{{ $t('auth.notNow') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -106,7 +110,7 @@
|
||||
<uv-popup ref="guidePopup" mode="center" round="24" :overlay="true" :closeOnClickOverlay="false" :safeAreaInsetBottom="false">
|
||||
<view class="guide-popup">
|
||||
<view class="guide-header">
|
||||
<text class="guide-title">使用指南</text>
|
||||
<text class="guide-title">{{ $t('guide.title') }}</text>
|
||||
<!-- <view class="guide-close" @click="closeGuidePopup">
|
||||
<uv-icon name="close" size="20"></uv-icon>
|
||||
</view> -->
|
||||
@@ -115,8 +119,8 @@
|
||||
<view class="guide-step" v-for="(step, idx) in guideSteps" :key="idx">
|
||||
<view class="step-index">{{ idx + 1 }}</view>
|
||||
<view class="step-info">
|
||||
<view class="step-title">{{ step.title }}</view>
|
||||
<view class="step-desc">{{ step.desc }}</view>
|
||||
<view class="step-title">{{ $t('guide.step' + (idx + 1) + 'Title') }}</view>
|
||||
<view class="step-desc">{{ $t('guide.step' + (idx + 1) + 'Desc') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -133,7 +137,7 @@
|
||||
<uv-popup ref="noticePopup" mode="center" round="24" :overlay="true" :closeOnClickOverlay="true" :safeAreaInsetBottom="false">
|
||||
<view class="notice-popup">
|
||||
<view class="notice-header">
|
||||
<text class="notice-title">通知公告</text>
|
||||
<text class="notice-title">{{ $t('home.noticeTitle') }}</text>
|
||||
</view>
|
||||
<view class="notice-content">
|
||||
<text class="notice-text">{{ noticeText }}</text>
|
||||
@@ -182,6 +186,8 @@
|
||||
// 注意:从 pages/index/ 目录访问 components/ 需要使用 ../../components/ 路径
|
||||
import MapComponent from '../../components/MapComponent.vue'
|
||||
import LocationListSheet from '../../components/LocationListSheet.vue'
|
||||
import { useI18n } from '../../utils/i18n.js'
|
||||
|
||||
// 开启右上角分享菜单(仅 mp-weixin 有效)
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.showShareMenu({
|
||||
@@ -190,6 +196,8 @@
|
||||
})
|
||||
// #endif
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 响应式数据
|
||||
const searchKeyword = ref('')
|
||||
const userLocation = ref(null)
|
||||
@@ -205,6 +213,7 @@
|
||||
// 导航栏高度相关
|
||||
const statusBarHeight = ref(0)
|
||||
const navBarHeight = ref(44) // 默认导航栏内容高度
|
||||
const noticeHeight = ref(0) // 通知栏高度
|
||||
|
||||
// 使用指南步骤
|
||||
const guideSteps = ref([
|
||||
@@ -240,6 +249,11 @@
|
||||
const res = await getNoticeTextData(parasm);
|
||||
noticeText.value = res.data.noticeContent;
|
||||
|
||||
// 设置通知栏高度
|
||||
if (res.data.noticeContent) {
|
||||
noticeHeight.value = 50 // 通知栏高度约50px
|
||||
}
|
||||
|
||||
// 将通知内容存储到本地缓存
|
||||
try {
|
||||
uni.setStorageSync('noticeContent', res.data.noticeContent);
|
||||
@@ -400,7 +414,7 @@ const noticePopup = ref(null)
|
||||
} catch (error) {
|
||||
console.error('获取位置失败:', error)
|
||||
uni.showToast({
|
||||
title: '获取位置失败,显示默认地图',
|
||||
title: $t('home.getLocationFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -578,7 +592,7 @@ const noticePopup = ref(null)
|
||||
uni.hideLoading()
|
||||
|
||||
uni.showToast({
|
||||
title: '定位成功',
|
||||
title: $t('home.locateSuccess'),
|
||||
icon: 'success',
|
||||
duration: 1500
|
||||
})
|
||||
@@ -587,7 +601,7 @@ const noticePopup = ref(null)
|
||||
uni.hideLoading()
|
||||
|
||||
uni.showToast({
|
||||
title: e.errMsg || '定位失败,请检查定位权限',
|
||||
title: e.errMsg || $t('home.locateFailed'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
@@ -691,7 +705,7 @@ const noticePopup = ref(null)
|
||||
|
||||
if (!deviceNo) {
|
||||
uni.showToast({
|
||||
title: '无效的设备二维码',
|
||||
title: $t('home.invalidQRCode'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -830,16 +844,18 @@ const closeNoticePopup = () => {
|
||||
export default {
|
||||
// 分享给朋友
|
||||
onShareAppMessage() {
|
||||
const $t = this.$t || ((key) => key)
|
||||
return {
|
||||
title: '风电者 - 共享风扇暖手充电宝',
|
||||
title: $t('share.title'),
|
||||
path: '/pages/index/index',
|
||||
// imageUrl: '/static/logo.png'
|
||||
}
|
||||
},
|
||||
// 朋友圈
|
||||
onShareTimeline() {
|
||||
const $t = this.$t || ((key) => key)
|
||||
return {
|
||||
title: '风电者 - 共享风扇暖手充电宝',
|
||||
title: $t('share.title'),
|
||||
query: '',
|
||||
// imageUrl: '/static/logo.png'
|
||||
}
|
||||
@@ -889,6 +905,8 @@ const closeNoticePopup = () => {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-bottom: 180rpx; /* 为底部按钮留出空间 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 顶部Logo和通知栏 */
|
||||
@@ -1376,7 +1394,7 @@ const closeNoticePopup = () => {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
bottom: 180rpx; /* 为底部按钮留出空间 */
|
||||
background: #f6f7fb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1502,11 +1520,19 @@ const closeNoticePopup = () => {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.map-notice {
|
||||
/* 顶部信息区域 */
|
||||
.top-info-section {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 998;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.notice-wrapper {
|
||||
margin: 0 20rpx;
|
||||
margin-top: 10rpx;
|
||||
padding: 10rpx 0;
|
||||
border-radius: 20rpx;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
/* 使用指南弹窗样式 */
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 外部网页地址
|
||||
const webUrl = ref('https://joininvestment.gxfs123.com/')
|
||||
@@ -24,13 +27,16 @@
|
||||
const handleError = (e) => {
|
||||
console.error('web-view 加载错误:', e)
|
||||
uni.showToast({
|
||||
title: '页面加载失败',
|
||||
title: $t('join.pageLoadFailed'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('join.title')
|
||||
})
|
||||
console.log('招商页面加载,外部网址:', webUrl.value)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<view class="legal-page">
|
||||
<view class="header">
|
||||
<view class="title">用户协议</view>
|
||||
<view class="subtitle">适用于“风电者”共享风扇租借服务(最后更新:{{ effectiveDate }})</view>
|
||||
<view class="title">{{ $t('legal.agreement') }}</view>
|
||||
<view class="subtitle">{{ $t('legal.applicableToService') }}({{ $t('legal.lastUpdate') }}:{{ effectiveDate }})</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content" scroll-y>
|
||||
@@ -71,12 +71,21 @@
|
||||
<view class="p">15.2 协议条款如被认定无效或不可执行,不影响其他条款的效力与执行。</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">如对本协议有疑问,请前往“我的-客服”咨询</view>
|
||||
<view class="footer">{{ $t('legal.footerNotice') }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('legal.agreement')
|
||||
})
|
||||
})
|
||||
|
||||
const brandName = '风电者'
|
||||
const companyName = '深圳乐慕智云科技有限公司'
|
||||
|
||||
+14
-4
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<view class="legal-page">
|
||||
<view class="header">
|
||||
<view class="title">隐私政策</view>
|
||||
<view class="subtitle">适用于“风电者”共享风扇租借服务(最后更新:{{ effectiveDate }})</view>
|
||||
<view class="title">{{ $t('legal.privacy') }}</view>
|
||||
<view class="subtitle">{{ $t('legal.applicableToService') }}({{ $t('legal.lastUpdate') }}:{{ effectiveDate }})</view>
|
||||
</view>
|
||||
|
||||
<view class="card notice">
|
||||
@@ -56,14 +56,24 @@
|
||||
<view class="p">10.1 您可通过“我的-客服”与我们联系以行使前述权利或就本政策提出疑问。</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer">如对本政策有疑问,请前往“我的-客服”咨询</view>
|
||||
<view class="footer">{{ $t('legal.footerNoticePolicy') }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('legal.privacy')
|
||||
})
|
||||
})
|
||||
|
||||
const brandName = '风电者'
|
||||
const companyName = '深圳乐慕智云科技有限公司'
|
||||
|
||||
+41
-31
@@ -2,18 +2,18 @@
|
||||
<view class="login-container">
|
||||
<view class="logo">
|
||||
<image src="/static/logo.png" mode="aspectFit" />
|
||||
<text class="app-name">风电者共享风扇&充电宝</text>
|
||||
<text class="app-name">{{ $t('app.slogan') }}</text>
|
||||
</view>
|
||||
|
||||
<view class="title">登录您的账号</view>
|
||||
<view class="subtitle">为保障使用体验,请先完成登录</view>
|
||||
<view class="title">{{ $t('auth.loginTitle') }}</view>
|
||||
<view class="subtitle">{{ $t('auth.loginDesc') }}</view>
|
||||
|
||||
<!-- 微信一键手机号快捷登录(推荐) -->
|
||||
<button v-if="!isAgreed" class="btn primary" @click="handleLoginClick">
|
||||
手机号快捷登录
|
||||
{{ $t('auth.getPhoneNumber') }}
|
||||
</button>
|
||||
<button v-else class="btn primary" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
|
||||
手机号快捷登录
|
||||
{{ $t('auth.getPhoneNumber') }}
|
||||
</button>
|
||||
|
||||
<!-- 仅微信登录(不授权手机号时使用) -->
|
||||
@@ -24,10 +24,10 @@
|
||||
<label class="agreement-label">
|
||||
<checkbox value="agreed" :checked="isAgreed" color="#07c160" class="agreement-checkbox" />
|
||||
<text class="agreement-text">
|
||||
我已阅读并同意
|
||||
<text class="link" @tap.stop="go('/pages/legal/agreement')">《用户协议》</text>
|
||||
和
|
||||
<text class="link" @tap.stop="go('/pages/legal/privacy')">《隐私政策》</text>
|
||||
{{ $t('auth.agreeToTerms') }}
|
||||
<text class="link" @tap.stop="go('/pages/legal/agreement')">{{ $t('user.userAgreement') }}</text>
|
||||
{{ $t('common.and') }}
|
||||
<text class="link" @tap.stop="go('/pages/legal/privacy')">{{ $t('user.privacyPolicy') }}</text>
|
||||
</text>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
@@ -36,9 +36,19 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { wxLogin, getUserPhoneNumber, getUserInfo } from '../../util/index.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 设置页面标题
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('auth.loginTitle')
|
||||
})
|
||||
})
|
||||
|
||||
const redirect = ref('/pages/index/index')
|
||||
const isAgreed = ref(false) // 是否同意协议
|
||||
@@ -67,23 +77,23 @@
|
||||
return
|
||||
}
|
||||
|
||||
// 未勾选,弹窗提示
|
||||
uni.showModal({
|
||||
title: '温馨提示',
|
||||
content: '请先阅读并同意《用户协议》和《隐私政策》',
|
||||
confirmText: '同意',
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 用户点击同意,自动勾选
|
||||
isAgreed.value = true
|
||||
resolve()
|
||||
} else {
|
||||
// 用户点击取消
|
||||
reject(new Error('需要同意协议才能登录'))
|
||||
}
|
||||
// 未勾选,弹窗提示
|
||||
uni.showModal({
|
||||
title: $t('common.tips'),
|
||||
content: $t('auth.pleaseAgreeToTerms'),
|
||||
confirmText: $t('common.confirm'),
|
||||
cancelText: $t('common.cancel'),
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 用户点击同意,自动勾选
|
||||
isAgreed.value = true
|
||||
resolve()
|
||||
} else {
|
||||
// 用户点击取消
|
||||
reject(new Error('需要同意协议才能登录'))
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,8 +118,8 @@
|
||||
// 先检查是否同意协议
|
||||
await checkAgreement()
|
||||
|
||||
await wxLogin()
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
await wxLogin()
|
||||
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
||||
await navigateAfterLogin()
|
||||
} catch (error) {
|
||||
if (error.message !== '需要同意协议才能登录') {
|
||||
@@ -120,7 +130,7 @@
|
||||
|
||||
const onGetPhoneNumber = async (e) => {
|
||||
if (!e || e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
uni.showToast({ title: '已取消手机号授权', icon: 'none' })
|
||||
uni.showToast({ title: $t('auth.phoneCancelled'), icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
@@ -129,10 +139,10 @@
|
||||
await wxLogin()
|
||||
// 再用微信返回的临时 code 换取手机号
|
||||
await getUserPhoneNumber(e.detail.code)
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
uni.showToast({ title: $t('auth.loginSuccess'), icon: 'success' })
|
||||
await navigateAfterLogin()
|
||||
} catch (error) {
|
||||
uni.showToast({ title: error.message || '登录失败', icon: 'none' })
|
||||
uni.showToast({ title: error.message || $t('auth.loginFailed'), icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-22
@@ -6,8 +6,8 @@
|
||||
<image v-else class="avatar" src="@/static/head.png" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="user-text">
|
||||
<view class="nickname">{{ userInfo.nickName || '点击登录' }}</view>
|
||||
<view class="subtext">{{ userInfo.phone ? maskPhone(userInfo.phone) : '授权登录后可查看订单与资产' }}</view>
|
||||
<view class="nickname">{{ userInfo.nickName || $t('user.clickToLogin') }}</view>
|
||||
<view class="subtext">{{ userInfo.phone ? maskPhone(userInfo.phone) : $t('user.loginPrompt') }}</view>
|
||||
</view>
|
||||
<uv-icon type="right" size="16" color="#999"></uv-icon>
|
||||
</view>
|
||||
@@ -32,56 +32,56 @@
|
||||
<view class="list-item" @click="handleQuickReturn">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/express_return.png" mode="aspectFit"></image>
|
||||
<text class="title">快速归还<text style="font-size: 18rpx;">(直接查看使用中的订单)</text></text>
|
||||
<text class="title">{{ $t('user.quickReturn') }}<text style="font-size: 18rpx;">{{ $t('user.quickReturnDesc') }}</text></text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="list-item" @click="navigateTo('/pages/expressReturn/index')" v-if="showMenuItem">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/express.png" mode="aspectFit"></image>
|
||||
<text class="title">快递归还记录</text>
|
||||
<text class="title">{{ $t('user.expressReturn') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="list-item" @click="navigateTo('/pages/order/index')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/orderList.png" mode="aspectFit"></image>
|
||||
<text class="title">我的订单</text>
|
||||
<text class="title">{{ $t('user.myOrders') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="list-item" @click="navigateTo('/pages/help/index')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/customer-service.png" mode="aspectFit"></image>
|
||||
<text class="title">客服中心</text>
|
||||
<text class="title">{{ $t('user.customerService') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="list-item" @click="navigateTo('/pages/feedback/index')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/suggess.png" mode="aspectFit"></image>
|
||||
<text class="title">投诉与建议</text>
|
||||
<text class="title">{{ $t('user.feedback') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<!-- <view class="list-item" @click="navigateTo('/pages/legal/agreement')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/business-licence.png" mode="aspectFit"></image>
|
||||
<text class="title">营业资质</text>
|
||||
<text class="title">{{ $t('user.businessLicense') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view> -->
|
||||
<view class="list-item" @click="navigateTo('/pages/join/index')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/peopleInWork.png" mode="aspectFit"></image>
|
||||
<text class="title">合作加盟</text>
|
||||
<text class="title">{{ $t('user.cooperation') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="list-item" @click="navigateTo('/pages/setting/index')">
|
||||
<view class="left">
|
||||
<image class="icon" src="/static/setting.png" mode="aspectFit"></image>
|
||||
<text class="title">设置</text>
|
||||
<text class="title">{{ $t('user.settings') }}</text>
|
||||
</view>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
@@ -90,11 +90,11 @@
|
||||
|
||||
<view class="footer-agreements">
|
||||
<view class="link-box">
|
||||
<text class="link" @click="navigateTo('/pages/legal/agreement')">《用户协议》</text>
|
||||
<text class="link" @click="navigateTo('/pages/legal/agreement')">{{ $t('user.userAgreement') }}</text>
|
||||
<text class="sep">|</text>
|
||||
<text class="link" @click="navigateTo('/pages/legal/privacy')">《隐私政策》</text>
|
||||
<text class="link" @click="navigateTo('/pages/legal/privacy')">{{ $t('user.privacyPolicy') }}</text>
|
||||
</view>
|
||||
<view class="version">v{{ appVersion }}</view>
|
||||
<view class="version">{{ $t('user.version') }}{{ appVersion }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 保留授权弹窗,暂不启用 -->
|
||||
@@ -133,8 +133,11 @@ import {
|
||||
import {
|
||||
URL
|
||||
} from '../../config/url.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
// 设置页执行退出登录,此页不再直接调用
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 响应式状态
|
||||
const userInfo = ref({});
|
||||
const deposit = ref('0.00');
|
||||
@@ -147,6 +150,9 @@ import {
|
||||
|
||||
// 页面加载时初始化
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('user.personalCenter')
|
||||
})
|
||||
getInfo();
|
||||
initVersion();
|
||||
});
|
||||
@@ -186,7 +192,7 @@ import {
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
title: $t('user.getUserInfoFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -269,7 +275,7 @@ import {
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '暂无使用中的订单',
|
||||
title: $t('order.noOrder'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -277,7 +283,7 @@ import {
|
||||
uni.hideLoading();
|
||||
console.error('获取使用中订单失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取订单失败',
|
||||
title: $t('order.getOrderFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -300,7 +306,7 @@ import {
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.showToast({
|
||||
title: '请在微信小程序中使用此功能',
|
||||
title: $t('auth.pleaseUseInWechat'),
|
||||
icon: 'none'
|
||||
})
|
||||
// #endif
|
||||
@@ -404,7 +410,7 @@ import {
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
uni.showToast({
|
||||
title: '请在微信小程序中使用此功能',
|
||||
title: $t('auth.pleaseUseInWechat'),
|
||||
icon: 'none'
|
||||
});
|
||||
closeAuthPopup();
|
||||
@@ -433,7 +439,7 @@ import {
|
||||
// });
|
||||
|
||||
uni.showToast({
|
||||
title: '信息更新成功',
|
||||
title: $t('user.updateSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
@@ -442,7 +448,7 @@ import {
|
||||
} catch (error) {
|
||||
console.error('更新用户信息失败:', error);
|
||||
uni.showToast({
|
||||
title: '更新用户信息失败',
|
||||
title: $t('user.updateFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -511,7 +517,7 @@ import {
|
||||
// 关于我们
|
||||
const handleAboutUs = () => {
|
||||
uni.showToast({
|
||||
title: '功能开发中',
|
||||
title: $t('help.functionDeveloping'),
|
||||
icon: 'none'
|
||||
});
|
||||
};
|
||||
@@ -519,7 +525,7 @@ import {
|
||||
// 隐私政策
|
||||
const handlePrivacyPolicy = () => {
|
||||
uni.showToast({
|
||||
title: '功能开发中',
|
||||
title: $t('help.functionDeveloping'),
|
||||
icon: 'none'
|
||||
});
|
||||
};
|
||||
|
||||
+58
-53
@@ -19,9 +19,9 @@
|
||||
<view class="info-col">
|
||||
<view class="info-value-wrapper">
|
||||
<text class="info-value-large">{{ getOrderFee() }}</text>
|
||||
<text class="info-value-unit">元</text>
|
||||
<text class="info-value-unit">{{ $t('unit.yuan') }}</text>
|
||||
</view>
|
||||
<view class="info-label">订单金额</view>
|
||||
<view class="info-label">{{ $t('order.totalAmount') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fee-rule">
|
||||
@@ -31,39 +31,39 @@
|
||||
|
||||
<!-- 租借信息卡片 -->
|
||||
<view class="rent-card">
|
||||
<view class="rent-title">租借信息</view>
|
||||
<view class="rent-title">{{ $t('order.rentInfo') }}</view>
|
||||
<view class="rent-item">
|
||||
<view class="rent-label">订单编号</view>
|
||||
<view class="rent-label">{{ $t('order.orderNo') }}</view>
|
||||
<view class="rent-value">{{ orderInfo.orderNo || '-' }}</view>
|
||||
</view>
|
||||
<view class="rent-item">
|
||||
<view class="rent-label">风扇编号</view>
|
||||
<view class="rent-label">{{ $t('order.fanNo') }}</view>
|
||||
<view class="rent-value">{{ deviceId || '-' }}</view>
|
||||
</view>
|
||||
<view class="rent-item">
|
||||
<view class="rent-label">租借时间</view>
|
||||
<view class="rent-label">{{ $t('order.rentTime') }}</view>
|
||||
<view class="rent-value">{{ orderInfo.startTime || '-' }}</view>
|
||||
</view>
|
||||
<view class="rent-item">
|
||||
<view class="rent-label">租借地点</view>
|
||||
<view class="rent-value">{{ orderInfo.positionName || '新佳宜(九天银河店)' }}</view>
|
||||
<view class="rent-label">{{ $t('order.rentLocation') }}</view>
|
||||
<view class="rent-value">{{ orderInfo.positionName || '-' }}</view>
|
||||
</view>
|
||||
<view class="rent-item">
|
||||
<view class="rent-label">租借方式</view>
|
||||
<view class="rent-label">{{ $t('order.rentMethod') }}</view>
|
||||
<view class="rent-value">{{ getPayWayText() }}</view>
|
||||
</view>
|
||||
<view class="rent-item" v-if="isOrderCompleted() && orderInfo.endTime">
|
||||
<view class="rent-label">归还时间</view>
|
||||
<view class="rent-label">{{ $t('order.returnTime') }}</view>
|
||||
<view class="rent-value">{{ orderInfo.endTime }}</view>
|
||||
</view>
|
||||
<view class="rent-item" v-if="isOrderCompleted() && orderInfo.returnPosition">
|
||||
<view class="rent-label">归还地点</view>
|
||||
<view class="rent-value">{{ orderInfo.returnPosition || '新佳宜(九天银河店)' }}</view>
|
||||
<view class="rent-label">{{ $t('order.returnLocation') }}</view>
|
||||
<view class="rent-value">{{ orderInfo.returnPosition || '-' }}</view>
|
||||
</view>
|
||||
<view class="rent-paid" v-if="isOrderCompleted()">
|
||||
<text class="paid-label">已支付</text>
|
||||
<text class="paid-label">{{ $t('order.paid') }}</text>
|
||||
<text class="paid-value">{{ orderInfo.currentFee || orderInfo.payAmount || '10' }}</text>
|
||||
<text class="paid-unit">元</text>
|
||||
<text class="paid-unit">{{ $t('unit.yuan') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -73,16 +73,16 @@
|
||||
<template v-if="orderInfo.orderStatus === 'in_used'">
|
||||
<view class="bottom-icon-btn" @click="contactService">
|
||||
<image src="/static/customer-service.png" class="icon" mode="aspectFit"></image>
|
||||
<text>客服中心</text>
|
||||
<text>{{ $t('user.customerService') }}</text>
|
||||
</view>
|
||||
<view v-if="!showExpressAction" class="countdown-btn">
|
||||
{{ formatCountdown(countdownRemaining) }}后可快递归还
|
||||
{{ formatCountdown(countdownRemaining) }}{{ $t('order.canExpressReturn') }}
|
||||
</view>
|
||||
<view v-if="showExpressAction" class="action-btn secondary" @click="expressRetrunOrder">
|
||||
暂停计费
|
||||
{{ $t('order.pauseBilling') }}
|
||||
</view>
|
||||
<view v-if="showExpressAction" class="action-btn primary" @click="quickReturn">
|
||||
快速归还
|
||||
{{ $t('order.quickReturn') }}
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -90,26 +90,26 @@
|
||||
<template v-if="isOrderCompleted()">
|
||||
<view class="bottom-icon-btn" @click="handleWithdraw" v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">
|
||||
<image src="/static/suggess.png" class="icon" mode="aspectFit"></image>
|
||||
<text>费用申诉</text>
|
||||
<text>{{ $t('order.feeAppeal') }}</text>
|
||||
</view>
|
||||
<view class="bottom-icon-btn" @click="contactService">
|
||||
<image src="/static/customer-service.png" class="icon" mode="aspectFit"></image>
|
||||
<text>客服中心</text>
|
||||
<text>{{ $t('user.customerService') }}</text>
|
||||
</view>
|
||||
<view class="action-btn primary" @click="rentAgain">
|
||||
再次租借
|
||||
{{ $t('order.rentAgain') }}
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 待支付状态 -->
|
||||
<template v-if="orderInfo.orderStatus === 'waiting_for_payment'">
|
||||
<view class="action-btn secondary" @click="handleCancelOrder">取消订单</view>
|
||||
<view class="action-btn primary" @click="handlePayment">立即支付</view>
|
||||
<view class="action-btn secondary" @click="handleCancelOrder">{{ $t('order.cancelOrder') }}</view>
|
||||
<view class="action-btn primary" @click="handlePayment">{{ $t('order.payNow') }}</view>
|
||||
</template>
|
||||
|
||||
<!-- 已取消状态 -->
|
||||
<template v-if="orderInfo.orderStatus === 'order_cancelled'">
|
||||
<view class="action-btn primary full-width" @click="goToHome">返回首页</view>
|
||||
<view class="action-btn primary full-width" @click="goToHome">{{ $t('order.backToHome') }}</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
@@ -168,6 +168,11 @@
|
||||
onLoad(options) {
|
||||
console.log('订单详情页加载,参数:', JSON.stringify(options))
|
||||
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('order.orderDetail')
|
||||
})
|
||||
|
||||
this.isPageActive = true
|
||||
|
||||
// 从缓存读取通知内容(计费规则)
|
||||
@@ -241,27 +246,27 @@
|
||||
// 获取订单状态文字
|
||||
getOrderStatusText() {
|
||||
const statusMap = {
|
||||
'waiting_for_payment': '待支付',
|
||||
'payment_in_progress': '支付中',
|
||||
'payment_successful': '支付成功',
|
||||
'in_used': '使用中',
|
||||
'payment_failed': '支付失败',
|
||||
'order_cancelled': '已取消',
|
||||
'used_done': '已完成',
|
||||
'used_down': '已完成'
|
||||
'waiting_for_payment': this.$t('order.waitingForPayment'),
|
||||
'payment_in_progress': this.$t('order.paymentInProgress'),
|
||||
'payment_successful': this.$t('order.paymentSuccess'),
|
||||
'in_used': this.$t('order.inUse'),
|
||||
'payment_failed': this.$t('order.paymentFailed'),
|
||||
'order_cancelled': this.$t('order.cancelled'),
|
||||
'used_done': this.$t('order.finished'),
|
||||
'used_down': this.$t('order.finished')
|
||||
}
|
||||
return statusMap[this.orderInfo.orderStatus] || '订单详情'
|
||||
return statusMap[this.orderInfo.orderStatus] || this.$t('order.orderDetail')
|
||||
},
|
||||
|
||||
// 获取状态描述
|
||||
getStatusDesc() {
|
||||
const descMap = {
|
||||
'waiting_for_payment': '请尽快完成支付',
|
||||
'in_used': '请妥善保管设备,使用完毕后及时归还',
|
||||
'used_done': '您的风扇已归还,感谢使用',
|
||||
'used_down': '您的风扇已归还,感谢使用',
|
||||
'order_cancelled': '订单已取消',
|
||||
'payment_failed': '支付失败,请重新支付'
|
||||
'waiting_for_payment': this.$t('order.pleasePaySoon'),
|
||||
'in_used': this.$t('order.pleaseReturnInTime'),
|
||||
'used_done': this.$t('order.returnedThankYou'),
|
||||
'used_down': this.$t('order.returnedThankYou'),
|
||||
'order_cancelled': this.$t('order.orderCancelled'),
|
||||
'payment_failed': this.$t('order.paymentFailedRetry')
|
||||
}
|
||||
return descMap[this.orderInfo.orderStatus] || ''
|
||||
},
|
||||
@@ -293,11 +298,11 @@
|
||||
// 获取支付方式文本
|
||||
getPayWayText() {
|
||||
const payWayMap = {
|
||||
'wx_score_pay': '免押租借',
|
||||
'wx_member_pay': '会员订单',
|
||||
'wx_pay': '押金租借'
|
||||
'wx_score_pay': this.$t('order.depositFree'),
|
||||
'wx_member_pay': this.$t('order.memberOrder'),
|
||||
'wx_pay': this.$t('order.depositPay')
|
||||
}
|
||||
return payWayMap[this.orderInfo.payWay] || '免押租借'
|
||||
return payWayMap[this.orderInfo.payWay] || this.$t('order.depositFree')
|
||||
},
|
||||
|
||||
// 格式化倒计时(显示为 HH:MM:SS 格式)
|
||||
@@ -393,7 +398,7 @@
|
||||
// 获取使用时长标签文本
|
||||
getUsedTimeLabel() {
|
||||
// 使用中状态显示"已使用",已完成状态显示"使用时长"
|
||||
return this.orderInfo.orderStatus === 'in_used' ? '已使用' : '使用时长'
|
||||
return this.orderInfo.orderStatus === 'in_used' ? this.$t('order.used') : this.$t('order.duration')
|
||||
},
|
||||
|
||||
// 获取订单费用(不含单位)
|
||||
@@ -549,7 +554,7 @@
|
||||
|
||||
try {
|
||||
if (!this.orderInfo.orderId) {
|
||||
throw new Error('订单ID不能为空')
|
||||
throw new Error(this.$t('order.orderIdRequired'))
|
||||
}
|
||||
|
||||
const result = await queryById(this.orderInfo.orderId)
|
||||
@@ -762,13 +767,13 @@
|
||||
// 取消订单
|
||||
handleCancelOrder() {
|
||||
uni.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定要取消此订单吗?',
|
||||
title: this.$t('order.confirmCancel'),
|
||||
content: this.$t('order.confirmCancelContent'),
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: this.$t('common.processing')
|
||||
})
|
||||
const result = await cancelOrder({
|
||||
orderId: this.orderInfo.orderId
|
||||
@@ -776,17 +781,17 @@
|
||||
if (result.code === 200) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
title: this.$t('order.cancelSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
await this.getOrderDetails()
|
||||
} else {
|
||||
throw new Error(result.msg || '取消订单失败')
|
||||
throw new Error(result.msg || this.$t('order.cancelFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '取消订单失败',
|
||||
title: error.message || this.$t('order.cancelFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -821,7 +826,7 @@
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200) {
|
||||
uni.showToast({
|
||||
title: '退款申请成功',
|
||||
title: this.$t('order.refundSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
@@ -837,7 +842,7 @@
|
||||
} catch (error) {
|
||||
console.error('退款申请错误:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '退款申请失败',
|
||||
title: error.message || this.$t('order.refundFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
|
||||
+42
-32
@@ -10,12 +10,12 @@
|
||||
|
||||
<!-- 订单列表 -->
|
||||
<view class="order-list">
|
||||
<view class="empty-state" v-if="orderList.length === 0">
|
||||
<view class="empty-icon">
|
||||
<image src="/static/orderList.png" mode="aspectFill" class="empty-icon"></image>
|
||||
</view>
|
||||
<text class="empty-text">暂无订单记录</text>
|
||||
<view class="empty-state" v-if="orderList.length === 0">
|
||||
<view class="empty-icon">
|
||||
<image src="/static/orderList.png" mode="aspectFill" class="empty-icon"></image>
|
||||
</view>
|
||||
<text class="empty-text">{{ $t('order.noOrderRecord') }}</text>
|
||||
</view>
|
||||
|
||||
<OrderItemCard
|
||||
v-for="(order, index) in orderList"
|
||||
@@ -56,6 +56,16 @@
|
||||
import {
|
||||
URL
|
||||
} from '../../config/url.js';
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 设置页面标题
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('order.myOrders')
|
||||
})
|
||||
})
|
||||
|
||||
// 初始化状态
|
||||
const currentTab = ref(0);
|
||||
@@ -64,62 +74,62 @@
|
||||
// 订单状态映射
|
||||
const orderStatusMap = reactive({
|
||||
'0': {
|
||||
text: '待支付',
|
||||
get text() { return $t('order.waitingForPayment') },
|
||||
class: 'status-waiting'
|
||||
},
|
||||
'1': {
|
||||
text: '使用中',
|
||||
get text() { return $t('order.inUse') },
|
||||
class: 'status-using'
|
||||
},
|
||||
'2': {
|
||||
text: '已完成',
|
||||
get text() { return $t('order.finished') },
|
||||
class: 'status-finished'
|
||||
},
|
||||
'3': {
|
||||
text: '已取消',
|
||||
get text() { return $t('order.cancelled') },
|
||||
class: 'status-cancelled'
|
||||
},
|
||||
'waiting_for_payment': {
|
||||
text: '待支付',
|
||||
get text() { return $t('order.waitingForPayment') },
|
||||
class: 'status-waiting'
|
||||
},
|
||||
'in_used': {
|
||||
text: '使用中',
|
||||
get text() { return $t('order.inUse') },
|
||||
class: 'status-using'
|
||||
},
|
||||
'used_done': {
|
||||
text: '已完成',
|
||||
get text() { return $t('order.finished') },
|
||||
class: 'status-finished'
|
||||
},
|
||||
'order_cancelled': {
|
||||
text: '已取消',
|
||||
get text() { return $t('order.cancelled') },
|
||||
class: 'status-cancelled'
|
||||
},
|
||||
'express_return': {
|
||||
text: '快递归还',
|
||||
get text() { return $t('express.title') },
|
||||
class: 'status-express-return'
|
||||
}
|
||||
});
|
||||
|
||||
// 订单状态标签
|
||||
const orderStatusTabs = reactive([{
|
||||
text: '全部',
|
||||
get text() { return $t('common.all') },
|
||||
status: []
|
||||
},
|
||||
{
|
||||
text: '待付款',
|
||||
get text() { return $t('order.waitingForPayment') },
|
||||
status: ['waiting_for_payment']
|
||||
},
|
||||
{
|
||||
text: '使用中',
|
||||
get text() { return $t('order.inUse') },
|
||||
status: ['in_used']
|
||||
},
|
||||
{
|
||||
text: '已完成',
|
||||
get text() { return $t('order.finished') },
|
||||
status: ['used_done']
|
||||
},
|
||||
{
|
||||
text: '已取消',
|
||||
get text() { return $t('order.cancelled') },
|
||||
status: ['order_cancelled']
|
||||
}
|
||||
]);
|
||||
@@ -212,7 +222,7 @@
|
||||
} catch (error) {
|
||||
console.error('获取订单列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取订单列表失败',
|
||||
title: $t('order.getOrderListFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -224,14 +234,14 @@
|
||||
const res = await getOrderByOrderNoScorePayStatus(order.orderNo);
|
||||
if (res.code === 200) {
|
||||
uni.showToast({
|
||||
title: '状态同步成功',
|
||||
title: $t('order.syncSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
await loadOrderList(orderStatusTabs[currentTab.value].status);
|
||||
}
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: '同步状态失败',
|
||||
title: $t('order.syncFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -258,7 +268,7 @@
|
||||
const handlePayment = async (order) => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: $t('common.processing')
|
||||
});
|
||||
|
||||
// 调用后端创建微信支付订单接口
|
||||
@@ -279,7 +289,7 @@
|
||||
...payParams,
|
||||
success: async () => {
|
||||
uni.showToast({
|
||||
title: '支付成功',
|
||||
title: $t('payment.paymentSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
@@ -295,7 +305,7 @@
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('支付失败:', err);
|
||||
throw new Error('支付失败,请重试');
|
||||
throw new Error($t('payment.paymentFailedRetry'));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -306,7 +316,7 @@
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: error.message || '支付失败',
|
||||
title: error.message || $t('payment.paymentFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -316,12 +326,12 @@
|
||||
const handleCancelOrder = async (order) => {
|
||||
try {
|
||||
uni.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定要取消此订单吗?',
|
||||
title: $t('order.confirmCancel'),
|
||||
content: $t('order.confirmCancelContent'),
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: $t('common.processing')
|
||||
});
|
||||
|
||||
const result = await cancelOrder({
|
||||
@@ -331,14 +341,14 @@
|
||||
if (result) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
title: $t('order.cancelSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 刷新订单列表
|
||||
await loadOrderList();
|
||||
} else {
|
||||
throw new Error(result.msg || '取消订单失败');
|
||||
throw new Error(result.msg || $t('order.cancelFailed'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +356,7 @@
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: error.message || '取消订单失败',
|
||||
title: error.message || $t('order.cancelFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
+29
-24
@@ -9,38 +9,38 @@
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-card">
|
||||
<view class="card-title">订单信息</view>
|
||||
<view class="card-title">{{ $t('payment.orderInfo') }}</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单号</text>
|
||||
<text class="label">{{ $t('order.orderNo') }}</text>
|
||||
<text class="value">{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">设备号</text>
|
||||
<text class="label">{{ $t('order.deviceNo') }}</text>
|
||||
<text class="value">{{ orderInfo.deviceNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">创建时间</text>
|
||||
<text class="label">{{ $t('payment.createTime') }}</text>
|
||||
<text class="value">{{ orderInfo.createTime || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">联系电话</text>
|
||||
<text class="label">{{ $t('payment.contactPhone') }}</text>
|
||||
<text class="value">{{ orderInfo.phone || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 费用信息 -->
|
||||
<view class="price-card">
|
||||
<view class="card-title">费用信息</view>
|
||||
<view class="card-title">{{ $t('payment.feeInfo') }}</view>
|
||||
<view class="price-item">
|
||||
<text class="label">押金</text>
|
||||
<text class="label">{{ $t('payment.deposit') }}</text>
|
||||
<text class="value">¥{{ orderInfo.deposit || '99.00' }}</text>
|
||||
</view>
|
||||
<view class="price-item">
|
||||
<text class="label">套餐</text>
|
||||
<text class="value">{{ packageInfo.price }}元/{{ packageInfo.time }}小时</text>
|
||||
<text class="label">{{ $t('payment.package') }}</text>
|
||||
<text class="value">{{ packageInfo.price }}{{ $t('unit.yuan') }}/{{ packageInfo.time }}{{ $t('time.hour') }}</text>
|
||||
</view>
|
||||
<view class="price-item total">
|
||||
<text class="label">合计</text>
|
||||
<text class="label">{{ $t('payment.total') }}</text>
|
||||
<text class="value">¥{{ totalAmount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -51,10 +51,10 @@
|
||||
<!-- 底部操作栏 -->
|
||||
<view class="bottom-bar">
|
||||
<view class="total-amount">
|
||||
<text>合计:</text>
|
||||
<text>{{ $t('payment.total') }}:</text>
|
||||
<text class="amount">¥{{ totalAmount }}</text>
|
||||
</view>
|
||||
<view class="pay-btn" @click="handlePayment">立即支付</view>
|
||||
<view class="pay-btn" @click="handlePayment">{{ $t('payment.payNow') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -81,8 +81,8 @@ export default {
|
||||
passedTotalAmount: null,
|
||||
passedDepositAmount: null,
|
||||
orderStatus: {
|
||||
text: '等待支付',
|
||||
desc: '请在15分钟内完成支付',
|
||||
get text() { return this.$t('payment.waitingForPayment') },
|
||||
get desc() { return this.$t('payment.pleasePayIn15Min') },
|
||||
class: 'waiting'
|
||||
}
|
||||
}
|
||||
@@ -117,6 +117,11 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('payment.orderPayment')
|
||||
})
|
||||
|
||||
if (options && options.orderId) {
|
||||
this.orderId = options.orderId
|
||||
|
||||
@@ -141,9 +146,9 @@ export default {
|
||||
}
|
||||
|
||||
this.loadOrderInfo()
|
||||
} else {
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '订单信息不存在',
|
||||
title: this.$t('order.orderNotExist'),
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
@@ -158,7 +163,7 @@ export default {
|
||||
async loadOrderInfo() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
title: this.$t('common.loading')
|
||||
})
|
||||
|
||||
const res = await queryById(this.orderId)
|
||||
@@ -238,7 +243,7 @@ export default {
|
||||
async handlePayment() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: this.$t('common.processing')
|
||||
})
|
||||
|
||||
// 调用后端创建微信支付订单接口
|
||||
@@ -259,7 +264,7 @@ export default {
|
||||
...payParams,
|
||||
success: async () => {
|
||||
uni.showToast({
|
||||
title: '支付成功',
|
||||
title: this.$t('payment.paymentSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
@@ -279,7 +284,7 @@ export default {
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('支付失败:', err)
|
||||
throw new Error('支付失败,请重试')
|
||||
throw new Error(this.$t('payment.paymentFailedRetry'))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -298,7 +303,7 @@ export default {
|
||||
async sendRentCommand() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: this.$t('common.processing')
|
||||
})
|
||||
|
||||
// 调用发送租借指令的接口
|
||||
@@ -307,7 +312,7 @@ export default {
|
||||
if (res.code === 200) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '租借成功',
|
||||
title: this.$t('device.rentSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
|
||||
@@ -318,12 +323,12 @@ export default {
|
||||
})
|
||||
}, 1500)
|
||||
} else {
|
||||
throw new Error(res.msg || '租借失败')
|
||||
throw new Error(res.msg || this.$t('device.rentFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '租借失败',
|
||||
title: error.message || this.$t('device.rentFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,82 +3,82 @@
|
||||
<!-- 支付成功状态 -->
|
||||
<view class="status-card">
|
||||
<view class="status-icon success"></view>
|
||||
<view class="status-text">归还成功</view>
|
||||
<view class="status-desc">您的风扇已归还,费用已从押金中扣除</view>
|
||||
<view class="status-text">{{ $t('success.returnSuccess') }}</view>
|
||||
<view class="status-desc">{{ $t('success.returnSuccessDesc') }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-card">
|
||||
<view class="card-title">订单信息</view>
|
||||
<view class="card-title">{{ $t('success.orderInfo') }}</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单号</text>
|
||||
<text class="label">{{ $t('order.orderNo') }}</text>
|
||||
<text class="value">{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">设备号</text>
|
||||
<text class="label">{{ $t('order.deviceNo') }}</text>
|
||||
<text class="value">{{ orderInfo.deviceNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">使用时长</text>
|
||||
<text class="label">{{ $t('success.usedTime') }}</text>
|
||||
<text class="value">{{ orderInfo.usedTime || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">套餐时长</text>
|
||||
<text class="value">{{ orderInfo.packageTime || '1小时' }}</text>
|
||||
<text class="label">{{ $t('success.packageTime') }}</text>
|
||||
<text class="value">{{ orderInfo.packageTime || '1' + $t('time.hour') }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">超出时长</text>
|
||||
<text class="value">{{ orderInfo.extraTime || '0分钟' }}</text>
|
||||
<text class="label">{{ $t('success.extraTime') }}</text>
|
||||
<text class="value">{{ orderInfo.extraTime || '0' + $t('time.minute') }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">归还时间</text>
|
||||
<text class="label">{{ $t('success.returnTime') }}</text>
|
||||
<text class="value">{{ orderInfo.endTime || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 费用信息 -->
|
||||
<view class="refund-card">
|
||||
<view class="card-title">费用信息</view>
|
||||
<view class="card-title">{{ $t('payment.feeInfo') }}</view>
|
||||
<view class="info-item">
|
||||
<text class="label">套餐费用</text>
|
||||
<text class="label">{{ $t('success.packageFee') }}</text>
|
||||
<text class="value">¥{{ orderInfo.packagePrice || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">超时费用</text>
|
||||
<text class="label">{{ $t('success.extraFee') }}</text>
|
||||
<text class="value">¥{{ orderInfo.extraFee || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">总费用</text>
|
||||
<text class="label">{{ $t('success.totalFee') }}</text>
|
||||
<text class="value">¥{{ orderInfo.currentFee || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">押金</text>
|
||||
<text class="label">{{ $t('success.depositAmount') }}</text>
|
||||
<text class="value">¥{{ orderInfo.deposit || '99.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">退还金额</text>
|
||||
<text class="label">{{ $t('success.refundAmount') }}</text>
|
||||
<text class="value highlight">¥{{ orderInfo.refundAmount || '99.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">退还状态</text>
|
||||
<text class="label">{{ $t('success.refundStatus') }}</text>
|
||||
<text class="value" :class="orderInfo.withdrawStatus || 'waiting'">{{ getWithdrawStatusText() }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退款说明卡片 -->
|
||||
<view class="notice-card">
|
||||
<view class="card-title">退款说明</view>
|
||||
<view class="card-title">{{ $t('success.refundNotice') }}</view>
|
||||
<view class="notice-content">
|
||||
<view>1. 押金剩余金额需要您手动申请提现</view>
|
||||
<view>2. 提现申请提交后将在1-3个工作日内退还到原支付账户</view>
|
||||
<view>3. 如有疑问,请联系客服</view>
|
||||
<view>1. {{ $t('success.refundNotice1') }}</view>
|
||||
<view>2. {{ $t('success.refundNotice2') }}</view>
|
||||
<view>3. {{ $t('success.refundNotice3') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="button-group">
|
||||
<button class="primary-btn" @click="handleWithdraw" v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">申请退款</button>
|
||||
<button class="primary-btn" @click="goToHome">返回首页</button>
|
||||
<button class="primary-btn" @click="handleWithdraw" v-if="!orderInfo.isWithdrawn && orderInfo.refundAmount > 0">{{ $t('success.applyRefund') }}</button>
|
||||
<button class="primary-btn" @click="goToHome">{{ $t('success.backToHome') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -107,12 +107,17 @@ export default {
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('success.returnSuccess')
|
||||
})
|
||||
|
||||
if (options && options.orderId) {
|
||||
this.orderId = options.orderId;
|
||||
this.loadOrderInfo();
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '订单ID不能为空',
|
||||
title: this.$t('order.orderIdRequired'),
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
@@ -124,18 +129,18 @@ export default {
|
||||
// 获取退款状态文本
|
||||
getWithdrawStatusText() {
|
||||
const statusMap = {
|
||||
'waiting': '待申请',
|
||||
'processing': '处理中',
|
||||
'success': '已退款',
|
||||
'failed': '退款失败'
|
||||
'waiting': this.$t('success.refundWaiting'),
|
||||
'processing': this.$t('success.refundProcessing'),
|
||||
'success': this.$t('success.refundSuccess'),
|
||||
'failed': this.$t('success.refundFailed')
|
||||
};
|
||||
return statusMap[this.orderInfo.withdrawStatus] || '待申请';
|
||||
return statusMap[this.orderInfo.withdrawStatus] || this.$t('success.refundWaiting');
|
||||
},
|
||||
|
||||
// 加载订单信息
|
||||
async loadOrderInfo() {
|
||||
try {
|
||||
uni.showLoading({ title: '加载中' });
|
||||
uni.showLoading({ title: this.$t('common.loading') });
|
||||
|
||||
const result = await queryById(this.orderId);
|
||||
if (result.code === 200 && result.data) {
|
||||
@@ -216,7 +221,7 @@ export default {
|
||||
} catch (error) {
|
||||
console.error('加载订单信息错误:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
title: error.message || this.$t('order.getOrderFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
@@ -227,7 +232,7 @@ export default {
|
||||
// 申请退款
|
||||
async handleWithdraw() {
|
||||
try {
|
||||
uni.showLoading({ title: '处理中' });
|
||||
uni.showLoading({ title: this.$t('common.processing') });
|
||||
|
||||
const res = await uni.request({
|
||||
url: `${URL || 'http://127.0.0.1:8080'}/app/withdraw/add/${this.orderInfo.orderNo}`,
|
||||
@@ -241,7 +246,7 @@ export default {
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 200) {
|
||||
uni.showToast({
|
||||
title: '退款申请成功',
|
||||
title: this.$t('order.refundSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
@@ -254,12 +259,12 @@ export default {
|
||||
this.loadOrderInfo();
|
||||
}, 1500);
|
||||
} else {
|
||||
throw new Error(res.data.msg || '退款申请失败');
|
||||
throw new Error(res.data.msg || this.$t('order.refundFailed'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('退款申请错误:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '退款申请失败',
|
||||
title: error.message || this.$t('order.refundFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
|
||||
+26
-19
@@ -3,27 +3,27 @@
|
||||
<!-- 支付成功状态 -->
|
||||
<view class="status-card">
|
||||
<view class="status-icon success"></view>
|
||||
<view class="status-text">支付成功</view>
|
||||
<view class="status-desc">您的订单已支付成功</view>
|
||||
<view class="status-text">{{ $t('success.paymentSuccess') }}</view>
|
||||
<view class="status-desc">{{ $t('success.paymentSuccessDesc') }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单信息 -->
|
||||
<view class="order-card">
|
||||
<view class="card-title">订单信息</view>
|
||||
<view class="card-title">{{ $t('success.orderInfo') }}</view>
|
||||
<view class="info-item">
|
||||
<text class="label">订单号</text>
|
||||
<text class="label">{{ $t('order.orderNo') }}</text>
|
||||
<text class="value">{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">设备号</text>
|
||||
<text class="label">{{ $t('order.deviceNo') }}</text>
|
||||
<text class="value">{{ orderInfo.deviceNo || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付金额</text>
|
||||
<text class="label">{{ $t('success.paymentAmount') }}</text>
|
||||
<text class="value">¥{{ orderInfo.amount || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">支付时间</text>
|
||||
<text class="label">{{ $t('success.paymentTime') }}</text>
|
||||
<text class="value">{{ orderInfo.payTime || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -38,8 +38,8 @@
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="button-group">
|
||||
<button class="primary-btn" @click="goToHome">返回首页</button>
|
||||
<button class="secondary-btn" @click="goToOrderList">查看订单</button>
|
||||
<button class="primary-btn" @click="goToHome">{{ $t('success.backToHome') }}</button>
|
||||
<button class="secondary-btn" @click="goToOrderList">{{ $t('success.viewOrder') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -54,11 +54,18 @@ export default {
|
||||
orderId: '',
|
||||
orderInfo: {},
|
||||
isLoading: true,
|
||||
deviceMessage: '正在准备您的设备,请稍候...',
|
||||
deviceMessage: '',
|
||||
hasTriggeredDevice: false
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('success.paymentSuccess')
|
||||
})
|
||||
|
||||
this.deviceMessage = this.$t('success.preparingDevice')
|
||||
|
||||
if (options && options.orderId) {
|
||||
this.orderId = options.orderId
|
||||
this.loadOrderInfo()
|
||||
@@ -70,7 +77,7 @@ export default {
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '订单信息不存在',
|
||||
title: this.$t('order.orderNotExist'),
|
||||
icon: 'none'
|
||||
})
|
||||
setTimeout(() => {
|
||||
@@ -82,7 +89,7 @@ export default {
|
||||
async loadOrderInfo() {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中'
|
||||
title: this.$t('common.loading')
|
||||
})
|
||||
|
||||
const res = await queryById(this.orderId)
|
||||
@@ -118,7 +125,7 @@ export default {
|
||||
} catch (error) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
title: error.message || this.$t('order.getOrderFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
@@ -134,7 +141,7 @@ export default {
|
||||
this.hasTriggeredDevice = true
|
||||
uni.$emit('orderSuccess:' + this.orderId)
|
||||
this.isLoading = true
|
||||
this.deviceMessage = '正在准备您的设备,请稍候...'
|
||||
this.deviceMessage = this.$t('success.preparingDevice')
|
||||
|
||||
try {
|
||||
console.log(`准备触发弹出风扇,orderId: ${this.orderId}`)
|
||||
@@ -144,19 +151,19 @@ export default {
|
||||
console.log('确认支付并弹出风扇结果:', JSON.stringify(result))
|
||||
|
||||
if (result && result.code === 200) {
|
||||
this.deviceMessage = '设备已弹出,请取走您的风扇'
|
||||
this.deviceMessage = this.$t('success.deviceReady')
|
||||
uni.showToast({
|
||||
title: '风扇已弹出',
|
||||
title: this.$t('success.deviceReady'),
|
||||
icon: 'success'
|
||||
})
|
||||
} else {
|
||||
throw new Error((result && result.msg) || '弹出风扇失败')
|
||||
throw new Error((result && result.msg) || this.$t('success.deviceFailed'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('弹出风扇错误:', error)
|
||||
this.deviceMessage = '弹出设备失败,请联系客服'
|
||||
this.deviceMessage = this.$t('success.deviceFailed')
|
||||
uni.showToast({
|
||||
title: error.message || '弹出风扇失败,请联系客服',
|
||||
title: error.message || this.$t('success.deviceFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
|
||||
+20
-20
@@ -8,7 +8,7 @@
|
||||
<!-- 场地信息卡片 -->
|
||||
<view class="info-card">
|
||||
<!-- 场地名称 -->
|
||||
<view class="position-name">{{ positionInfo.name || '加载中...' }}</view>
|
||||
<view class="position-name">{{ positionInfo.name || $t('common.loading') }}</view>
|
||||
|
||||
<!-- 地址信息 -->
|
||||
<view class="info-item" v-if="positionInfo.location">
|
||||
@@ -19,30 +19,30 @@
|
||||
<!-- 营业时间 -->
|
||||
<view class="info-item" v-if="positionInfo.workTime && positionInfo.workTime !== '0'">
|
||||
<image src="/static/device-time.png" class="item-icon" mode="aspectFit"></image>
|
||||
<text class="item-text">营业时间:{{ positionInfo.workTime }}</text>
|
||||
<text class="item-text">{{ $t('location.businessHours') }}{{ positionInfo.workTime }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 计费信息 -->
|
||||
<view class="info-item">
|
||||
<image src="/static/device-price.png" class="item-icon" mode="aspectFit"></image>
|
||||
<text class="item-text">计费:{{ pricingText }}</text>
|
||||
<text class="item-text">{{ $t('device.pricing') }}:{{ pricingText }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 按钮组 -->
|
||||
<view class="button-group">
|
||||
<view style="display: flex;flex-direction: row;gap: 10rpx;">
|
||||
<view class="status-btn" v-if="isRentable">可租借</view>
|
||||
<view class="status-btn" v-if="isReturnable">可归还</view>
|
||||
<view class="status-btn" v-if="isRentable">{{ $t('location.rent') }}</view>
|
||||
<view class="status-btn" v-if="isReturnable">{{ $t('location.return') }}</view>
|
||||
</view>
|
||||
|
||||
<view class="nav-btn" @click.stop="navigateToPosition">导航去这</view>
|
||||
<view class="nav-btn" @click.stop="navigateToPosition">{{ $t('location.navigateHere') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部操作按钮 -->
|
||||
<view class="footer-actions">
|
||||
<button class="action-btn btn-outline" @click="reportError">设备报错</button>
|
||||
<button class="action-btn btn-primary" @click="scanCode">扫码使用</button>
|
||||
<button class="action-btn btn-outline" @click="reportError">{{ $t('device.reportError') }}</button>
|
||||
<button class="action-btn btn-primary" @click="scanCode">{{ $t('device.scanToUse') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -93,7 +93,7 @@
|
||||
const loadPositionDetail = async () => {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '加载中...'
|
||||
title: $t('common.loading')
|
||||
})
|
||||
|
||||
const res = await uni.request({
|
||||
@@ -111,10 +111,10 @@
|
||||
if (position) {
|
||||
positionInfo.value = position
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '场地不存在',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.showToast({
|
||||
title: this.$t('location.notExist'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} else if (res.statusCode === 401 || res.data?.code === 401 || res.data?.code === 40101) {
|
||||
uni.reLaunch({
|
||||
@@ -124,7 +124,7 @@
|
||||
} catch (e) {
|
||||
console.error('加载场地详情失败:', e)
|
||||
uni.showToast({
|
||||
title: '加载失败',
|
||||
title: $t('common.loadFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
@@ -135,7 +135,7 @@
|
||||
const navigateToPosition = () => {
|
||||
if (!positionInfo.value.latitude || !positionInfo.value.longitude) {
|
||||
uni.showToast({
|
||||
title: '该场地坐标信息异常',
|
||||
title: $t('location.coordinateError'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -150,7 +150,7 @@
|
||||
longitude < -180 || longitude > 180 ||
|
||||
(latitude === 0 && longitude === 0)) {
|
||||
uni.showToast({
|
||||
title: '该场地坐标信息异常',
|
||||
title: $t('location.coordinateError'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -185,10 +185,10 @@
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('扫码失败:', err)
|
||||
uni.showToast({
|
||||
title: '扫码失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.showToast({
|
||||
title: this.$t('home.scanFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
+63
-58
@@ -4,13 +4,13 @@
|
||||
<view class="order-card">
|
||||
<view class="order-header">
|
||||
<text class="title">{{ getOrderStatusText() }}</text>
|
||||
<text class="order-no">订单号:{{ orderInfo.orderNo || '-' }}</text>
|
||||
<text class="order-no">{{ $t('order.orderNo') }}:{{ orderInfo.orderNo || '-' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="device-info">
|
||||
<view class="device-left">
|
||||
<view class="device-name">共享风扇</view>
|
||||
<view class="device-id">设备号:{{ deviceId }}</view>
|
||||
<view class="device-name">{{ $t('device.sharedFan') }}</view>
|
||||
<view class="device-id">{{ $t('order.deviceNo') }}:{{ deviceId }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 支付方式标识 -->
|
||||
@@ -19,41 +19,41 @@
|
||||
<view class="payment-badge wx-score" v-if="orderInfo.payWay == 'wx_score_pay'">
|
||||
<image src="/static/images/wxpayflag.png" mode="aspectFit" class="badge-icon"></image>
|
||||
<view class="badge-text">
|
||||
<text>微信支付分</text>
|
||||
<text>{{ $t('order.wxPayScore') }}</text>
|
||||
<text class="divider">|</text>
|
||||
<text class="highlight">免押租借</text>
|
||||
<text class="highlight">{{ $t('order.depositFree') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 会员订单标识 -->
|
||||
<view class="payment-badge member" v-else-if="orderInfo.payWay == 'wx_member_pay'">
|
||||
<text class="badge-text">会员订单</text>
|
||||
<text class="badge-text">{{ $t('order.memberOrder') }}</text>
|
||||
</view>
|
||||
<!-- 微信支付(押金)标识 -->
|
||||
<view class="payment-badge deposit" v-else-if="orderInfo.payWay == 'wx_pay'">
|
||||
<text class="badge-text">押金租借</text>
|
||||
<text class="badge-text">{{ $t('order.depositPay') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="time-info">
|
||||
<view class="time-item">
|
||||
<text class="label">开始时间</text>
|
||||
<text class="label">{{ $t('order.startTime') }}</text>
|
||||
<text class="value">{{ orderInfo.startTime }}</text>
|
||||
</view>
|
||||
<view class="time-item" v-if="orderInfo.endTime">
|
||||
<text class="label">结束时间</text>
|
||||
<text class="label">{{ $t('order.endTime') }}</text>
|
||||
<text class="value">{{ orderInfo.endTime }}</text>
|
||||
</view>
|
||||
<view class="time-item" v-if="orderInfo.orderStatus === 'in_used'">
|
||||
<text class="label">已使用时长</text>
|
||||
<text class="label">{{ $t('order.used') }}</text>
|
||||
<text class="value highlight">{{ orderInfo.usedTime }}</text>
|
||||
</view>
|
||||
<view class="time-item" v-if="orderInfo.orderStatus === 'in_used'">
|
||||
<text class="label">当前费用</text>
|
||||
<text class="label">{{ $t('order.currentFee') }}</text>
|
||||
<text class="value">¥{{ orderInfo.currentFee }}</text>
|
||||
</view>
|
||||
<view class="time-item" v-if="orderInfo.phone">
|
||||
<text class="label">联系电话</text>
|
||||
<text class="label">{{ $t('payment.contactPhone') }}</text>
|
||||
<text class="value">{{ orderInfo.phone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -69,42 +69,42 @@
|
||||
|
||||
<!-- 费用信息卡片 -->
|
||||
<view class="notice-card" v-if="orderInfo.depositAmount || orderInfo.packageTime">
|
||||
<view class="notice-title">费用信息</view>
|
||||
<view class="notice-title">{{ $t('payment.feeInfo') }}</view>
|
||||
<view class="notice-list">
|
||||
<view class="notice-item" v-if="orderInfo.depositAmount">
|
||||
<view class="dot"></view>
|
||||
<text>押金:¥{{ orderInfo.depositAmount }}</text>
|
||||
<text>{{ $t('payment.deposit') }}:¥{{ orderInfo.depositAmount }}</text>
|
||||
</view>
|
||||
<view class="notice-item" v-if="orderInfo.packageTime && orderInfo.packagePrice">
|
||||
<view class="dot"></view>
|
||||
<text>套餐:¥{{ orderInfo.packagePrice }}元 / {{ formatTime(orderInfo.packageTime) }}</text>
|
||||
<text>{{ $t('payment.package') }}:¥{{ orderInfo.packagePrice }}{{ $t('unit.yuan') }} / {{ formatTime(orderInfo.packageTime) }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="dot"></view>
|
||||
<text>合计:¥{{ orderInfo.payAmount || 0 }}</text>
|
||||
<text>{{ $t('payment.total') }}:¥{{ orderInfo.payAmount || 0 }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 归还说明 -->
|
||||
<view class="notice-card" v-if="orderInfo.orderStatus === 'in_used'">
|
||||
<view class="notice-title">归还说明</view>
|
||||
<view class="notice-title">{{ $t('order.returnInstructions') }}</view>
|
||||
<view class="notice-list">
|
||||
<view class="notice-item">
|
||||
<view class="dot"></view>
|
||||
<text>请确保设备完好无损</text>
|
||||
<text>{{ $t('order.ensureDeviceIntact') }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="dot"></view>
|
||||
<text>将风扇插入原位置或空闲插口</text>
|
||||
<text>{{ $t('order.insertFanBack') }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="dot"></view>
|
||||
<text>系统将自动检测归还并处理退款</text>
|
||||
<text>{{ $t('order.autoDetectReturn') }}</text>
|
||||
</view>
|
||||
<view class="notice-item">
|
||||
<view class="dot"></view>
|
||||
<text>归还成功后将自动跳转到成功页面</text>
|
||||
<text>{{ $t('order.autoJumpAfterReturn') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -117,25 +117,25 @@
|
||||
<view class="bottom-bar">
|
||||
<!-- 使用中状态显示归还相关操作 -->
|
||||
<view v-if="orderInfo.orderStatus === 'in_used'" class="action-item secondary" @click="checkReturnStatus">
|
||||
刷新状态</view>
|
||||
{{ $t('order.refreshStatus') }}</view>
|
||||
<view v-if="orderInfo.orderStatus === 'in_used' && !showExpressAction" class="action-item primary">
|
||||
倒计时{{ formatHms(countdownRemaining) }}
|
||||
{{ $t('order.countdown') }}{{ formatHms(countdownRemaining) }}
|
||||
</view>
|
||||
<view v-if="orderInfo.orderStatus === 'in_used' && showExpressAction" class="action-item primary" @click="expressRetrunOrder">
|
||||
暂停计费,快递归还
|
||||
{{ $t('order.pauseAndExpress') }}
|
||||
</view>
|
||||
|
||||
<!-- 已完成状态显示查看详情和返回首页 -->
|
||||
<view v-if="orderInfo.orderStatus === 'used_done' || orderInfo.orderStatus === 'used_down'"
|
||||
class="action-item secondary" @click="goToHome">返回首页</view>
|
||||
class="action-item secondary" @click="goToHome">{{ $t('order.backToHome') }}</view>
|
||||
<view v-if="orderInfo.orderStatus === 'used_done' || orderInfo.orderStatus === 'used_down'"
|
||||
class="action-item primary" @click="viewOrderDetails">查看详情</view>
|
||||
class="action-item primary" @click="viewOrderDetails">{{ $t('order.viewDetails') }}</view>
|
||||
|
||||
<!-- 待支付状态显示支付和取消操作 -->
|
||||
<view v-if="orderInfo.orderStatus === 'waiting_for_payment'" class="action-item secondary"
|
||||
@click="handleCancelOrder">取消订单</view>
|
||||
@click="handleCancelOrder">{{ $t('order.cancelOrder') }}</view>
|
||||
<view v-if="orderInfo.orderStatus === 'waiting_for_payment'" class="action-item primary"
|
||||
@click="handlePayment">立即支付</view>
|
||||
@click="handlePayment">{{ $t('order.payNow') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -190,6 +190,11 @@
|
||||
onLoad(options) {
|
||||
console.log('Return page loaded with options:', JSON.stringify(options))
|
||||
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('order.orderDetail')
|
||||
})
|
||||
|
||||
// 标记页面为活跃状态
|
||||
this.isPageActive = true
|
||||
|
||||
@@ -209,7 +214,7 @@
|
||||
} else {
|
||||
// 缺少必要参数
|
||||
uni.showToast({
|
||||
title: '缺少订单信息',
|
||||
title: this.$t('order.orderInfoMissing'),
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
@@ -406,9 +411,9 @@
|
||||
|
||||
// 显示归还成功弹窗
|
||||
uni.showModal({
|
||||
title: '归还成功',
|
||||
content: '风扇已归还成功,剩余押金将退还到您的账户',
|
||||
confirmText: '查看详情',
|
||||
title: this.$t('order.returnSuccess'),
|
||||
content: this.$t('order.returnSuccessMessage'),
|
||||
confirmText: this.$t('order.viewDetails'),
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 跳转到归还成功页面查看详情
|
||||
@@ -428,17 +433,17 @@
|
||||
// 根据订单状态获取对应的文字显示
|
||||
getOrderStatusText() {
|
||||
const statusMap = {
|
||||
'waiting_for_payment': '待支付',
|
||||
'payment_in_progress': '支付中',
|
||||
'payment_successful': '支付成功',
|
||||
'in_used': '使用中',
|
||||
'payment_failed': '支付失败',
|
||||
'order_cancelled': '已取消',
|
||||
'used_done': '已完成',
|
||||
'used_down': '已完成'
|
||||
'waiting_for_payment': this.$t('order.waitingForPayment'),
|
||||
'payment_in_progress': this.$t('order.paymentInProgress'),
|
||||
'payment_successful': this.$t('order.paymentSuccess'),
|
||||
'in_used': this.$t('order.inUse'),
|
||||
'payment_failed': this.$t('order.paymentFailed'),
|
||||
'order_cancelled': this.$t('order.cancelled'),
|
||||
'used_done': this.$t('order.finished'),
|
||||
'used_down': this.$t('order.finished')
|
||||
}
|
||||
|
||||
return statusMap[this.orderInfo.orderStatus] || '使用中'
|
||||
return statusMap[this.orderInfo.orderStatus] || this.$t('order.inUse')
|
||||
},
|
||||
|
||||
// 获取订单详情
|
||||
@@ -453,7 +458,7 @@
|
||||
// uni.showLoading({ title: '加载中' })
|
||||
|
||||
if (!this.orderInfo.orderId) {
|
||||
throw new Error('订单ID不能为空')
|
||||
throw new Error(this.$t('order.orderIdRequired'))
|
||||
}
|
||||
|
||||
const result = await queryById(this.orderInfo.orderId)
|
||||
@@ -527,7 +532,7 @@
|
||||
} catch (error) {
|
||||
console.error('获取订单详情错误:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
title: error.message || this.$t('order.getOrderFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
@@ -679,12 +684,12 @@
|
||||
if (this.currentStatusChecks >= this.maxStatusChecks) {
|
||||
this.clearStatusCheckTimer()
|
||||
|
||||
// 提示用户手动刷新
|
||||
uni.showToast({
|
||||
title: '请手动刷新查看归还状态',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
// 提示用户手动刷新
|
||||
uni.showToast({
|
||||
title: this.$t('order.pleaseRefreshManually'),
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.log('页面已不活跃,停止状态检查计时器')
|
||||
@@ -701,7 +706,7 @@
|
||||
// uni.showLoading({ title: '加载中' })
|
||||
|
||||
if (!this.deviceId) {
|
||||
throw new Error('设备号不能为空')
|
||||
throw new Error(this.$t('device.deviceNoRequired'))
|
||||
}
|
||||
|
||||
// 这里调用API查询该设备的使用中订单
|
||||
@@ -742,12 +747,12 @@
|
||||
// 获取详细订单信息
|
||||
this.getOrderDetails()
|
||||
} else {
|
||||
throw new Error('未找到使用中的订单')
|
||||
throw new Error(this.$t('order.noOrderInUse'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('通过设备号查询订单失败:', error)
|
||||
uni.showToast({
|
||||
title: error.message || '获取订单信息失败',
|
||||
title: error.message || this.$t('order.getOrderFailed'),
|
||||
icon: 'none'
|
||||
})
|
||||
|
||||
@@ -795,13 +800,13 @@
|
||||
// 取消订单
|
||||
handleCancelOrder() {
|
||||
uni.showModal({
|
||||
title: '确认取消',
|
||||
content: '确定要取消此订单吗?',
|
||||
title: this.$t('order.confirmCancel'),
|
||||
content: this.$t('order.confirmCancelContent'),
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中'
|
||||
title: this.$t('common.processing')
|
||||
});
|
||||
const result = await cancelOrder({
|
||||
orderId: this.orderInfo.orderId
|
||||
@@ -809,17 +814,17 @@
|
||||
if (result.code === 200) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '订单已取消',
|
||||
title: this.$t('order.cancelSuccess'),
|
||||
icon: 'success'
|
||||
});
|
||||
await this.getOrderDetails();
|
||||
} else {
|
||||
throw new Error(result.msg || '取消订单失败');
|
||||
throw new Error(result.msg || this.$t('order.cancelFailed'));
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: error.message || '取消订单失败',
|
||||
title: error.message || this.$t('order.cancelFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
+28
-21
@@ -12,8 +12,8 @@
|
||||
<view class="list-wrap">
|
||||
<view class="panel">
|
||||
<view class="filter-tabs">
|
||||
<view class="tab" :class="{ active: activeTab === 'rent' }" @click="setTab('rent')">可租借</view>
|
||||
<view class="tab" :class="{ active: activeTab === 'return' }" @click="setTab('return')">可归还</view>
|
||||
<view class="tab" :class="{ active: activeTab === 'rent' }" @click="setTab('rent')">{{ $t('location.rent') }}</view>
|
||||
<view class="tab" :class="{ active: activeTab === 'return' }" @click="setTab('return')">{{ $t('location.return') }}</view>
|
||||
</view>
|
||||
<scroll-view class="list-scroll" scroll-y="true">
|
||||
<view class="card" :class="{ available: isRentable(item), invalid: !isValidCoordinate(item.latitude, item.longitude) }"
|
||||
@@ -28,16 +28,16 @@
|
||||
<view class="row sub" v-if="item.location">
|
||||
<text class="addr">{{ item.location }}</text>
|
||||
</view>
|
||||
<view class="row meta" v-if="item.workTime && item.workTime !== '0'">
|
||||
<text class="time">营业时间:{{ item.workTime }}</text>
|
||||
</view>
|
||||
<view class="row meta" v-if="!isValidCoordinate(item.latitude, item.longitude)">
|
||||
<text class="time" style="color: #ff6b6b;">坐标信息异常</text>
|
||||
</view>
|
||||
<view class="tags">
|
||||
<view class="tag rent" v-if="isRentable(item)">可租借</view>
|
||||
<view class="tag return" v-if="isReturnable(item)">可归还</view>
|
||||
</view>
|
||||
<view class="row meta" v-if="item.workTime && item.workTime !== '0'">
|
||||
<text class="time">{{ $t('location.businessHours') }}{{ item.workTime }}</text>
|
||||
</view>
|
||||
<view class="row meta" v-if="!isValidCoordinate(item.latitude, item.longitude)">
|
||||
<text class="time" style="color: #ff6b6b;">{{ $t('location.coordinateError') }}</text>
|
||||
</view>
|
||||
<view class="tags">
|
||||
<view class="tag rent" v-if="isRentable(item)">{{ $t('location.rent') }}</view>
|
||||
<view class="tag return" v-if="isReturnable(item)">{{ $t('location.return') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="actions">
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="empty-state" v-if="!isLoading && (!positionList || positionList.length === 0)">
|
||||
<image class="empty-icon" src="/static/scan-icon.png" mode="aspectFit" />
|
||||
<text class="empty-text">附近暂无设备</text>
|
||||
</view>
|
||||
<view class="empty-state" v-if="!isLoading && (!positionList || positionList.length === 0)">
|
||||
<image class="empty-icon" src="/static/scan-icon.png" mode="aspectFit" />
|
||||
<text class="empty-text">{{ $t('home.noNearbyDevice') }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -75,6 +75,16 @@
|
||||
getRegeo,
|
||||
calculateDistanceSync
|
||||
} from '../../utils/mapUtils.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('search.title')
|
||||
})
|
||||
init()
|
||||
})
|
||||
|
||||
const userLocation = ref(null)
|
||||
const positionList = ref([])
|
||||
@@ -208,7 +218,7 @@
|
||||
const navigateToPosition = (position) => {
|
||||
if (!isValidCoordinate(position.latitude, position.longitude)) {
|
||||
uni.showToast({
|
||||
title: '该位置坐标无效',
|
||||
title: $t('search.invalidCoordinate'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -226,7 +236,7 @@
|
||||
const goToPositionDetail = (position) => {
|
||||
if (!position.positionId) {
|
||||
uni.showToast({
|
||||
title: '场地信息异常',
|
||||
title: $t('search.positionInfoError'),
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
@@ -236,9 +246,6 @@
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -25,15 +25,21 @@
|
||||
},
|
||||
async onLoad(option) {
|
||||
console.log('bagCheck onLoad option:', option);
|
||||
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('device.checking')
|
||||
})
|
||||
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '处理中...',
|
||||
title: this.$t('common.processing'),
|
||||
mask: true
|
||||
});
|
||||
|
||||
// 检查是否传入设备编号
|
||||
if (!option || !option.deviceNo) {
|
||||
throw new Error('未识别到设备编号');
|
||||
throw new Error(this.$t('device.deviceNoNotRecognized'));
|
||||
}
|
||||
|
||||
const deviceNo = option.deviceNo;
|
||||
@@ -97,10 +103,10 @@
|
||||
error.message.includes('未识别到设备编号') ||
|
||||
error.message.includes('网络请求失败') ||
|
||||
error.message.includes('服务器错误')
|
||||
)) {
|
||||
) ) {
|
||||
console.error('扫码检查订单失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '处理失败,请稍后重试',
|
||||
title: error.message || this.$t('device.processFailed'),
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
+110
-6
@@ -1,18 +1,27 @@
|
||||
<template>
|
||||
<view class="setting-page">
|
||||
<view class="group">
|
||||
<view class="item" @click="showLanguageSelector">
|
||||
<text class="label">{{ $t('settings.language') }}</text>
|
||||
<view class="right">
|
||||
<text class="value">{{ currentLanguageText }}</text>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="group">
|
||||
<view class="item" @click="navigateTo('/pages/legal/agreement')">
|
||||
<text class="label">用户协议</text>
|
||||
<text class="label">{{ $t('user.userAgreement') }}</text>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
<view class="item" @click="navigateTo('/pages/legal/privacy')">
|
||||
<text class="label">隐私政策</text>
|
||||
<text class="label">{{ $t('user.privacyPolicy') }}</text>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view class="group">
|
||||
<view class="item" @click="handleLogout">
|
||||
<text class="label">退出登录</text>
|
||||
<text class="label">{{ $t('user.logout') }}</text>
|
||||
<uv-icon name="arrow-right" size="16" color="#c8c8c8"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
@@ -20,21 +29,105 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, getCurrentInstance } from 'vue'
|
||||
import { userLogout } from '@/config/api/user.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 获取全局 i18n 实例
|
||||
const instance = getCurrentInstance()
|
||||
const globalI18n = instance?.appContext?.config?.globalProperties?.$i18n
|
||||
|
||||
// 设置页面标题
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('settings.title')
|
||||
})
|
||||
})
|
||||
|
||||
// 当前语言
|
||||
const currentLanguage = ref(uni.getStorageSync('language') || 'zh-CN')
|
||||
|
||||
// 当前语言文本显示
|
||||
const currentLanguageText = computed(() => {
|
||||
return currentLanguage.value === 'zh-CN' ? '简体中文' : 'English'
|
||||
})
|
||||
|
||||
const navigateTo = (url) => {
|
||||
uni.navigateTo({ url })
|
||||
}
|
||||
|
||||
// 显示语言选择器
|
||||
const showLanguageSelector = () => {
|
||||
uni.showActionSheet({
|
||||
itemList: ['简体中文', 'English'],
|
||||
success: (res) => {
|
||||
const lang = res.tapIndex === 0 ? 'zh-CN' : 'en-US'
|
||||
if (lang !== currentLanguage.value) {
|
||||
console.log('========================================')
|
||||
console.log('=== 用户选择切换语言 ===')
|
||||
console.log('旧语言:', currentLanguage.value)
|
||||
console.log('新语言:', lang)
|
||||
|
||||
// 1. 保存到缓存
|
||||
uni.setStorageSync('language', lang)
|
||||
console.log('✓ 语言已保存到缓存')
|
||||
|
||||
// 2. 立即更新 i18n 实例(重要!)
|
||||
if (globalI18n) {
|
||||
console.log('✓ 正在更新 globalI18n.locale...')
|
||||
console.log(' 更新前:', globalI18n.locale)
|
||||
globalI18n.locale = lang
|
||||
console.log(' 更新后:', globalI18n.locale)
|
||||
console.log('✓ 测试翻译:', globalI18n.t('common.loading'))
|
||||
} else {
|
||||
console.warn('✗ globalI18n 不存在!')
|
||||
console.warn(' instance:', !!instance)
|
||||
console.warn(' appContext:', !!instance?.appContext)
|
||||
console.warn(' globalProperties:', !!instance?.appContext?.config?.globalProperties)
|
||||
}
|
||||
|
||||
// 3. 更新当前语言状态
|
||||
currentLanguage.value = lang
|
||||
|
||||
console.log('========================================')
|
||||
|
||||
// 4. 提示用户
|
||||
uni.showToast({
|
||||
title: lang === 'zh-CN' ? '语言已切换,正在刷新...' : 'Language switched, refreshing...',
|
||||
icon: 'none',
|
||||
duration: 800
|
||||
})
|
||||
|
||||
// 5. 延迟后重新加载应用(确保 i18n 更新已生效)
|
||||
setTimeout(() => {
|
||||
console.log('=== 准备 reLaunch 到首页 ===')
|
||||
// 使用 reLaunch 完全重启应用
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index',
|
||||
success: () => {
|
||||
console.log('✓ 页面已重新加载')
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('✗ 页面重载失败:', err)
|
||||
}
|
||||
})
|
||||
}, 800)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleLogout = async () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
title: $t('common.tips'),
|
||||
content: $t('user.confirmLogout'),
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
const response = await userLogout();
|
||||
if (response.code == 200) {
|
||||
uni.showToast({ title: '退出成功', icon: 'none' })
|
||||
uni.showToast({ title: $t('user.logoutSuccess'), icon: 'none' })
|
||||
setTimeout(() => {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('userInfo')
|
||||
@@ -77,4 +170,15 @@ const handleLogout = async () => {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
</style>
|
||||
+27
-15
@@ -6,40 +6,40 @@
|
||||
<image :src="userInfo.avatar || '/static/images/default-avatar.png'" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="user-info">
|
||||
<text class="nickname">{{ userInfo.nickName || '未登录' }}</text>
|
||||
<text class="phone">{{ userInfo.phone || '未绑定手机号' }}</text>
|
||||
<text class="nickname">{{ userInfo.nickName || $t('user.notLoggedIn') }}</text>
|
||||
<text class="phone">{{ userInfo.phone || $t('user.phoneNotBound') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 余额卡片 -->
|
||||
<view class="balance-card">
|
||||
<view class="balance-title">余额</view>
|
||||
<view class="balance-title">{{ $t('userProfile.balance') }}</view>
|
||||
<view class="balance-amount">¥{{ userInfo.balanceAmount || '0.00' }}</view>
|
||||
<view class="balance-desc">可用于租借设备</view>
|
||||
<view class="balance-desc">{{ $t('user.balanceDesc') }}</view>
|
||||
</view>
|
||||
|
||||
<!-- 功能菜单 -->
|
||||
<view class="menu-list">
|
||||
<view class="menu-item" @click="navigateTo('/pages/order/list')">
|
||||
<view class="menu-item" @click="navigateTo('/pages/order/index')">
|
||||
<text class="menu-icon">📋</text>
|
||||
<text class="menu-text">我的订单</text>
|
||||
<text class="menu-text">{{ $t('user.myOrders') }}</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/feedback')">
|
||||
<view class="menu-item" @click="navigateTo('/pages/feedback/index')">
|
||||
<text class="menu-icon">💬</text>
|
||||
<text class="menu-text">意见反馈</text>
|
||||
<text class="menu-text">{{ $t('user.feedback') }}</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
<view class="menu-item" @click="navigateTo('/pages/user/about')">
|
||||
<view class="menu-item" @click="navigateTo('/pages/help/index')">
|
||||
<text class="menu-icon">ℹ️</text>
|
||||
<text class="menu-text">关于我们</text>
|
||||
<text class="menu-text">{{ $t('help.title') }}</text>
|
||||
<text class="menu-arrow">></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 退出登录按钮 -->
|
||||
<view class="logout-btn" @click="handleLogout" v-if="isLogin">
|
||||
<text>退出登录</text>
|
||||
<text>{{ $t('user.logout') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -55,6 +55,12 @@ export default {
|
||||
isLogin: false
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 设置页面标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.$t('user.personalCenter')
|
||||
})
|
||||
},
|
||||
onShow() {
|
||||
this.loadUserInfo()
|
||||
},
|
||||
@@ -90,16 +96,22 @@ export default {
|
||||
},
|
||||
handleLogout() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要退出登录吗?',
|
||||
title: this.$t('common.tips'),
|
||||
content: this.$t('user.confirmLogout'),
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('userInfo')
|
||||
this.isLogin = false
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
uni.showToast({
|
||||
title: this.$t('user.logoutSuccess'),
|
||||
icon: 'success'
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/index'
|
||||
})
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+26
-20
@@ -9,15 +9,15 @@
|
||||
<button class="avatar-choose-btn" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"></button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="avatar-tip">点击头像更换</view>
|
||||
</view>
|
||||
<view class="avatar-tip">{{ $t('userProfile.clickToChange') }}</view>
|
||||
</view>
|
||||
|
||||
<view class="form-section">
|
||||
<!-- 昵称编辑区域 -->
|
||||
<view class="form-item nickname-item" :class="{ editing: isEditingNickname }">
|
||||
<view class="label">昵称</view>
|
||||
<view class="label">{{ $t('userProfile.nickname') }}</view>
|
||||
<view class="value" v-if="!isEditingNickname" @click="startEditNickname">
|
||||
<text class="value-text">{{ userInfo.nickName || '未设置' }}</text>
|
||||
<text class="value-text">{{ userInfo.nickName || $t('userProfile.notSet') }}</text>
|
||||
<uv-icon name="edit-pen" size="16" color="#999999"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
@@ -27,25 +27,25 @@
|
||||
<input
|
||||
class="nickname-input"
|
||||
v-model="newNickname"
|
||||
placeholder="请输入新昵称"
|
||||
:placeholder="$t('userProfile.enterNickname')"
|
||||
maxlength="20"
|
||||
:focus="true"
|
||||
/>
|
||||
<view class="edit-buttons">
|
||||
<button class="cancel-btn" @click="cancelEditNickname">取消</button>
|
||||
<button class="save-btn" @click="saveNickname">保存</button>
|
||||
<button class="cancel-btn" @click="cancelEditNickname">{{ $t('common.cancel') }}</button>
|
||||
<button class="save-btn" @click="saveNickname">{{ $t('common.save') }}</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="label">手机号</view>
|
||||
<view class="label">{{ $t('userProfile.phone') }}</view>
|
||||
<view class="value">
|
||||
<text class="value-text">{{ userInfo.phone ? maskPhone(userInfo.phone) : '未绑定' }}</text>
|
||||
<text class="value-text">{{ userInfo.phone ? maskPhone(userInfo.phone) : $t('userProfile.notBound') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item" v-if="userInfo.balanceAmount !== undefined">
|
||||
<view class="label">余额</view>
|
||||
<view class="label">{{ $t('userProfile.balance') }}</view>
|
||||
<view class="value">
|
||||
<text class="value-text amount">¥{{ userInfo.balanceAmount || '0.00' }}</text>
|
||||
</view>
|
||||
@@ -57,6 +57,9 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { getMyIndexInfo, uploadUserAvatar, updateUserInfo } from '../../config/api/user.js';
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
// 响应式状态
|
||||
const userInfo = ref({
|
||||
@@ -71,6 +74,9 @@ const isEditingNickname = ref(false);
|
||||
|
||||
// 页面加载时初始化
|
||||
onMounted(() => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('userProfile.title')
|
||||
})
|
||||
loadUserInfo();
|
||||
});
|
||||
|
||||
@@ -96,7 +102,7 @@ const loadUserInfo = async () => {
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取用户信息失败',
|
||||
title: $t('user.getUserInfoFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
@@ -132,13 +138,13 @@ const onChooseAvatar = async (e) => {
|
||||
const avatarLocalPath = e?.detail?.avatarUrl;
|
||||
if (!avatarLocalPath) {
|
||||
uni.showToast({
|
||||
title: '未选择头像',
|
||||
title: $t('user.noAvatar'),
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.showLoading({
|
||||
title: '上传中...',
|
||||
title: $t('userProfile.uploading'),
|
||||
mask: true
|
||||
});
|
||||
const uploadRes = await uploadUserAvatar(avatarLocalPath);
|
||||
@@ -151,14 +157,14 @@ const onChooseAvatar = async (e) => {
|
||||
uni.setStorageSync('userInfo', userInfo.value);
|
||||
}
|
||||
uni.showToast({
|
||||
title: '头像更新成功',
|
||||
title: $t('user.avatarUpdated'),
|
||||
icon: 'success'
|
||||
});
|
||||
await loadUserInfo();
|
||||
} catch (err) {
|
||||
console.error('选择/上传头像失败:', err);
|
||||
uni.showToast({
|
||||
title: '头像更新失败',
|
||||
title: $t('user.avatarUploadFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
@@ -182,7 +188,7 @@ const cancelEditNickname = () => {
|
||||
const saveNickname = async () => {
|
||||
if (!newNickname.value || !newNickname.value.trim()) {
|
||||
uni.showToast({
|
||||
title: '昵称不能为空',
|
||||
title: $t('userProfile.nicknameRequired'),
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
@@ -190,7 +196,7 @@ const saveNickname = async () => {
|
||||
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: '保存中...',
|
||||
title: $t('userProfile.saving'),
|
||||
mask: true
|
||||
});
|
||||
|
||||
@@ -222,19 +228,19 @@ const saveNickname = async () => {
|
||||
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '昵称修改成功',
|
||||
title: $t('userProfile.nicknameUpdated'),
|
||||
icon: 'success'
|
||||
});
|
||||
isEditingNickname.value = false;
|
||||
} else {
|
||||
throw new Error(res.message || '修改失败');
|
||||
throw new Error(res.message || $t('userProfile.updateFailed'));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('修改昵称失败:', error);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: error.message || '修改失败',
|
||||
title: error.message || $t('userProfile.updateFailed'),
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
+11
-5
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view class="waiting-container">
|
||||
<view class="title">设备弹出中,请稍候</view>
|
||||
<view class="title">{{ $t('waiting.title') }}</view>
|
||||
<view class="progress-wrapper">
|
||||
<view class="progress-circle">
|
||||
<view class="progress-left">
|
||||
@@ -11,12 +11,12 @@
|
||||
</view>
|
||||
<view class="progress-inner">
|
||||
<text class="percent">{{ progress }}%</text>
|
||||
<text class="hint">正在为您弹出设备</text>
|
||||
<text class="hint">{{ $t('waiting.preparing') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="desc">若长时间未弹出,请联系现场工作人员或稍后重试</view>
|
||||
<view class="desc">{{ $t('waiting.longTimeNotice') }}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
import { ref, onMounted, onUnmounted } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
import { getOrderByOrderNoScorePayStatus, cancelOrder } from '@/config/api/order.js'
|
||||
import { useI18n } from '@/utils/i18n.js'
|
||||
|
||||
const { t: $t } = useI18n()
|
||||
|
||||
const progress = ref(0)
|
||||
const leftRotateDeg = ref(0)
|
||||
@@ -83,7 +86,7 @@
|
||||
await cancelOrder({ orderId: orderNo.value })
|
||||
}
|
||||
} catch (e) {}
|
||||
uni.showToast({ title: '设备租借失败,订单已取消', icon: 'none' })
|
||||
uni.showToast({ title: $t('waiting.rentFailed'), icon: 'none' })
|
||||
setTimeout(() => {
|
||||
uni.switchTab({ url: '/pages/index/index' })
|
||||
}, 800)
|
||||
@@ -111,7 +114,7 @@
|
||||
// 超时保护:例如 60 秒
|
||||
timeoutTimer = setTimeout(() => {
|
||||
stopAllTimers()
|
||||
uni.showToast({ title: '等待超时,请稍后重试', icon: 'none' })
|
||||
uni.showToast({ title: $t('waiting.timeout'), icon: 'none' })
|
||||
setTimeout(() => {
|
||||
uni.switchTab({ url: '/pages/index/index' })
|
||||
}, 800)
|
||||
@@ -119,6 +122,9 @@
|
||||
}
|
||||
|
||||
onLoad((query) => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: $t('waiting.title')
|
||||
})
|
||||
if (query && query.orderNo) {
|
||||
orderNo.value = query.orderNo
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user