|
|
@@ -1,657 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="coin-exchange-page">
|
|
|
- <!-- 顶部标题 -->
|
|
|
- <div class="page-header">
|
|
|
- <div class="header-content">
|
|
|
- <div class="back-btn" @click="goBack">
|
|
|
- <van-icon name="arrow-left" size="20" />
|
|
|
- </div>
|
|
|
- <div class="header-title">金币兑换</div>
|
|
|
- <div class="record-btn" @click="goToRecord">
|
|
|
- 兑换记录
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 金币余额 -->
|
|
|
- <div class="balance-section">
|
|
|
- <div class="balance-card">
|
|
|
- <div class="balance-label">我的金币余额</div>
|
|
|
- <div class="balance-amount">{{ coinBalance }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 兑换表单 -->
|
|
|
- <div class="exchange-form">
|
|
|
- <div class="form-card">
|
|
|
- <!-- 用户ID输入 -->
|
|
|
- <div class="form-item">
|
|
|
- <div class="form-label">输入要兑换的用户ID</div>
|
|
|
- <van-field
|
|
|
- v-model="userId"
|
|
|
- type="tel"
|
|
|
- placeholder="请输入6位用户ID"
|
|
|
- maxlength="6"
|
|
|
- class="user-id-input"
|
|
|
- @input="onUserIdInput"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 用户信息显示 -->
|
|
|
- <div v-if="userInfo" class="user-info-section">
|
|
|
- <div class="user-info-card">
|
|
|
- <div class="user-avatar">
|
|
|
- <img v-if="userInfo.avatar" :src="userInfo.avatar" class="avatar" />
|
|
|
- <div v-else class="avatar-placeholder">
|
|
|
- <van-icon name="user-o" size="24" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="user-details">
|
|
|
- <div class="user-name">{{ userInfo.nickname || '未知用户' }}</div>
|
|
|
- <div class="user-id-display">ID: {{ userInfo.id }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 兑换数量输入 -->
|
|
|
- <div class="form-item">
|
|
|
- <div class="form-label">输入要兑换的金币数量</div>
|
|
|
- <van-field
|
|
|
- v-model="exchangeAmount"
|
|
|
- type="number"
|
|
|
- placeholder="请输入金币数量"
|
|
|
- class="exchange-input"
|
|
|
- @input="onExchangeAmountInput"
|
|
|
- />
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 兑换结果显示 -->
|
|
|
- <div v-if="exchangeAmount && exchangeAmount > 0" class="exchange-result">
|
|
|
- <div class="result-item">
|
|
|
- <span class="result-label">兑换后获得钻石:</span>
|
|
|
- <span class="result-value">{{ getDiamondAmount }} 钻石</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 确认兑换按钮 -->
|
|
|
- <div class="confirm-btn-container">
|
|
|
- <van-button
|
|
|
- type="primary"
|
|
|
- block
|
|
|
- round
|
|
|
- :disabled="!canExchange"
|
|
|
- @click="showConfirmDialog"
|
|
|
- class="confirm-btn"
|
|
|
- >
|
|
|
- 确认兑换(-{{ exchangeAmount || 0 }}金币)
|
|
|
- </van-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 二次确认弹窗 -->
|
|
|
- <van-dialog
|
|
|
- v-model="confirmDialogVisible"
|
|
|
- title="是否确认ID兑换?"
|
|
|
- show-cancel-button
|
|
|
- confirm-button-text="确认兑换"
|
|
|
- cancel-button-text="取消兑换"
|
|
|
- @confirm="confirmExchange"
|
|
|
- @cancel="confirmDialogVisible = false"
|
|
|
- class="confirm-dialog"
|
|
|
- >
|
|
|
- <div class="confirm-content">
|
|
|
- <div class="confirm-user-info">
|
|
|
- <div class="confirm-avatar">
|
|
|
- <img v-if="userInfo && userInfo.avatar" :src="userInfo.avatar" class="avatar" />
|
|
|
- <div v-else class="avatar-placeholder">
|
|
|
- <van-icon name="user-o" size="32" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="confirm-user-details">
|
|
|
- <div class="confirm-user-name">{{ userInfo ? userInfo.nickname : '用户昵称' }}</div>
|
|
|
- <div class="confirm-user-id">ID: {{ userInfo ? userInfo.id : userId }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="confirm-exchange-info">
|
|
|
- <div class="confirm-item">
|
|
|
- <span class="confirm-label">兑换的金币数量:</span>
|
|
|
- <span class="confirm-value">{{ exchangeAmount }}</span>
|
|
|
- </div>
|
|
|
- <div class="confirm-item">
|
|
|
- <span class="confirm-label">兑换后获得:</span>
|
|
|
- <span class="confirm-value highlight">{{ getDiamondAmount }} <van-icon name="diamond-o" size="16" /></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </van-dialog>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import { getUserInfo } from '@/api/user'
|
|
|
-import { integralExchangeGoldCoinToOther } from '@/api/coin'
|
|
|
-
|
|
|
-export default {
|
|
|
- name: 'CoinExchangePage',
|
|
|
- data() {
|
|
|
- return {
|
|
|
- coinBalance: 0, // 金币余额,从localStorage获取
|
|
|
- userId: '',
|
|
|
- userInfo: null,
|
|
|
- exchangeAmount: '',
|
|
|
- confirmDialogVisible: false,
|
|
|
- exchangeRate: 10 // 1金币 = 10钻石
|
|
|
- }
|
|
|
- },
|
|
|
- created() {
|
|
|
- // 从localStorage获取金币余额
|
|
|
- const integral = localStorage.getItem('integral')
|
|
|
- this.coinBalance = parseInt(integral) || 0
|
|
|
- },
|
|
|
- computed: {
|
|
|
- // 计算兑换后获得的钻石数量
|
|
|
- getDiamondAmount() {
|
|
|
- const amount = parseInt(this.exchangeAmount) || 0
|
|
|
- return amount * this.exchangeRate
|
|
|
- },
|
|
|
-
|
|
|
- // 是否可以兑换
|
|
|
- canExchange() {
|
|
|
- const amount = parseInt(this.exchangeAmount) || 0
|
|
|
- return this.userInfo &&
|
|
|
- amount > 0 &&
|
|
|
- amount <= this.coinBalance &&
|
|
|
- this.userId.length === 6
|
|
|
- }
|
|
|
- },
|
|
|
- methods: {
|
|
|
- // 返回上一页
|
|
|
- goBack() {
|
|
|
- this.$router.go(-1)
|
|
|
- },
|
|
|
-
|
|
|
- // 跳转到兑换记录页面
|
|
|
- goToRecord() {
|
|
|
- this.$router.push('/coin-exchange-record')
|
|
|
- },
|
|
|
-
|
|
|
- // 用户ID输入处理
|
|
|
- async onUserIdInput() {
|
|
|
- // 只允许数字
|
|
|
- this.userId = this.userId.replace(/\D/g, '')
|
|
|
-
|
|
|
- // 当输入6位数字时自动搜索用户
|
|
|
- if (this.userId.length === 6) {
|
|
|
- await this.searchUser()
|
|
|
- } else {
|
|
|
- this.userInfo = null
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 搜索用户信息
|
|
|
- async searchUser() {
|
|
|
- if (!this.userId || this.userId.length !== 6) {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- try {
|
|
|
- this.$toast.loading({
|
|
|
- message: '搜索用户中...',
|
|
|
- forbidClick: true,
|
|
|
- duration: 0
|
|
|
- })
|
|
|
-
|
|
|
- // 调用API搜索用户信息
|
|
|
- const res = await getUserInfo(this.userId)
|
|
|
- this.$toast.clear()
|
|
|
-
|
|
|
- if (res.data && res.data.userId) {
|
|
|
- this.userInfo = {
|
|
|
- id: res.data.userId,
|
|
|
- nickname: res.data.userName || '未知用户',
|
|
|
- avatar: res.data.avatar || ''
|
|
|
- }
|
|
|
- } else {
|
|
|
- this.userInfo = null
|
|
|
- this.$toast('未找到该用户')
|
|
|
- }
|
|
|
- } catch (error) {
|
|
|
- this.$toast.clear()
|
|
|
- this.userInfo = null
|
|
|
- this.$toast('搜索用户失败')
|
|
|
- console.error('搜索用户失败:', error)
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 兑换数量输入处理
|
|
|
- onExchangeAmountInput() {
|
|
|
- // 只允许正整数
|
|
|
- this.exchangeAmount = this.exchangeAmount.replace(/\D/g, '')
|
|
|
-
|
|
|
- // 检查是否超过余额
|
|
|
- const amount = parseInt(this.exchangeAmount) || 0
|
|
|
- if (amount > this.coinBalance) {
|
|
|
- this.$toast('兑换数量不能超过余额')
|
|
|
- this.exchangeAmount = this.coinBalance.toString()
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 显示确认对话框
|
|
|
- showConfirmDialog() {
|
|
|
- if (!this.canExchange) {
|
|
|
- if (!this.userInfo) {
|
|
|
- this.$toast('请先输入有效的用户ID')
|
|
|
- } else if (!this.exchangeAmount || this.exchangeAmount <= 0) {
|
|
|
- this.$toast('请输入有效的兑换数量')
|
|
|
- } else if (parseInt(this.exchangeAmount) > this.coinBalance) {
|
|
|
- this.$toast('兑换数量不能超过余额')
|
|
|
- }
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- this.confirmDialogVisible = true
|
|
|
- },
|
|
|
-
|
|
|
- // 确认兑换
|
|
|
- async confirmExchange() {
|
|
|
- // 关闭弹窗
|
|
|
- this.confirmDialogVisible = false
|
|
|
-
|
|
|
- try {
|
|
|
- this.$toast.loading({
|
|
|
- message: '兑换中...',
|
|
|
- forbidClick: true,
|
|
|
- duration: 0
|
|
|
- })
|
|
|
-
|
|
|
- // 调用兑换API
|
|
|
- const response = await integralExchangeGoldCoinToOther(
|
|
|
- this.userId,
|
|
|
- parseInt(this.exchangeAmount)
|
|
|
- )
|
|
|
-
|
|
|
- this.$toast.clear()
|
|
|
- this.$toast.success('兑换成功')
|
|
|
-
|
|
|
- // 更新余额 - 从API返回值获取最新的integral并更新localStorage
|
|
|
- if (response && response.data && typeof response.data.integral !== 'undefined') {
|
|
|
- this.coinBalance = response.data.integral
|
|
|
- localStorage.setItem('integral', response.data.integral.toString())
|
|
|
- } else {
|
|
|
- // 如果API没有返回integral,则使用原来的减法逻辑
|
|
|
- this.coinBalance -= parseInt(this.exchangeAmount)
|
|
|
- }
|
|
|
-
|
|
|
- // 重置表单
|
|
|
- this.resetForm()
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- this.$toast.clear()
|
|
|
- this.$toast.fail('兑换失败,请重试')
|
|
|
- console.error('兑换失败:', error)
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 重置表单
|
|
|
- resetForm() {
|
|
|
- this.userId = ''
|
|
|
- this.userInfo = null
|
|
|
- this.exchangeAmount = ''
|
|
|
- this.confirmDialogVisible = false
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.coin-exchange-page {
|
|
|
- min-height: 100vh;
|
|
|
- background-color: var(--background-color);
|
|
|
-}
|
|
|
-
|
|
|
-/* 页面头部 */
|
|
|
-.page-header {
|
|
|
- background: var(--card-background);
|
|
|
- padding: 12px 16px;
|
|
|
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
|
|
-}
|
|
|
-
|
|
|
-.header-content {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-
|
|
|
-.back-btn {
|
|
|
- width: 40px;
|
|
|
- height: 40px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- cursor: pointer;
|
|
|
- color: var(--text-color);
|
|
|
-}
|
|
|
-
|
|
|
-.header-title {
|
|
|
- font-size: 18px;
|
|
|
- font-weight: 600;
|
|
|
- color: var(--text-color);
|
|
|
-}
|
|
|
-
|
|
|
-.record-btn {
|
|
|
- font-size: 14px;
|
|
|
- color: var(--primary-color);
|
|
|
- cursor: pointer;
|
|
|
- padding: 8px 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.record-btn:hover {
|
|
|
- opacity: 0.8;
|
|
|
-}
|
|
|
-
|
|
|
-/* 余额部分 */
|
|
|
-.balance-section {
|
|
|
- padding: 20px 16px;
|
|
|
-}
|
|
|
-
|
|
|
-.balance-card {
|
|
|
- background: linear-gradient(135deg, var(--primary-color), #9B59FF);
|
|
|
- border-radius: 16px;
|
|
|
- padding: 24px;
|
|
|
- text-align: center;
|
|
|
- color: white;
|
|
|
-}
|
|
|
-
|
|
|
-.balance-label {
|
|
|
- font-size: 14px;
|
|
|
- opacity: 0.9;
|
|
|
- margin-bottom: 8px;
|
|
|
-}
|
|
|
-
|
|
|
-.balance-amount {
|
|
|
- font-size: 32px;
|
|
|
- font-weight: 700;
|
|
|
-}
|
|
|
-
|
|
|
-/* 表单部分 */
|
|
|
-.exchange-form {
|
|
|
- padding: 0 16px 20px;
|
|
|
-}
|
|
|
-
|
|
|
-.form-card {
|
|
|
- background: var(--card-background);
|
|
|
- border-radius: 16px;
|
|
|
- padding: 24px;
|
|
|
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
|
|
-}
|
|
|
-
|
|
|
-.form-item {
|
|
|
- margin-bottom: 24px;
|
|
|
-}
|
|
|
-
|
|
|
-.form-label {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- color: var(--text-color);
|
|
|
- margin-bottom: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.user-id-input,
|
|
|
-.exchange-input {
|
|
|
- background: var(--input-background);
|
|
|
- border-radius: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.user-id-input :deep(.van-field__control),
|
|
|
-.exchange-input :deep(.van-field__control) {
|
|
|
- font-size: 16px;
|
|
|
- color: var(--text-color);
|
|
|
- padding: 16px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 用户信息显示 */
|
|
|
-.user-info-section {
|
|
|
- margin-bottom: 24px;
|
|
|
-}
|
|
|
-
|
|
|
-.user-info-card {
|
|
|
- background: var(--secondary-color);
|
|
|
- border-radius: 12px;
|
|
|
- padding: 16px;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-
|
|
|
-.user-avatar {
|
|
|
- width: 48px;
|
|
|
- height: 48px;
|
|
|
- border-radius: 50%;
|
|
|
- overflow: hidden;
|
|
|
- margin-right: 12px;
|
|
|
- background: var(--card-background);
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-
|
|
|
-.avatar {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- object-fit: cover;
|
|
|
-}
|
|
|
-
|
|
|
-.avatar-placeholder {
|
|
|
- color: var(--text-lighter-color);
|
|
|
-}
|
|
|
-
|
|
|
-.user-details {
|
|
|
- flex: 1;
|
|
|
-}
|
|
|
-
|
|
|
-.user-name {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- color: var(--text-color);
|
|
|
- margin-bottom: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.user-id-display {
|
|
|
- font-size: 14px;
|
|
|
- color: var(--text-lighter-color);
|
|
|
-}
|
|
|
-
|
|
|
-/* 兑换结果 */
|
|
|
-.exchange-result {
|
|
|
- background: var(--secondary-color);
|
|
|
- border-radius: 12px;
|
|
|
- padding: 16px;
|
|
|
- margin-bottom: 24px;
|
|
|
-}
|
|
|
-
|
|
|
-.result-item {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
-}
|
|
|
-
|
|
|
-.result-label {
|
|
|
- font-size: 14px;
|
|
|
- color: var(--text-color);
|
|
|
-}
|
|
|
-
|
|
|
-.result-value {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 600;
|
|
|
- color: var(--primary-color);
|
|
|
-}
|
|
|
-
|
|
|
-/* 确认按钮 */
|
|
|
-.confirm-btn-container {
|
|
|
- margin-top: 32px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-btn {
|
|
|
- height: 48px;
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- background: var(--primary-color);
|
|
|
- border: none;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-btn:disabled {
|
|
|
- background: var(--text-lighter-color);
|
|
|
- opacity: 0.6;
|
|
|
-}
|
|
|
-
|
|
|
-/* 确认对话框 */
|
|
|
-.confirm-dialog :deep(.van-dialog) {
|
|
|
- border-radius: 16px;
|
|
|
- overflow: hidden;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-dialog :deep(.van-dialog__header) {
|
|
|
- padding: 20px 24px 16px;
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- color: #333;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-dialog :deep(.van-dialog__content) {
|
|
|
- padding: 0 24px 24px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-dialog :deep(.van-dialog__footer) {
|
|
|
- padding: 16px 24px 24px;
|
|
|
- display: flex;
|
|
|
- gap: 12px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-dialog :deep(.van-dialog__cancel) {
|
|
|
- flex: 1;
|
|
|
- background: #f5f5f5;
|
|
|
- color: #666;
|
|
|
- border: none;
|
|
|
- border-radius: 24px;
|
|
|
- height: 48px;
|
|
|
- font-size: 16px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-dialog :deep(.van-dialog__confirm) {
|
|
|
- flex: 1;
|
|
|
- background: var(--primary-color);
|
|
|
- color: white;
|
|
|
- border: none;
|
|
|
- border-radius: 24px;
|
|
|
- height: 48px;
|
|
|
- font-size: 16px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-content {
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-user-info {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: flex-start;
|
|
|
- margin-bottom: 24px;
|
|
|
- padding: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-avatar {
|
|
|
- width: 48px;
|
|
|
- height: 48px;
|
|
|
- border-radius: 50%;
|
|
|
- overflow: hidden;
|
|
|
- margin-right: 12px;
|
|
|
- background: #f5f5f5;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-avatar .avatar {
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- object-fit: cover;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-user-details {
|
|
|
- text-align: left;
|
|
|
- flex: 1;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-user-name {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- color: #333;
|
|
|
- margin-bottom: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-user-id {
|
|
|
- font-size: 14px;
|
|
|
- color: #999;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-exchange-info {
|
|
|
- text-align: left;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-item {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 16px;
|
|
|
- padding: 0;
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-label {
|
|
|
- font-size: 14px;
|
|
|
- color: var(--text-color);
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-value {
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 500;
|
|
|
- color: var(--text-color);
|
|
|
-}
|
|
|
-
|
|
|
-.confirm-value.highlight {
|
|
|
- color: var(--primary-color);
|
|
|
- font-weight: 600;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 4px;
|
|
|
-}
|
|
|
-
|
|
|
-/* 响应式设计 */
|
|
|
-@media (max-width: 375px) {
|
|
|
- .balance-card {
|
|
|
- padding: 20px;
|
|
|
- }
|
|
|
-
|
|
|
- .balance-amount {
|
|
|
- font-size: 28px;
|
|
|
- }
|
|
|
-
|
|
|
- .form-card {
|
|
|
- padding: 20px;
|
|
|
- }
|
|
|
-
|
|
|
- .confirm-user-info {
|
|
|
- flex-direction: column;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
-
|
|
|
- .confirm-avatar {
|
|
|
- margin-right: 0;
|
|
|
- margin-bottom: 12px;
|
|
|
- }
|
|
|
-
|
|
|
- .confirm-user-details {
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|