编写湖畔缴费页面 - 模拟话费缴费

This commit is contained in:
赵毅 2025-08-18 09:05:20 +08:00
parent 6f84133a0a
commit 41f655373f
5 changed files with 526 additions and 2 deletions

View File

@ -0,0 +1,194 @@
page {
background-color: #f6f7fb;
}
.pay-container {
padding: 30rpx;
min-height: 100vh;
}
.header {
text-align: center;
padding: 30rpx 0;
background-color: #fff;
border-radius: 10rpx;
margin-bottom: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.title {
font-size: 40rpx;
font-weight: bold;
color: #333;
}
.form-container {
background-color: #fff;
border-radius: 10rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.form-item {
margin-bottom: 40rpx;
}
.label {
font-size: 28rpx;
color: #666;
margin-bottom: 15rpx;
display: block;
}
.input {
width: 100%;
height: 80rpx;
border: 2rpx solid #e0e0e0;
border-radius: 8rpx;
padding: 0 20rpx;
box-sizing: border-box;
font-size: 30rpx;
}
.input:focus {
border-color: #ff6c00;
outline: none;
}
.operator-list {
display: flex;
justify-content: space-between;
margin-top: 20rpx;
}
.operator-item {
width: 200rpx;
height: 120rpx;
border: 2rpx solid #e0e0e0;
border-radius: 8rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10rpx;
box-sizing: border-box;
}
.operator-item.active {
border-color: #ff6c00;
background-color: #ff6a0013;
}
.operator-icon {
width: 50rpx;
height: 50rpx;
margin-bottom: 10rpx;
}
.operator-item text {
font-size: 26rpx;
color: #333;
}
/* 自动识别运营商显示样式 */
.selected-operator {
display: flex;
align-items: center;
padding: 20rpx;
border: 2rpx solid #e0e0e0;
border-radius: 8rpx;
background-color: #f9f9f9;
}
.selected-operator .operator-icon {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
margin-bottom: 0;
}
.selected-operator text {
font-size: 30rpx;
color: #333;
}
.change-btn {
margin-left: auto;
color: #ff6c00;
font-size: 28rpx;
padding: 10rpx 20rpx;
border-radius: 6rpx;
}
.amount-input {
margin-bottom: 20rpx;
}
.amount-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.amount-item {
width: 160rpx;
height: 70rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
}
.amount-item:active {
background-color: #e0e0e0;
}
.pay-btn {
width: 100%;
height: 90rpx;
background-color: #ff6c00;
color: #fff;
border-radius: 45rpx;
font-size: 32rpx;
line-height: 90rpx;
text-align: center;
margin-top: 40rpx;
}
.pay-btn:disabled {
background-color: #cccccc;
color: #666666;
}
/* 响应式适配 */
@media screen and (min-width: 768px) {
.pay-container {
max-width: 600rpx;
margin: 0 auto;
padding: 40rpx;
}
.header {
padding: 40rpx 0;
}
.title {
font-size: 48rpx;
}
.form-container {
padding: 40rpx;
}
}
/* 错误提示样式 */
.error-message {
color: #ff4d4f;
font-size: 26rpx;
margin-top: 10rpx;
display: block;
}

View File

@ -0,0 +1,156 @@
<template>
<view class="pay-container">
<!-- <view class="header">
<text class="title">手机缴费</text>
</view> -->
<view class="form-container">
<!-- 手机号码输入 -->
<view class="form-item">
<view class="label">手机号码</view>
<input class="input" type="number" v-model="phoneNumber" placeholder="请输入手机号码" maxlength="11" @input="onPhoneInput" />
</view>
<!-- 运营商选择 -->
<view class="form-item" v-if="showOperatorSelect">
<view class="label">选择运营商</view>
<view class="operator-list">
<view class="operator-item" :class="{ 'active': selectedOperator === 'chinaMobile' }" @click="selectOperator('chinaMobile')">
<image class="operator-icon" src="http://localhost:8080/payTheFees_yidong.png" mode="aspectFit" />
<text>移动</text>
</view>
<view class="operator-item" :class="{ 'active': selectedOperator === 'chinaUnicom' }" @click="selectOperator('chinaUnicom')">
<image class="operator-icon" src="http://localhost:8080/payTheFees_liantong.png" mode="aspectFit" />
<text>中国联通</text>
</view>
<view class="operator-item" :class="{ 'active': selectedOperator === 'chinaTelecom' }" @click="selectOperator('chinaTelecom')">
<image class="operator-icon" src="http://localhost:8080/payTheFees_dianxin.png" mode="aspectFit" />
<text>中国电信</text>
</view>
</view>
</view>
<!-- 自动识别的运营商显示 -->
<view class="form-item" v-else-if="selectedOperator">
<view class="label">运营商</view>
<view class="selected-operator">
<image class="operator-icon" :src="getOperatorIcon()" mode="aspectFit" />
<text>{{ getOperatorName() }}</text>
<text class="change-btn" @click="showOperatorSelect = true">更换</text>
</view>
</view>
<!-- 缴费金额 -->
<view class="form-item">
<view class="label">缴费金额</view>
<input class="input amount-input" type="number" v-model="amount" placeholder="请输入金额" />
<view class="amount-list">
<view class="amount-item" v-for="item in amountOptions" :key="item" @click="selectAmount(item)">{{ item }}</view>
</view>
</view>
<!-- 缴费按钮 -->
<button class="pay-btn" :disabled="!isFormValid" @click="handlePay">立即缴费</button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
phoneNumber: '',
selectedOperator: '',
amount: '',
amountOptions: [10, 20, 30, 50, 100, 200],
showOperatorSelect: false
}
},
computed: {
isFormValid() {
// 110
return this.phoneNumber.length === 11 &&
this.selectedOperator &&
this.amount &&
Number(this.amount) > 0;
}
},
methods: {
onPhoneInput() {
if (this.phoneNumber.length >= 3) {
this.autoDetectOperator();
}
},
autoDetectOperator() {
// 34
const prefix = this.phoneNumber.substring(0, 3);
const prefix4 = this.phoneNumber.substring(0, 4);
//
const chinaMobilePrefixes = ['134', '135', '136', '137', '138', '139', '147', '150', '151', '152', '157', '158', '159', '178', '182', '183', '184', '187', '188', '198'];
//
const chinaUnicomPrefixes = ['130', '131', '132', '145', '155', '156', '166', '175', '176', '185', '186'];
//
const chinaTelecomPrefixes = ['133', '149', '153', '173', '177', '180', '181', '189', '199'];
if (chinaMobilePrefixes.includes(prefix) || chinaMobilePrefixes.includes(prefix4)) {
this.selectedOperator = 'chinaMobile';
this.showOperatorSelect = false;
} else if (chinaUnicomPrefixes.includes(prefix) || chinaUnicomPrefixes.includes(prefix4)) {
this.selectedOperator = 'chinaUnicom';
this.showOperatorSelect = false;
} else if (chinaTelecomPrefixes.includes(prefix) || chinaTelecomPrefixes.includes(prefix4)) {
this.selectedOperator = 'chinaTelecom';
this.showOperatorSelect = false;
} else {
//
this.showOperatorSelect = true;
}
},
selectOperator(operator) {
this.selectedOperator = operator;
this.showOperatorSelect = false;
},
selectAmount(amount) {
this.amount = amount;
},
handlePay() {
if (this.isFormValid) {
uni.showToast({
title: '缴费成功',
icon: 'success'
});
}
},
getOperatorName() {
switch (this.selectedOperator) {
case 'chinaMobile':
return '中国移动';
case 'chinaUnicom':
return '中国联通';
case 'chinaTelecom':
return '中国电信';
default:
return '';
}
},
getOperatorIcon() {
switch (this.selectedOperator) {
case 'chinaMobile':
return 'http://localhost:8080/payTheFees_yidong.png';
case 'chinaUnicom':
return 'http://localhost:8080/payTheFees_liantong.png';
case 'chinaTelecom':
return 'http://localhost:8080/payTheFees_dianxin.png';
default:
return '';
}
}
}
}
</script>
<style>
@import url("./index.css");
</style>

