|
|
@@ -0,0 +1,282 @@
|
|
|
+<template>
|
|
|
+ <div class="recharge-container">
|
|
|
+ <el-tabs v-model="activeTab" type="card">
|
|
|
+ <el-tab-pane label="充值到总账户" name="recharge">
|
|
|
+ <div class="form-card">
|
|
|
+ <el-form :model="rechargeForm" label-width="120px" ref="rechargeForm">
|
|
|
+ <el-form-item label="租户ID" prop="tenantId">
|
|
|
+ <el-input v-model="rechargeForm.tenantId" type="number" placeholder="请输入租户ID" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="租户名称" prop="tenantName">
|
|
|
+ <el-input v-model="rechargeForm.tenantName" placeholder="请输入租户名称" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="充值金额" prop="amount">
|
|
|
+ <el-input v-model="rechargeForm.amount" type="number" placeholder="请输入充值金额" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleRecharge">确认充值</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="购买预存服务" name="purchase">
|
|
|
+ <div class="form-card">
|
|
|
+ <el-form :model="purchaseForm" label-width="120px" ref="purchaseForm">
|
|
|
+ <el-form-item label="租户ID" prop="tenantId">
|
|
|
+ <el-input v-model="purchaseForm.tenantId" type="number" placeholder="请输入租户ID" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="服务类型" prop="serviceType">
|
|
|
+ <el-select v-model="purchaseForm.serviceType" placeholder="请选择服务类型">
|
|
|
+ <el-option label="AI模型训练" :value="1" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="购买数量" prop="quantity">
|
|
|
+ <el-input v-model="purchaseForm.quantity" type="number" placeholder="请输入购买数量" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="预计费用">
|
|
|
+ <span class="fee-display">¥{{ estimatedFee.toFixed(2) }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handlePurchase">确认购买</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="服务余额转回" name="transfer">
|
|
|
+ <div class="form-card">
|
|
|
+ <el-form :model="transferForm" label-width="120px" ref="transferForm">
|
|
|
+ <el-form-item label="租户ID" prop="tenantId">
|
|
|
+ <el-input v-model="transferForm.tenantId" type="number" placeholder="请输入租户ID" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="服务类型" prop="serviceType">
|
|
|
+ <el-select v-model="transferForm.serviceType" placeholder="请选择服务类型">
|
|
|
+ <el-option label="AI模型训练" :value="1" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="转回数量" prop="quantity">
|
|
|
+ <el-input v-model="transferForm.quantity" type="number" placeholder="请输入转回数量" />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleTransfer">确认转回</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </el-tab-pane>
|
|
|
+
|
|
|
+ <el-tab-pane label="充值记录" name="records">
|
|
|
+ <div class="search-bar">
|
|
|
+ <el-input v-model="searchForm.keyword" placeholder="租户名称/订单号" class="search-input" />
|
|
|
+ <el-date-picker v-model="searchForm.dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
+ <el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
|
+ </div>
|
|
|
+ <el-table :data="rechargeList" border>
|
|
|
+ <el-table-column prop="tenantName" label="租户名称" />
|
|
|
+ <el-table-column prop="amount" label="充值金额">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span class="text-green">+¥{{ scope.row.amount }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="orderNo" label="订单号" />
|
|
|
+ <el-table-column prop="status" label="状态">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tag :type="scope.row.status === 1 ? 'success' : 'warning'">
|
|
|
+ {{ scope.row.status === 1 ? '成功' : '处理中' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="createTime" label="充值时间" />
|
|
|
+ </el-table>
|
|
|
+ <el-pagination
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ :current-page="pageInfo.pageNum"
|
|
|
+ :page-size="pageInfo.pageSize"
|
|
|
+ :total="pageInfo.total"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ />
|
|
|
+ </el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { rechargeToTotal, purchaseService, transferToTotal, getConsumeRecords, getFeeConfigs } from '@/api/balance'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'BalanceRecharge',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ activeTab: 'recharge',
|
|
|
+ rechargeForm: {
|
|
|
+ tenantId: '',
|
|
|
+ tenantName: '',
|
|
|
+ amount: ''
|
|
|
+ },
|
|
|
+ purchaseForm: {
|
|
|
+ tenantId: '',
|
|
|
+ serviceType: '',
|
|
|
+ quantity: ''
|
|
|
+ },
|
|
|
+ transferForm: {
|
|
|
+ tenantId: '',
|
|
|
+ serviceType: '',
|
|
|
+ quantity: ''
|
|
|
+ },
|
|
|
+ searchForm: {
|
|
|
+ keyword: '',
|
|
|
+ dateRange: []
|
|
|
+ },
|
|
|
+ rechargeList: [],
|
|
|
+ pageInfo: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0
|
|
|
+ },
|
|
|
+ feeConfigs: [],
|
|
|
+ estimatedFee: 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.loadFeeConfigs()
|
|
|
+ this.loadRechargeList()
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ 'purchaseForm.serviceType': function(val) {
|
|
|
+ this.calculateEstimatedFee()
|
|
|
+ },
|
|
|
+ 'purchaseForm.quantity': function(val) {
|
|
|
+ this.calculateEstimatedFee()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async loadFeeConfigs() {
|
|
|
+ const response = await getFeeConfigs()
|
|
|
+ this.feeConfigs = response.data || []
|
|
|
+ },
|
|
|
+ calculateEstimatedFee() {
|
|
|
+ const config = this.feeConfigs.find(c => c.serviceType === this.purchaseForm.serviceType)
|
|
|
+ if (config && this.purchaseForm.quantity) {
|
|
|
+ this.estimatedFee = config.feeStandard * this.purchaseForm.quantity
|
|
|
+ } else {
|
|
|
+ this.estimatedFee = 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handleRecharge() {
|
|
|
+ try {
|
|
|
+ await rechargeToTotal({
|
|
|
+ tenantId: this.rechargeForm.tenantId,
|
|
|
+ amount: this.rechargeForm.amount
|
|
|
+ })
|
|
|
+ this.$message.success('充值成功')
|
|
|
+ this.rechargeForm = { tenantId: '', tenantName: '', amount: '' }
|
|
|
+ this.activeTab = 'records'
|
|
|
+ this.loadRechargeList()
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error('充值失败: ' + (error.response?.data?.msg || error.message))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handlePurchase() {
|
|
|
+ try {
|
|
|
+ await purchaseService({
|
|
|
+ tenantId: this.purchaseForm.tenantId,
|
|
|
+ serviceType: this.purchaseForm.serviceType,
|
|
|
+ quantity: this.purchaseForm.quantity
|
|
|
+ })
|
|
|
+ this.$message.success('购买成功')
|
|
|
+ this.purchaseForm = { tenantId: '', serviceType: '', quantity: '' }
|
|
|
+ this.estimatedFee = 0
|
|
|
+ this.activeTab = 'records'
|
|
|
+ this.loadRechargeList()
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error('购买失败: ' + (error.response?.data?.msg || error.message))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async handleTransfer() {
|
|
|
+ try {
|
|
|
+ await transferToTotal({
|
|
|
+ tenantId: this.transferForm.tenantId,
|
|
|
+ serviceType: this.transferForm.serviceType,
|
|
|
+ quantity: this.transferForm.quantity
|
|
|
+ })
|
|
|
+ this.$message.success('转回成功')
|
|
|
+ this.transferForm = { tenantId: '', serviceType: '', quantity: '' }
|
|
|
+ this.activeTab = 'records'
|
|
|
+ this.loadRechargeList()
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error('转回失败: ' + (error.response?.data?.msg || error.message))
|
|
|
+ }
|
|
|
+ },
|
|
|
+ formatDate(date) {
|
|
|
+ const d = new Date(date)
|
|
|
+ const pad = n => n.toString().padStart(2, '0')
|
|
|
+ return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds())
|
|
|
+ },
|
|
|
+ async loadRechargeList() {
|
|
|
+ const params = {
|
|
|
+ serviceType: 0,
|
|
|
+ startTime: this.searchForm.dateRange[0] ? this.formatDate(this.searchForm.dateRange[0]) : '',
|
|
|
+ endTime: this.searchForm.dateRange[1] ? this.formatDate(this.searchForm.dateRange[1]) : '',
|
|
|
+ pageNum: this.pageInfo.pageNum,
|
|
|
+ pageSize: this.pageInfo.pageSize
|
|
|
+ }
|
|
|
+ const response = await getConsumeRecords(params)
|
|
|
+ this.rechargeList = response.data.list || []
|
|
|
+ this.pageInfo.total = response.data.total || 0
|
|
|
+ },
|
|
|
+ handleSearch() {
|
|
|
+ this.pageInfo.pageNum = 1
|
|
|
+ this.loadRechargeList()
|
|
|
+ },
|
|
|
+ handleSizeChange(val) {
|
|
|
+ this.pageInfo.pageSize = val
|
|
|
+ this.loadRechargeList()
|
|
|
+ },
|
|
|
+ handleCurrentChange(val) {
|
|
|
+ this.pageInfo.pageNum = val
|
|
|
+ this.loadRechargeList()
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.recharge-container {
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.form-card {
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 30px;
|
|
|
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
|
|
+ max-width: 500px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-bar {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ flex-wrap: wrap;
|
|
|
+
|
|
|
+ .search-input {
|
|
|
+ width: 200px;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-date-picker {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.fee-display {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
+.text-green {
|
|
|
+ color: #67c23a;
|
|
|
+}
|
|
|
+</style>
|