feat:账单记录界面移动端适配
This commit is contained in:
@@ -648,7 +648,8 @@ const local: any = {
|
|||||||
endpoint:{
|
endpoint:{
|
||||||
access:"current client",
|
access:"current client",
|
||||||
records:"Historical client",
|
records:"Historical client",
|
||||||
cdrlrecords:"Internet records"
|
cdrlrecords:"Internet records",
|
||||||
|
bill:'Bill records',
|
||||||
},
|
},
|
||||||
cdrlrecords:{
|
cdrlrecords:{
|
||||||
total:'Total',
|
total:'Total',
|
||||||
|
|||||||
@@ -678,7 +678,8 @@ const local:any = {
|
|||||||
endpoint:{
|
endpoint:{
|
||||||
access:"当前设备",
|
access:"当前设备",
|
||||||
records:"历史设备",
|
records:"历史设备",
|
||||||
cdrlrecords:"上网记录"
|
cdrlrecords:"上网记录",
|
||||||
|
bill:'账单记录',
|
||||||
},
|
},
|
||||||
cdrlrecords:{
|
cdrlrecords:{
|
||||||
total:'共',
|
total:'共',
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import type { Api } from '@/typings/api'
|
|||||||
import { SimpleScrollbar } from '~/packages/materials/src'
|
import { SimpleScrollbar } from '~/packages/materials/src'
|
||||||
import { Card as ACard, Tag as ATag } from 'ant-design-vue'
|
import { Card as ACard, Tag as ATag } from 'ant-design-vue'
|
||||||
import { useElementSize } from '@vueuse/core'
|
import { useElementSize } from '@vueuse/core'
|
||||||
|
import {
|
||||||
|
EyeOutlined,
|
||||||
|
DownloadOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -121,8 +125,8 @@ const { columns, data, loading, getData, mobilePagination, searchParams } = useT
|
|||||||
key: 'invoiceNumber',
|
key: 'invoiceNumber',
|
||||||
dataIndex: 'invoiceNumber',
|
dataIndex: 'invoiceNumber',
|
||||||
title: t('page.bill.invoiceNumber'),
|
title: t('page.bill.invoiceNumber'),
|
||||||
align: 'center',
|
align: 'left',
|
||||||
width: 150
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'invoiceTime',
|
key: 'invoiceTime',
|
||||||
@@ -138,6 +142,7 @@ const { columns, data, loading, getData, mobilePagination, searchParams } = useT
|
|||||||
title: t('page.bill.amount'),
|
title: t('page.bill.amount'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 120,
|
width: 120,
|
||||||
|
responsive: ['md'],
|
||||||
customRender: ({ text }: { text: number }) => {
|
customRender: ({ text }: { text: number }) => {
|
||||||
const formattedAmount = Number(text).toFixed(2)
|
const formattedAmount = Number(text).toFixed(2)
|
||||||
return `${currencySymbol.value}${formattedAmount}`
|
return `${currencySymbol.value}${formattedAmount}`
|
||||||
@@ -149,6 +154,7 @@ const { columns, data, loading, getData, mobilePagination, searchParams } = useT
|
|||||||
title: t('page.bill.billType'),
|
title: t('page.bill.billType'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 120,
|
width: 120,
|
||||||
|
responsive: ['md'],
|
||||||
customRender: ({ text }: { text: Api.Bill.BillRecord['type'] }) => {
|
customRender: ({ text }: { text: Api.Bill.BillRecord['type'] }) => {
|
||||||
const typeMap: Record<Api.Bill.BillRecord['type'],{ color: string; label: string }> = {
|
const typeMap: Record<Api.Bill.BillRecord['type'],{ color: string; label: string }> = {
|
||||||
0: { color: 'blue', label: t('page.bill.types.package') },
|
0: { color: 'blue', label: t('page.bill.types.package') },
|
||||||
@@ -162,8 +168,7 @@ const { columns, data, loading, getData, mobilePagination, searchParams } = useT
|
|||||||
key: 'invoiceFile',
|
key: 'invoiceFile',
|
||||||
title: t('page.bill.actions'),
|
title: t('page.bill.actions'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 150,
|
width: 60,
|
||||||
fixed: 'right'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@@ -229,6 +234,10 @@ const handlePreview = async (record: Api.Bill.BillRecord) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
router.push('/billing/billservice');
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchCurrencySymbol()
|
fetchCurrencySymbol()
|
||||||
getData()
|
getData()
|
||||||
@@ -239,7 +248,22 @@ onMounted(() => {
|
|||||||
<SimpleScrollbar>
|
<SimpleScrollbar>
|
||||||
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
||||||
<ACard
|
<ACard
|
||||||
:title="t('page.bill.title')"
|
:title="
|
||||||
|
isMobile
|
||||||
|
? h('div', { class: 'flex justify-between items-center w-full' }, [
|
||||||
|
h('span', t('page.bill.title')),
|
||||||
|
h(
|
||||||
|
AButton,
|
||||||
|
{
|
||||||
|
onClick: handleBack,
|
||||||
|
size: 'small',
|
||||||
|
style: { marginLeft: '8px' }
|
||||||
|
},
|
||||||
|
{ default: () => t('page.login.common.back') }
|
||||||
|
)
|
||||||
|
])
|
||||||
|
: t('page.bill.title')
|
||||||
|
"
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:body-style="{ flex: 1, overflow: 'hidden' }"
|
:body-style="{ flex: 1, overflow: 'hidden' }"
|
||||||
class="flex-col-stretch sm:flex-1-hidden card-wrapper"
|
class="flex-col-stretch sm:flex-1-hidden card-wrapper"
|
||||||
@@ -251,6 +275,7 @@ onMounted(() => {
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
row-key="id"
|
row-key="id"
|
||||||
size="small"
|
size="small"
|
||||||
|
:expandIconColumnWidth="24"
|
||||||
:pagination="{
|
:pagination="{
|
||||||
...mobilePagination,
|
...mobilePagination,
|
||||||
total: mobilePagination.total,
|
total: mobilePagination.total,
|
||||||
@@ -266,6 +291,42 @@ onMounted(() => {
|
|||||||
getData();
|
getData();
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
<template #expandedRowRender="{ record }">
|
||||||
|
<div v-if="isMobile" class="pl-4">
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>{{ t('page.bill.billDate') }}:</strong>
|
||||||
|
{{ formatDateTime(record.invoiceTime) }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>{{ t('page.bill.amount') }}:</strong>
|
||||||
|
{{ currencySymbol + Number(record.amount).toFixed(2) }}
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<strong>{{ t('page.bill.billType') }}:</strong>
|
||||||
|
<ATag :color="record.type === 0 ? 'blue' : 'gold'">
|
||||||
|
{{ record.type === 0 ? t('page.bill.types.package') : t('page.bill.types.recharge') }}
|
||||||
|
</ATag>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<AButton
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
:disabled="!record.invoiceFile"
|
||||||
|
@click="handlePreview(record)"
|
||||||
|
>
|
||||||
|
<EyeOutlined />
|
||||||
|
</AButton>
|
||||||
|
<AButton
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
:disabled="!record.invoiceFile"
|
||||||
|
@click="handleExport(record)"
|
||||||
|
>
|
||||||
|
<DownloadOutlined />
|
||||||
|
</AButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'status'">
|
<template v-if="column.key === 'status'">
|
||||||
<ATag :color="getStatusColor(record.status)">
|
<ATag :color="getStatusColor(record.status)">
|
||||||
@@ -280,7 +341,7 @@ onMounted(() => {
|
|||||||
:disabled="!record.invoiceFile"
|
:disabled="!record.invoiceFile"
|
||||||
@click="handlePreview(record)"
|
@click="handlePreview(record)"
|
||||||
>
|
>
|
||||||
{{ t('page.bill.preview') }}
|
<EyeOutlined />
|
||||||
</AButton>
|
</AButton>
|
||||||
<AButton
|
<AButton
|
||||||
type="link"
|
type="link"
|
||||||
@@ -288,7 +349,7 @@ onMounted(() => {
|
|||||||
:disabled="!record.invoiceFile"
|
:disabled="!record.invoiceFile"
|
||||||
@click="handleExport(record)"
|
@click="handleExport(record)"
|
||||||
>
|
>
|
||||||
{{ t('page.bill.download') }}
|
<DownloadOutlined />
|
||||||
</AButton>
|
</AButton>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -312,8 +373,8 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 2px;
|
||||||
padding: 4px;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.ant-btn-link) {
|
:deep(.ant-btn-link) {
|
||||||
@@ -334,4 +395,10 @@ onMounted(() => {
|
|||||||
:deep(.ant-modal-confirm-content) {
|
:deep(.ant-modal-confirm-content) {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.ant-table-row-expand-icon-cell) {
|
||||||
|
width: 24px !important;
|
||||||
|
min-width: 24px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
CreditCardOutlined,
|
CreditCardOutlined,
|
||||||
ContainerOutlined,
|
ContainerOutlined,
|
||||||
WalletOutlined,
|
WalletOutlined,
|
||||||
|
AuditOutlined
|
||||||
|
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
|
|
||||||
@@ -45,6 +46,11 @@ const menuItems = [
|
|||||||
icon: FileTextOutlined,
|
icon: FileTextOutlined,
|
||||||
title: t('page.endpoint.cdrlrecords'),
|
title: t('page.endpoint.cdrlrecords'),
|
||||||
path: '/billing/cdrlrecords'
|
path: '/billing/cdrlrecords'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: AuditOutlined,
|
||||||
|
title:t('page.endpoint.bill'),
|
||||||
|
path: '/billing/bill'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
360
src/views/billing/pay/index.vue
Normal file
360
src/views/billing/pay/index.vue
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, computed, watchEffect } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { AlipayOutlined, WechatOutlined, WalletOutlined, ArrowLeftOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { Modal } from 'ant-design-vue';
|
||||||
|
import PaypalButton from '@/components/payment/paypal-button.vue';
|
||||||
|
import { useAuthStore } from '@/store/modules/auth';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const emit = defineEmits(['update:visible', 'confirm', 'cancel']);
|
||||||
|
const loading = ref(false);
|
||||||
|
const orderInfo = ref({
|
||||||
|
orderId: '',
|
||||||
|
orderType: 0,
|
||||||
|
orderAmount: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const userBalance = ref(0);
|
||||||
|
|
||||||
|
// 监听余额变化
|
||||||
|
watchEffect(async () => {
|
||||||
|
try {
|
||||||
|
const response = await authStore.getDashboardData();
|
||||||
|
if (response && typeof response === 'object' && !response.error) {
|
||||||
|
const numBalance = Number(response.balance);
|
||||||
|
userBalance.value = isNaN(numBalance) ? 0 : numBalance;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch user balance:', error);
|
||||||
|
userBalance.value = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Debug: 添加 authStore 状态日志
|
||||||
|
console.log('Debug - Complete Auth Store:', {
|
||||||
|
userInfo: JSON.parse(JSON.stringify(authStore.userInfo)),
|
||||||
|
user: authStore.userInfo?.user ? JSON.parse(JSON.stringify(authStore.userInfo.user)) : null,
|
||||||
|
allKeys: authStore.userInfo ? Object.keys(authStore.userInfo) : [],
|
||||||
|
userKeys: authStore.userInfo?.user ? Object.keys(authStore.userInfo.user) : []
|
||||||
|
});
|
||||||
|
|
||||||
|
// 判断是否显示余额支付按钮
|
||||||
|
const showBalancePayment = computed(() => {
|
||||||
|
// 如果是余额充值,不显示余额支付
|
||||||
|
return orderInfo.value.orderType !== 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 判断余额支付是否禁用
|
||||||
|
const isBalancePayDisabled = computed(() => {
|
||||||
|
const balanceNum = userBalance.value; // 已经确保是数字类型
|
||||||
|
const amountNum = Number(orderInfo.value.orderAmount);
|
||||||
|
|
||||||
|
console.log('Debug - Balance Check:', {
|
||||||
|
balance: balanceNum,
|
||||||
|
amount: amountNum,
|
||||||
|
isBalanceNaN: isNaN(balanceNum),
|
||||||
|
isAmountNaN: isNaN(amountNum),
|
||||||
|
loading: loading.value
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果转换后不是有效数字,禁用按钮
|
||||||
|
if (isNaN(balanceNum) || isNaN(amountNum)) {
|
||||||
|
console.log('Debug - Invalid number conversion');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果余额为0或小于订单金额,禁用按钮
|
||||||
|
const isInsufficient = balanceNum === 0 || balanceNum < amountNum;
|
||||||
|
console.log('Debug - Balance sufficient check:', {
|
||||||
|
balance: balanceNum,
|
||||||
|
amount: amountNum,
|
||||||
|
isInsufficient
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isInsufficient) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果正在加载,禁用按钮
|
||||||
|
return loading.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 从路由参数中获取订单信息
|
||||||
|
onMounted(async () => {
|
||||||
|
const { orderId, orderType, orderAmount } = route.query;
|
||||||
|
|
||||||
|
// 添加参数验证和错误处理
|
||||||
|
if (!orderId) {
|
||||||
|
Modal.error({
|
||||||
|
title: t('page.common.error'),
|
||||||
|
content: t('page.pay.missingOrderId'),
|
||||||
|
onOk: () => router.back()
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
orderInfo.value = {
|
||||||
|
orderId: orderId as string,
|
||||||
|
orderType: orderType ? parseInt(orderType as string) : 0,
|
||||||
|
orderAmount: orderAmount ? parseFloat(orderAmount as string) : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// 验证转换后的值是否有效
|
||||||
|
if (isNaN(orderInfo.value.orderType) || isNaN(orderInfo.value.orderAmount)) {
|
||||||
|
throw new Error('Invalid parameter values');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: 打印订单信息
|
||||||
|
console.log('Debug - Order Info:', orderInfo.value);
|
||||||
|
} catch (error) {
|
||||||
|
Modal.error({
|
||||||
|
title: t('page.common.error'),
|
||||||
|
content: t('page.pay.invalidParameters'),
|
||||||
|
onOk: () => router.back()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const orderTypeMap = {
|
||||||
|
0: t('page.order.packagePurchase'),
|
||||||
|
1: t('page.order.balanceRecharge')
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const handleConfirm = (paymentMethod: 'alipay' | 'wxpay' | 'balance') => {
|
||||||
|
|
||||||
|
if (paymentMethod === 'balance') {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('page.order.confirmPayment'),
|
||||||
|
content: t('page.order.balancePayConfirm'),
|
||||||
|
okText: t('page.order.confirm'),
|
||||||
|
cancelText: t('page.order.cancel'),
|
||||||
|
onOk: () => {
|
||||||
|
// 处理余额支付
|
||||||
|
emit('confirm', paymentMethod);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 处理其他支付方式
|
||||||
|
// emit('confirm', paymentMethod);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
router.back();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="pay-container">
|
||||||
|
<div class="header">
|
||||||
|
<a-button type="link" @click="handleBack" class="back-button">
|
||||||
|
<ArrowLeftOutlined />
|
||||||
|
{{ t('page.pay.back') }}
|
||||||
|
</a-button>
|
||||||
|
<h2>{{ t('page.pay.title') }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="order-info">
|
||||||
|
<h3>{{ t('page.pay.orderDetails') }}</h3>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">{{ t('page.order.orderType') }}:</span>
|
||||||
|
<span class="value">{{ orderTypeMap[orderInfo.orderType] }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">{{ t('page.order.orderAmount') }}:</span>
|
||||||
|
<span class="value highlight">¥{{ orderInfo.orderAmount.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">{{ t('page.order.orderId') }}:</span>
|
||||||
|
<span class="value">{{ orderInfo.orderId }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">{{ t('page.order.balance') }}:</span>
|
||||||
|
<span class="value">¥{{ userBalance.toFixed(2) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="payment-methods">
|
||||||
|
<h3>{{ t('page.order.selectPayment') }}</h3>
|
||||||
|
<div class="methods-container">
|
||||||
|
<!-- 余额支付按钮 -->
|
||||||
|
<div
|
||||||
|
v-if="showBalancePayment"
|
||||||
|
class="method-item"
|
||||||
|
:class="{ disabled: loading || isBalancePayDisabled }"
|
||||||
|
@click="!loading && !isBalancePayDisabled && handleConfirm('balance')"
|
||||||
|
>
|
||||||
|
<WalletOutlined class="payment-icon balance-icon" />
|
||||||
|
<span>{{ t('page.order.balancePay') }}</span>
|
||||||
|
<span v-if="isBalancePayDisabled" class="balance-insufficient">
|
||||||
|
{{ t('page.order.insufficientBalance') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="method-item"
|
||||||
|
:class="{ disabled: loading }"
|
||||||
|
@click="!loading && handleConfirm('alipay')"
|
||||||
|
>
|
||||||
|
<AlipayOutlined class="payment-icon alipay-icon" />
|
||||||
|
<span>{{ t('page.order.alipay') }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="method-item"
|
||||||
|
:class="{ disabled: loading }"
|
||||||
|
@click="!loading && handleConfirm('wxpay')"
|
||||||
|
>
|
||||||
|
<WechatOutlined class="payment-icon wxpay-icon" />
|
||||||
|
<span>{{ t('page.order.wxpay') }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="method-item">
|
||||||
|
<PaypalButton
|
||||||
|
:amount="orderInfo.orderAmount"
|
||||||
|
:loading="loading"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.pay-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-button {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h2 {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-info {
|
||||||
|
padding: 24px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-info h3,
|
||||||
|
.payment-methods h3 {
|
||||||
|
margin: 0 0 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
width: 84px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
flex: 1;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value.highlight {
|
||||||
|
color: #ff4d4f;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-methods {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.methods-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 24px;
|
||||||
|
border: 1px solid #e8e8e8;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item:hover {
|
||||||
|
border-color: #1890ff;
|
||||||
|
background: #f0f5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.payment-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alipay-icon {
|
||||||
|
color: #1677ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wxpay-icon {
|
||||||
|
color: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-icon {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.method-item.disabled:hover {
|
||||||
|
border-color: #e8e8e8;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balance-insufficient {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #ff4d4f;
|
||||||
|
margin-top: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user