View File

@ -0,0 +1,102 @@
page {
background-color: #f6f7fb;
}
.credits-exchange-container {
padding: 20rpx;
min-height: 100vh;
}
.page-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
text-align: center;
}
.goods-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.goods-item {
width: 48%;
background-color: #fff;
border-radius: 10rpx;
overflow: hidden;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.goods-image {
width: 100%;
height: 300rpx;
overflow: hidden;
}
.goods-image image {
width: 100%;
height: 100%;
object-fit: cover;
}
.goods-info {
padding: 20rpx;
}
.goods-name {
font-size: 26rpx;
color: #333;
margin-bottom: 10rpx;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
height: 64rpx;
}
.goods-points {
font-size: 32rpx;
color: #e64340;
font-weight: bold;
}
.goods-points text {
font-size: 24rpx;
}
/* 适配不同屏幕尺寸 */
@media screen and (min-width: 768px) {
.credits-exchange-container {
padding: 30rpx;
}
.page-title {
font-size: 44rpx;
margin-bottom: 30rpx;
}
.goods-item {
width: 32%;
margin-bottom: 30rpx;
}
.goods-image {
height: 400rpx;
}
.goods-name {
font-size: 32rpx;
height: 72rpx;
}
.goods-points {
font-size: 36rpx;
}
.goods-points text {
font-size: 28rpx;
}
}

View File

@ -0,0 +1,68 @@
<template>
<view class="credits-exchange-container">
<view class="goods-list">
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
<view class="goods-image">
<image :src="item.image" mode="aspectFill"></image>
</view>
<view class="goods-info">
<view class="goods-name">{{ item.name }}</view>
<view class="goods-points">{{ item.points }} <text>积分</text></view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'CreditsExchange',
data() {
return {
goodsList: [
{
id: 1,
name: '兰蔻持妆粉底液 持久遮瑕保湿',
points: 31800,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
},
{
id: 2,
name: '福临门一级小磨香油400ML',
points: 999999,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
},
{
id: 3,
name: '九阳Joyoung不用翻面 空气炸锅',
points: 999999,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
},
{
id: 4,
name: '福临门礼包(福临门自然香五常大米)',
points: 999999,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
},
{
id: 5,
name: '福临门礼包(福临门自然香五常大米)',
points: 999999,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
},
{
id: 6,
name: '福临门礼包(福临门自然香五常大米)',
points: 999999,
image: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png'
}
]
};
}
};
</script>
<style>
@import url("./index.css");
</style>

View File

@ -7,8 +7,8 @@
class="searchBox"
:style="{ height: localHeight + 'px', paddingTop: top + 'px' }"
>
<div class="searchBox_left">
<!-- <u-icon name="arrow-left" size="20px" color="#000"></u-icon> -->
<div class="searchBox_left" @click="back">
<u-icon name="arrow-left" size="20px" color="#000"></u-icon>
</div>
<div class="searchBox_ipt" @click="searchPage">
<image
@ -400,6 +400,10 @@ export default {
};
},
methods: {
back() {
NavgateTo('1')
},
changeCate(id) {
// id
const category = this.CateList.find((item) => item.id === id);