shish 11 months ago
parent
commit
60bf31a3af
4 changed files with 1000 additions and 0 deletions
  1. 0 0
      mallh5/pages/pay/demo.vue
  2. 0 0
      mallh5/pages/pay/index.vue
  3. 1000 0
      mallh5/pages/pay/pay.vue
  4. 0 0
      mallh5/pages/pay/success.vue

+ 0 - 0
mallh5/admin/ghs/index.vue → mallh5/pages/pay/demo.vue


+ 0 - 0
mallh5/admin/ghs/pay.vue → mallh5/pages/pay/index.vue


+ 1000 - 0
mallh5/pages/pay/pay.vue

@@ -0,0 +1,1000 @@
+<template>
+	<view class="pay-container">
+		<!-- 支付金额区域 -->
+		<view class="amount-section">
+			<view class="amount-label">支付金额</view>
+			<view class="amount-display">
+				<text class="currency">¥</text>
+				<text class="amount">{{ displayAmount }}</text>
+			</view>
+			<view class="amount-tip">请输入金额</view>
+		</view>
+
+		<!-- 客户信息卡片 -->
+		<view class="customer-info-card">
+			<view class="card-header">
+				<view class="customer-avatar">
+					<text class="avatar-text">{{ customInfo.name ? customInfo.name.charAt(0) : '客' }}</text>
+				</view>
+				<view class="customer-details">
+					<text class="customer-name">{{ customInfo.name || '客户' }}</text>
+					<text class="customer-status" :class="{ 'has-debt': Number(customInfo.remainDebtAmount) > 0 }">
+						{{ Number(customInfo.remainDebtAmount) > 0 ? '待结款' : '账单已结清' }}
+					</text>
+				</view>
+			</view>
+			<view class="debt-info" v-if="Number(customInfo.remainDebtAmount) > 0">
+				<view class="debt-amount">
+					<text class="debt-label">待结金额</text>
+					<text class="debt-value">¥{{ customInfo.remainDebtAmount }}</text>
+				</view>
+			</view>
+		</view>
+
+		<!-- 数字键盘 - 使用直接事件绑定,确保兼容性 -->
+		<view class="keyboard-section">
+			<view class="keyboard">
+				<view class="keyboard-row" v-for="(row, rowIndex) in keyboardKeys" :key="rowIndex">
+					<view 
+						class="key-item" 
+						v-for="(key, keyIndex) in row" 
+						:key="`${rowIndex}-${keyIndex}`"
+						:class="{ 
+							'key-number': key.type === 'number',
+							'key-delete': key.type === 'delete',
+							'key-dot': key.type === 'dot',
+							'key-confirm': key.type === 'confirm'
+						}"
+						@click="handleKeyPress(key)"
+						@touchstart="handleTouchStart"
+						@touchend="handleTouchEnd"
+					>
+						<text v-if="key.type === 'delete'" class="iconfont icon-delete"></text>
+						<text v-else-if="key.type === 'confirm'">确认</text>
+						<text v-else>{{ key.value }}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 支付按钮 -->
+		<view class="pay-button-section">
+			<button 
+				class="pay-button" 
+				:class="{ disabled: !canPay }"
+				:disabled="!canPay"
+				@click="showConfirmDialog"
+			>
+				<text class="button-text">支付宝支付</text>
+			</button>
+		</view>
+
+		<!-- 确认支付弹框 -->
+		<view class="confirm-dialog" v-if="showConfirm" @click="hideConfirmDialog">
+			<view class="dialog-content" @click.stop>
+				<view class="dialog-header">
+					<text class="dialog-title">提示</text>
+					<view class="close-btn" @click="hideConfirmDialog">
+						<text class="iconfont icon-close">×</text>
+					</view>
+				</view>
+				
+				<view class="dialog-body">
+					<view class="confirm-amount-section">
+						<text class="confirm-label">支付金额</text>
+						<view class="confirm-amount-display">
+							<text class="confirm-currency">¥</text>
+							<text class="confirm-amount">{{ displayAmount }}</text>
+						</view>
+					</view>
+					
+					<view class="confirm-tips">
+						<text class="tip-text">确认金额无误</text>
+					</view>
+				</view>
+				
+				<view class="dialog-footer">
+					<button class="cancel-btn" @click="hideConfirmDialog">取消</button>
+					<button class="confirm-btn" @click="handlePay">确认</button>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+import { getGhsData } from '@/api/ghs';
+import { rechargeFn } from '@/api/custom-recharge'
+
+// 优化:使用常量避免重复创建
+const KEY_TYPES = {
+	NUMBER: 'number',
+	DELETE: 'delete',
+	DOT: 'dot',
+	CONFIRM: 'confirm'
+};
+
+const MAX_INTEGER_LENGTH = 8;
+const MAX_DECIMAL_LENGTH = 2;
+
+export default {
+	name: 'pay',
+	data() {
+		return {
+			currentAmount: '0',
+			displayAmount: '0',
+			// 优化:使用静态数据,避免重复创建
+			keyboardKeys: [
+				[
+					{ type: KEY_TYPES.NUMBER, value: '1' },
+					{ type: KEY_TYPES.NUMBER, value: '2' },
+					{ type: KEY_TYPES.NUMBER, value: '3' }
+				],
+				[
+					{ type: KEY_TYPES.NUMBER, value: '4' },
+					{ type: KEY_TYPES.NUMBER, value: '5' },
+					{ type: KEY_TYPES.NUMBER, value: '6' }
+				],
+				[
+					{ type: KEY_TYPES.NUMBER, value: '7' },
+					{ type: KEY_TYPES.NUMBER, value: '8' },
+					{ type: KEY_TYPES.NUMBER, value: '9' }
+				],
+				[
+					{ type: KEY_TYPES.DOT, value: '.' },
+					{ type: KEY_TYPES.NUMBER, value: '0' },
+					{ type: KEY_TYPES.DELETE, value: '' }
+				]
+			],
+			// 优化:使用更高效的状态管理
+			amountBuffer: '0',
+			updateScheduled: false,
+			updateTimer: null,
+			// 弹框状态
+			showConfirm: false,
+			id:0,
+			salt:'',
+			ghsInfo:[],
+			customInfo:{},
+			payWay:1
+		}
+	},
+	computed: {
+		// 简化支付按钮判断逻辑:只要大于0就能支付
+		canPay() {
+			const amount = parseFloat(this.currentAmount);
+			return amount > 0;
+		}
+	},
+	onLoad(options) {
+		if (options.id) {
+			this.id = options.id;
+		}
+		if (options.salt) {
+			this.salt = options.salt;
+		}
+		let that = this
+		if (this.id && this.salt) {
+			getGhsData({id:this.id,salt:this.salt}).then(res => {
+				if (res.data && res.data.ghs){
+					that.ghsInfo = res.data.ghs
+					that.customInfo = res.data.custom?res.data.custom:[]
+
+					if(that.customInfo.remainDebtAmount && Number(that.customInfo.remainDebtAmount)>0){
+						that.currentAmount = parseFloat(that.customInfo.remainDebtAmount).toString()
+						that.updateDisplay()
+					}
+				}
+			})
+		}
+		
+
+	},
+	methods: {
+		// 优化:添加触摸反馈
+		handleTouchStart(e) {
+			const target = e.currentTarget;
+			if (target && target.style) {
+				target.style.transform = 'scale(0.95)';
+			}
+		},
+		
+		handleTouchEnd(e) {
+			const target = e.currentTarget;
+			if (target && target.style) {
+				setTimeout(() => {
+					target.style.transform = 'scale(1)';
+				}, 100);
+			}
+		},
+
+		// 优化:简化的键盘处理逻辑
+		handleKeyPress(key) {
+			// 防抖处理
+			if (this.updateTimer) {
+				clearTimeout(this.updateTimer);
+			}
+			
+			if (key.type === KEY_TYPES.NUMBER) {
+				this.addNumber(key.value);
+			} else if (key.type === KEY_TYPES.DELETE) {
+				this.deleteNumber();
+			} else if (key.type === KEY_TYPES.DOT) {
+				this.addDecimal();
+			}
+			
+			// 使用 requestAnimationFrame 优化更新
+			this.scheduleUpdate();
+		},
+
+		// 优化:使用 requestAnimationFrame 调度更新
+		scheduleUpdate() {
+			if (!this.updateScheduled) {
+				this.updateScheduled = true;
+				requestAnimationFrame(() => {
+					this.updateDisplay();
+					this.updateScheduled = false;
+				});
+			}
+		},
+
+		// 优化:更高效的数字添加逻辑
+		addNumber(num) {
+			const buffer = this.amountBuffer;
+			
+			// 快速路径:如果当前是0且输入的不是小数点,直接替换
+			if (buffer === '0' && num !== '.') {
+				this.amountBuffer = num;
+				this.currentAmount = num;
+				return;
+			}
+
+			// 检查长度限制
+			const parts = buffer.split('.');
+			const integerPart = parts[0];
+			const decimalPart = parts[1];
+
+			// 整数部分限制
+			if (!decimalPart && integerPart.length >= MAX_INTEGER_LENGTH) {
+				uni.showToast({
+					title: '金额不能超过8位数',
+					icon: 'none',
+					duration: 1500
+				})
+				return;
+			}
+
+			// 小数部分限制
+			if (decimalPart && decimalPart.length >= MAX_DECIMAL_LENGTH) {
+				uni.showToast({
+					title: '最多支持2位小数',
+					icon: 'none',
+					duration: 1500
+				})
+				return;
+			}
+
+			// 添加数字
+			this.amountBuffer = buffer + num;
+			this.currentAmount = this.amountBuffer;
+		},
+
+		// 优化:更高效的小数点添加逻辑
+		addDecimal() {
+			if (!this.amountBuffer.includes('.')) {
+				this.amountBuffer += '.';
+				this.currentAmount = this.amountBuffer;
+			}
+		},
+
+		// 优化:更高效的删除逻辑
+		deleteNumber() {
+			const buffer = this.amountBuffer;
+			if (buffer.length > 1) {
+				this.amountBuffer = buffer.slice(0, -1);
+			} else {
+				this.amountBuffer = '0';
+			}
+			this.currentAmount = this.amountBuffer;
+		},
+
+		// 优化:更高效的显示更新逻辑
+		updateDisplay() {
+			let amount = this.currentAmount;
+			
+			// 确保 amount 是字符串类型
+			if (typeof amount !== 'string') {
+				amount = amount.toString();
+			}
+			
+			// 快速路径:如果是0,直接显示
+			if (amount === '0') {
+				this.displayAmount = '0';
+				return;
+			}
+
+			// 检查是否包含小数点
+			if (amount.includes('.')) {
+				const numAmount = parseFloat(amount) || 0;
+				this.displayAmount = numAmount.toFixed(2);
+			} else {
+				// 整数显示
+				this.displayAmount = amount;
+			}
+		},
+
+		// 优化:更高效的金额设置
+		setAmount(amount) {
+			const numAmount = parseFloat(amount);
+			if (!isNaN(numAmount) && numAmount > 0) {
+				const amountStr = numAmount.toString();
+				this.amountBuffer = amountStr;
+				this.currentAmount = amountStr;
+				this.updateDisplay();
+			}
+		},
+
+		// 显示确认弹框
+		showConfirmDialog() {
+			if (!this.canPay) return;
+			this.showConfirm = true;
+		},
+
+		// 隐藏确认弹框
+		hideConfirmDialog() {
+			this.showConfirm = false;
+		},
+		// 处理支付
+		handlePay() {
+			if (!this.canPay) return;
+			const amount = parseFloat(this.currentAmount);
+			// 隐藏弹框
+			this.hideConfirmDialog();
+			// 简化验证:只要大于0就能支付
+			if (amount <= 0) {
+				uni.showToast({
+					title: '请输入金额!',
+					icon: 'none',
+					duration: 2000
+				})
+				return false
+			}
+			let params = {}
+			params = {
+				actPrice: amount,
+				payWay: this.payWay,
+			}
+			params.ghsId = this.id
+			params.salt = this.salt
+			rechargeFn(params).then(res => {
+				//错误返回判断
+				if(res.code == 0){
+					uni.hideLoading()
+					uni.showToast({
+						title: res.msg,
+						icon: 'none',
+						duration: 2000
+					})
+					return false
+				}			
+				// 隐藏加载提示
+				uni.hideLoading()
+				// 显示成功提示
+				uni.showToast({
+					title: '正在跳转支付...',
+					icon: 'success',
+					duration: 1500
+				})
+				// 延迟跳转到支付页面
+				setTimeout(() => {
+					window.location.href = res.data.url;
+				}, 300)					
+			}).catch(err => {
+				// 隐藏加载提示
+				uni.hideLoading()
+				// 显示错误提示
+				uni.showToast({
+					title: '请求失败,请重试',
+					icon: 'none',
+					duration: 2000
+				})
+			})
+
+		},
+
+		// 返回上一页
+		goBack() {
+			uni.navigateBack({
+				delta: 1
+			});
+		},
+
+
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.pay-container {
+	min-height: 100vh;
+	background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+	position: relative;
+}
+
+.nav-bar {
+	display: flex;
+	align-items: center;
+	justify-content: center; /* Changed to center the title */
+	padding: 20upx 30upx;
+	background: rgba(255, 255, 255, 0.1);
+	backdrop-filter: blur(10px);
+	
+	.nav-back {
+		width: 80upx;
+		height: 80upx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		border-radius: 50%;
+		background: rgba(255, 255, 255, 0.2);
+		cursor: pointer;
+		transition: all 0.2s ease;
+		
+		&:active {
+			background: rgba(255, 255, 255, 0.3);
+			transform: scale(0.9);
+		}
+		
+		.iconfont {
+			font-size: 40upx;
+			color: #fff;
+			font-weight: bold;
+		}
+	}
+	
+	.nav-title {
+		color: #fff;
+		font-size: 36upx;
+		font-weight: 600;
+	}
+	
+	.nav-placeholder {
+		width: 80upx; /* Placeholder for back button */
+	}
+}
+
+.amount-section {
+	padding: 60upx 40upx;
+	text-align: center;
+	
+	.amount-label {
+		color: rgba(255, 255, 255, 0.8);
+		font-size: 28upx;
+		margin-bottom: 20upx;
+	}
+	
+	.amount-display {
+		display: flex;
+		align-items: baseline;
+		justify-content: center;
+		margin-bottom: 20upx;
+		
+		.currency {
+			color: #fff;
+			font-size: 48upx;
+			font-weight: 600;
+			margin-right: 10upx;
+		}
+		
+		.amount {
+			color: #fff;
+			font-size: 80upx;
+			font-weight: 700;
+			font-family: 'Arial', sans-serif;
+		}
+	}
+	
+	.amount-tip {
+		color: rgba(255, 255, 255, 0.6);
+		font-size: 24upx;
+	}
+}
+
+.customer-info-card {
+	background: #fff; /* Changed to white */
+	margin: 0 30upx 20upx;
+	border-radius: 20upx;
+	padding: 30upx;
+	box-shadow: 0 8upx 30upx rgba(0, 0, 0, 0.08);
+	position: relative;
+	overflow: hidden;
+	
+	&::before {
+		content: '';
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		height: 8upx;
+		background: #fff; /* Changed to white */
+		box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.1);
+	}
+	
+	.card-header {
+		display: flex;
+		align-items: center;
+		margin-bottom: 20upx;
+		margin-top: 8upx;
+		
+		.customer-avatar {
+			width: 90upx;
+			height: 90upx;
+			border-radius: 50%;
+			background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			margin-right: 25upx;
+			box-shadow: 0 6upx 20upx rgba(22, 119, 255, 0.3);
+			position: relative;
+			
+			&::after {
+				content: '';
+				position: absolute;
+				top: -2upx;
+				left: -2upx;
+				right: -2upx;
+				bottom: -2upx;
+				border-radius: 50%;
+				background: linear-gradient(135deg, #1677ff 0%, #4096ff 100%);
+				z-index: -1;
+				opacity: 0.3;
+			}
+			
+			.avatar-text {
+				color: #fff;
+				font-size: 44upx;
+				font-weight: 600;
+			}
+		}
+		
+		.customer-details {
+			flex: 1;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			
+			.customer-name {
+				display: block;
+				font-size: 34upx;
+				font-weight: 600;
+				color: #333;
+			}
+			
+			.customer-status {
+				display: inline-block;
+				font-size: 24upx;
+				color: #999;
+				padding: 4upx 12upx;
+				border-radius: 20upx;
+				background: #f8f9fa;
+				border: 1upx solid #e9ecef;
+				
+				&.has-debt {
+					color: #fff;
+					background: linear-gradient(135deg, #ff6b6b 0%, #ff5252 100%);
+					border-color: #ff6b6b;
+					box-shadow: 0 2upx 10upx rgba(255, 107, 107, 0.3);
+				}
+			}
+		}
+	}
+	
+	.debt-info {
+		background: linear-gradient(135deg, #fff5f5 0%, #fef2f2 100%);
+		border-radius: 15upx;
+		padding: 20upx 25upx;
+		margin-top: 20upx;
+		border: 1upx solid rgba(255, 107, 107, 0.2);
+		position: relative;
+		
+		&::before {
+			content: '';
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			background: linear-gradient(135deg, rgba(255, 107, 107, 0.05) 0%, rgba(255, 107, 107, 0.02) 100%);
+			border-radius: 15upx;
+		}
+		
+		.debt-amount {
+			display: flex;
+			align-items: baseline;
+			justify-content: space-between;
+			margin-bottom: 10upx;
+			position: relative;
+			z-index: 1;
+			
+			.debt-label {
+				font-size: 28upx;
+				color: #666;
+				font-weight: 500;
+			}
+			
+			.debt-value {
+				font-size: 40upx;
+				font-weight: 700;
+				color: #ff6b6b;
+				font-family: 'Arial', sans-serif;
+				text-shadow: 0 2upx 10upx rgba(255, 107, 107, 0.2);
+			}
+		}
+		
+		.debt-tip {
+			font-size: 22upx;
+			color: #999;
+			text-align: right;
+			position: relative;
+			z-index: 1;
+			font-style: italic;
+		}
+	}
+}
+
+.keyboard-section {
+	position: fixed;
+	bottom: 160upx;
+	left: 0;
+	right: 0;
+	background: rgba(255, 255, 255, 0.98);
+	backdrop-filter: blur(20px);
+	padding: 30upx;
+	border-top: 1upx solid rgba(0, 0, 0, 0.05);
+	
+	.keyboard {
+		.keyboard-row {
+			display: flex;
+			margin-bottom: 20upx;
+			
+			&:last-child {
+				margin-bottom: 0;
+			}
+			
+			.key-item {
+				flex: 1;
+				height: 120upx;
+				margin: 0 10upx;
+				border-radius: 20upx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				font-size: 40upx;
+				font-weight: 600;
+				transition: all 0.15s ease;
+				user-select: none;
+				-webkit-user-select: none;
+				cursor: pointer;
+				will-change: transform;
+				position: relative;
+				overflow: hidden;
+				
+				&::before {
+					content: '';
+					position: absolute;
+					top: 0;
+					left: 0;
+					right: 0;
+					bottom: 0;
+					background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
+					opacity: 0;
+					transition: opacity 0.15s ease;
+				}
+				
+				&:active::before {
+					opacity: 1;
+				}
+				
+				&.key-number {
+					background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
+					color: #333;
+					box-shadow: 0 4upx 20upx rgba(0, 0, 0, 0.08);
+					border: 1upx solid rgba(0, 0, 0, 0.05);
+				}
+				
+				&.key-delete {
+					background: linear-gradient(135deg, #ff6b6b 0%, #ff5252 100%);
+					color: #fff;
+					box-shadow: 0 4upx 20upx rgba(255, 107, 107, 0.3);
+				}
+				
+				&.key-dot {
+					background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
+					color: #333;
+					box-shadow: 0 4upx 20upx rgba(0, 0, 0, 0.08);
+					border: 1upx solid rgba(0, 0, 0, 0.05);
+				}
+				
+				&.key-confirm {
+					background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+					color: #fff;
+					box-shadow: 0 4upx 20upx rgba(102, 126, 234, 0.3);
+				}
+			}
+		}
+	}
+}
+
+.pay-button-section {
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	padding: 30upx;
+	background: rgba(255, 255, 255, 0.98);
+	backdrop-filter: blur(20px);
+	border-top: 1upx solid rgba(0, 0, 0, 0.05);
+	
+	.pay-button {
+		width: 100%;
+		height: 100upx;
+		background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+		color: #fff;
+		font-size: 36upx;
+		font-weight: 600;
+		border-radius: 50upx;
+		border: none;
+		transition: all 0.3s ease;
+		position: relative;
+		overflow: hidden;
+		
+		&::before {
+			content: '';
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
+			opacity: 0;
+			transition: opacity 0.3s ease;
+		}
+		
+		&:active::before {
+			opacity: 1;
+		}
+		
+		&.disabled {
+			background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%);
+			color: #adb5bd;
+			box-shadow: none;
+		}
+		
+		&:not(.disabled):active {
+			transform: scale(0.98);
+		}
+		
+		.button-text {
+			position: absolute;
+			left: 50%;
+			transform: translateX(-50%);
+			font-size: 36upx;
+			font-weight: 600;
+			color: #fff;
+		}
+		
+		.button-amount {
+			position: absolute;
+			right: 30upx;
+			font-size: 36upx;
+			font-weight: 700;
+			color: #fff;
+			font-family: 'Arial', sans-serif;
+		}
+	}
+}
+
+// 确认支付弹框样式
+.confirm-dialog {
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	background: rgba(0, 0, 0, 0.6);
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	z-index: 9999;
+	animation: fadeIn 0.3s ease;
+	
+	.dialog-content {
+		width: 85%;
+		max-width: 700upx;
+		background: #fff;
+		border-radius: 25upx;
+		overflow: hidden;
+		animation: slideUp 0.3s ease;
+		box-shadow: 0 20upx 60upx rgba(0, 0, 0, 0.2);
+		
+		.dialog-header {
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			padding: 40upx 40upx 30upx;
+			border-bottom: 1upx solid #f0f0f0;
+			background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
+			
+			.dialog-title {
+				font-size: 36upx;
+				font-weight: 600;
+				color: #333;
+			}
+			
+			.close-btn {
+				width: 60upx;
+				height: 60upx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				border-radius: 50%;
+				background: rgba(0, 0, 0, 0.1);
+				cursor: pointer;
+				transition: all 0.2s ease;
+				
+				&:active {
+					background: rgba(0, 0, 0, 0.2);
+					transform: scale(0.95);
+				}
+				
+				.iconfont {
+					font-size: 32upx;
+					color: #666;
+					font-weight: bold;
+				}
+			}
+		}
+		
+		.dialog-body {
+			padding: 50upx 40upx;
+			
+			.confirm-amount-section {
+				text-align: center;
+				margin-bottom: 40upx;
+				
+				.confirm-label {
+					display: block;
+					font-size: 28upx;
+					color: #666;
+					margin-bottom: 25upx;
+					font-weight: 500;
+				}
+				
+				.confirm-amount-display {
+					display: flex;
+					align-items: baseline;
+					justify-content: center;
+					
+					.confirm-currency {
+						font-size: 60upx;
+						font-weight: 600;
+						color: #ff6b6b;
+						margin-right: 10upx;
+					}
+					
+					.confirm-amount {
+						font-size: 100upx;
+						font-weight: 700;
+						color: #ff6b6b;
+						font-family: 'Arial', sans-serif;
+						text-shadow: 0 2upx 10upx rgba(255, 107, 107, 0.3);
+					}
+				}
+			}
+			
+			.confirm-tips {
+				text-align: center;
+				padding: 20upx 30upx;
+				background: rgba(255, 107, 107, 0.1);
+				border-radius: 15upx;
+				border-left: 4upx solid #ff6b6b;
+				
+				.tip-text {
+					font-size: 26upx;
+					color: #666;
+					line-height: 1.5;
+				}
+			}
+		}
+		
+		.dialog-footer {
+			display: flex;
+			border-top: 1upx solid #f0f0f0;
+			padding: 30upx 40upx;
+			gap: 20upx;
+			
+			.cancel-btn, .confirm-btn {
+				flex: 1;
+				height: 100upx;
+				border: none;
+				font-size: 32upx;
+				font-weight: 600;
+				transition: all 0.2s ease;
+				border-radius: 50upx;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				position: relative;
+				overflow: hidden;
+				
+				&::before {
+					content: '';
+					position: absolute;
+					top: 0;
+					left: 0;
+					right: 0;
+					bottom: 0;
+					background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
+					opacity: 0;
+					transition: opacity 0.2s ease;
+				}
+				
+				&:active::before {
+					opacity: 1;
+				}
+				
+				&:active {
+					transform: scale(0.98);
+				}
+			}
+			
+			.cancel-btn {
+				background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
+				color: #666;
+				border: 2upx solid #dee2e6;
+				box-shadow: 0 2upx 8upx rgba(0, 0, 0, 0.1);
+				
+				&:active {
+					background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%);
+					border-color: #ced4da;
+					box-shadow: 0 1upx 4upx rgba(0, 0, 0, 0.15);
+				}
+			}
+			
+			.confirm-btn {
+				background: linear-gradient(135deg, #ff6b6b 0%, #ff5252 100%);
+				color: #fff;
+				box-shadow: 0 4upx 20upx rgba(255, 107, 107, 0.3);
+				
+				&:active {
+					background: linear-gradient(135deg, #ff5252 0%, #ff4444 100%);
+					box-shadow: 0 2upx 10upx rgba(255, 107, 107, 0.4);
+				}
+			}
+		}
+	}
+}
+
+// 弹框动画
+@keyframes fadeIn {
+	from {
+		opacity: 0;
+	}
+	to {
+		opacity: 1;
+	}
+}
+
+@keyframes slideUp {
+	from {
+		opacity: 0;
+		transform: translateY(50upx) scale(0.9);
+	}
+	to {
+		opacity: 1;
+		transform: translateY(0) scale(1);
+	}
+}
+
+</style>

+ 0 - 0
mallh5/admin/ghs/success.vue → mallh5/pages/pay/success.vue