feat:套餐办理界面中英适配
This commit is contained in:
@@ -518,16 +518,28 @@ const local: any = {
|
||||
},
|
||||
},
|
||||
setmeal:{
|
||||
changemeallable:'Change package discount|The traffic is unlimited, and you can choose from multiple grades!',
|
||||
changablelevel:'Selectable gears',
|
||||
highlyrecommended:'HOT',
|
||||
mealmin:'min',
|
||||
mealvip:'VIP*1',
|
||||
mealdetail:'Course details',
|
||||
Limitedtimeoffer:'Limited time offer',
|
||||
GeneralPurposeTraffic:'General Purpose Traffic',
|
||||
packagename:'Package name',
|
||||
client:'Client',
|
||||
GeneralPurposeTraffic:'Traffic',
|
||||
Expirationdate:'Expiration date',
|
||||
rate:'Rate',
|
||||
unlimit:'Unlimited',
|
||||
uplimit:'Up rate',
|
||||
downlimit:'Down rate',
|
||||
useful:' validity',
|
||||
device:'device',
|
||||
upto:'Up to ',
|
||||
canbe:' device can be online simultaneously',
|
||||
hour:'Hour',
|
||||
day:'Day',
|
||||
month:'Month',
|
||||
year:'Year',
|
||||
unknow:'Unknow',
|
||||
Effectivemethod:'Effective method',
|
||||
Applynow:'Apply now',
|
||||
noPackages:'No packages'
|
||||
},
|
||||
carddata:{
|
||||
email:'Email',
|
||||
|
||||
@@ -520,16 +520,28 @@ const local:any = {
|
||||
}
|
||||
},
|
||||
setmeal:{
|
||||
changemeallable:'换套餐优惠|流量畅用,多个档次任你选!',
|
||||
changablelevel:'可选档位',
|
||||
highlyrecommended:'强烈推荐',
|
||||
mealmin:'分钟',
|
||||
mealvip:'会员',
|
||||
mealdetail:'套餐详情',
|
||||
Limitedtimeoffer:'限时优惠',
|
||||
packagename:'套餐名称',
|
||||
client:'设备数量',
|
||||
GeneralPurposeTraffic:'通用流量',
|
||||
Expirationdate:'有效期限',
|
||||
rate:'套餐速率',
|
||||
unlimit:'无限制',
|
||||
uplimit:'上行速率',
|
||||
downlimit:'下行速率',
|
||||
useful:'内有效',
|
||||
device:'台设备',
|
||||
upto:'最多',
|
||||
canbe:'台设备允许同时在线',
|
||||
hour:'小时',
|
||||
day:'天',
|
||||
month:'月',
|
||||
year:'年',
|
||||
unknow:'未知',
|
||||
Effectivemethod:'生效方式',
|
||||
Applynow:'立即办理',
|
||||
noPackages:'暂无套餐'
|
||||
},
|
||||
carddata:{
|
||||
email:'邮箱地址',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { fetchPackageList, submitOrder } from '@/service/api/auth';
|
||||
import { message } from 'ant-design-vue';
|
||||
import OrderConfirmModal from '@/components/order-confirm/orderConfirmModal.vue';
|
||||
@@ -49,15 +49,15 @@ const PERIOD_TYPE = {
|
||||
|
||||
// 添加有效期单位映射
|
||||
const PERIOD_UNIT = {
|
||||
0: '小时',
|
||||
1: '天',
|
||||
2: '月',
|
||||
3: '年'
|
||||
0: t('page.setmeal.hour'),
|
||||
1: t('page.setmeal.day'),
|
||||
2: t('page.setmeal.month'),
|
||||
3: t('page.setmeal.year')
|
||||
} as const;
|
||||
|
||||
// 格式化有效期显示
|
||||
const formatValidityPeriod = (num: number, type: number): string => {
|
||||
const unit = PERIOD_UNIT[type as keyof typeof PERIOD_UNIT] || '未知';
|
||||
const unit = PERIOD_UNIT[type as keyof typeof PERIOD_UNIT] || t('page.setmeal.unknow');
|
||||
return `${num}${unit}`;
|
||||
};
|
||||
|
||||
@@ -95,10 +95,10 @@ const formatTraffic = (bytes: number): string => {
|
||||
|
||||
// 添加速率格式化函数
|
||||
const formatSpeed = (speed: number): string => {
|
||||
if (speed >= 1000000) {
|
||||
return `${(speed / 1000000).toFixed(1)}Gbps`;
|
||||
} else if (speed >= 1000) {
|
||||
return `${(speed / 1000).toFixed(1)}Mbps`;
|
||||
if (speed >= 1048576) {
|
||||
return `${(speed / 1048576).toFixed(1)}Gbps`;
|
||||
} else if (speed >= 1024) {
|
||||
return `${(speed / 1024).toFixed(1)}Mbps`;
|
||||
}
|
||||
return `${speed}Kbps`;
|
||||
};
|
||||
@@ -142,7 +142,12 @@ const currentOrderInfo = ref({
|
||||
// 添加 appStore 实例
|
||||
const appStore = useAppStore();
|
||||
|
||||
// 添加加载状态和数据状态的响应式引用
|
||||
const isLoading = ref(false);
|
||||
const hasPackages = computed(() => packageOptions.value.length > 0);
|
||||
|
||||
const fetchPackages = async () => {
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const response = await fetchPackageList();
|
||||
if (response.data && Array.isArray(response.data)) {
|
||||
@@ -154,7 +159,7 @@ const fetchPackages = async () => {
|
||||
clientNumEnable: pkg.clientNumEnable,
|
||||
traffic: Number(pkg.traffic),
|
||||
trafficEnable: pkg.trafficEnable,
|
||||
trafficDisplay: pkg.trafficEnable ? formatTraffic(Number(pkg.traffic)) : '无限制',
|
||||
trafficDisplay: pkg.trafficEnable ? formatTraffic(Number(pkg.traffic)) : t('page.setmeal.unlimit'),
|
||||
durationEnable: Boolean(pkg.periodNum && pkg.periodType !== undefined),
|
||||
isRecommended: pkg.isRecommended || false,
|
||||
promotion: pkg.promotion || '',
|
||||
@@ -162,7 +167,7 @@ const fetchPackages = async () => {
|
||||
periodType: Number(pkg.periodType),
|
||||
validityPeriod: pkg.periodNum && pkg.periodType !== undefined
|
||||
? formatValidityPeriod(Number(pkg.periodNum), Number(pkg.periodType))
|
||||
: '无限制',
|
||||
: t('page.setmeal.unlimit'),
|
||||
rateLimitEnable: pkg.rateLimitEnable,
|
||||
rateLimits: {
|
||||
upLimitEnable: pkg.rateLimits?.upLimitEnable || false,
|
||||
@@ -178,6 +183,9 @@ const fetchPackages = async () => {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch packages:', error);
|
||||
message.error(t('page.setmeal.fetchFailed'));
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -251,7 +259,6 @@ onMounted(async () => {
|
||||
<div class="price">
|
||||
<span class="currency">¥</span>
|
||||
<span class="amount">{{ selectedPackage.price }}</span>
|
||||
<span class="period">/月</span>
|
||||
</div>
|
||||
<div class="subtitle">{{ selectedPackage.packageName }}</div>
|
||||
</div>
|
||||
@@ -277,9 +284,9 @@ onMounted(async () => {
|
||||
</div>
|
||||
<div class="package-name">{{ option.packageName }}</div>
|
||||
<div class="price">¥{{ option.price }}</div>
|
||||
<div class="traffic">{{ option.trafficEnable ? option.trafficDisplay : '无限制' }}</div>
|
||||
<div class="traffic">{{ option.trafficEnable ? option.trafficDisplay : t('page.setmeal.unlimit') }}</div>
|
||||
<div class="device-count">
|
||||
{{ option.clientNumEnable ? `${option.clientNum}台设备` : '无限制' }}
|
||||
{{ option.clientNumEnable ? `${option.clientNum} ${t('page.setmeal.device')}` : t('page.setmeal.unlimit') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -290,39 +297,39 @@ onMounted(async () => {
|
||||
<h3 class="section-title">{{ t('page.setmeal.mealdetail') }}</h3>
|
||||
<div class="details-list">
|
||||
<div class="detail-item">
|
||||
<div class="label">套餐名称</div>
|
||||
<div class="label">{{ t('page.setmeal.packagename') }}</div>
|
||||
<div class="value">{{ selectedPackage.packageName }}</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="label">{{ t('page.setmeal.GeneralPurposeTraffic') }}</div>
|
||||
<div class="value">
|
||||
{{ selectedPackage.trafficEnable ? selectedPackage.trafficDisplay : '无限制' }}
|
||||
{{ selectedPackage.trafficEnable ? selectedPackage.trafficDisplay : t('page.setmeal.unlimit') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="label">设备数量</div>
|
||||
<div class="label">{{ t('page.setmeal.client') }}</div>
|
||||
<div class="value">
|
||||
{{ selectedPackage.clientNumEnable ? `最多${selectedPackage.clientNum}台设备同时在线` : '无限制' }}
|
||||
{{ selectedPackage.clientNumEnable ? `${t('page.setmeal.upto')} ${selectedPackage.clientNum} ${t('page.setmeal.canbe')}` : t('page.setmeal.unlimit') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="label">有效期限</div>
|
||||
<div class="label">{{ t('page.setmeal.Expirationdate') }}</div>
|
||||
<div class="value">
|
||||
{{ selectedPackage.durationEnable ? selectedPackage.validityPeriod+'内有效' : '无限制' }}
|
||||
{{ selectedPackage.durationEnable ? selectedPackage.validityPeriod+t('page.setmeal.useful') : t('page.setmeal.unlimit') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div class="label">速率限制</div>
|
||||
<div class="label">{{ t('page.setmeal.rate') }}</div>
|
||||
<div class="value">
|
||||
<template v-if="!selectedPackage.rateLimitEnable">
|
||||
不限速
|
||||
{{ t('page.setmeal.unlimit') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<div>
|
||||
上行:{{ selectedPackage.rateLimits.upLimitEnable ? formatSpeed(selectedPackage.rateLimits.upLimit) : '-' }}
|
||||
{{ t('page.setmeal.uplimit') }}:{{ selectedPackage.rateLimits.upLimitEnable ? formatSpeed(selectedPackage.rateLimits.upLimit) : '-' }}
|
||||
</div>
|
||||
<div>
|
||||
下行:{{ selectedPackage.rateLimits.downLimitEnable ? formatSpeed(selectedPackage.rateLimits.downLimit) : '-' }}
|
||||
{{ t('page.setmeal.downlimit') }}:{{ selectedPackage.rateLimits.downLimitEnable ? formatSpeed(selectedPackage.rateLimits.downLimit) : '-' }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -331,9 +338,12 @@ onMounted(async () => {
|
||||
<button
|
||||
class="btn-primary"
|
||||
@click="handleSubmitOrder"
|
||||
:disabled="!selectedPackage.id"
|
||||
:disabled="isLoading || !hasPackages"
|
||||
>
|
||||
{{ t('page.setmeal.Applynow') }}
|
||||
{{ isLoading ? t('page.common.loading') :
|
||||
!hasPackages ? t('page.setmeal.noPackages') :
|
||||
t('page.setmeal.Applynow')
|
||||
}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -491,6 +501,13 @@ onMounted(async () => {
|
||||
font-size: 16px;
|
||||
width: 90%;
|
||||
max-width: 400px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.package-name {
|
||||
|
||||
Reference in New Issue
Block a user