785 lines
21 KiB
Vue
785 lines
21 KiB
Vue
<template>
|
||
<div class="user-balance-container">
|
||
<!-- 顶部信息栏 -->
|
||
<div class="page-header">
|
||
<div class="header-left">
|
||
<el-button @click="router.go(-1)" link class="back-btn">
|
||
<el-icon><ArrowLeft /></el-icon> 返回
|
||
</el-button>
|
||
<el-divider direction="vertical" />
|
||
<h2 class="page-title">用户余额管理</h2>
|
||
<div class="user-info">
|
||
<span class="user-name">{{ getCurrentUserName() }}</span>
|
||
<span class="user-id">ID: {{ queryParams.user_id }}</span>
|
||
</div>
|
||
</div>
|
||
<el-button type="primary" @click="fetchUserBalance">
|
||
<el-icon><Refresh /></el-icon>刷新数据
|
||
</el-button>
|
||
</div>
|
||
|
||
<!-- 余额卡片 -->
|
||
<div class="balance-cards" v-loading="loading">
|
||
<div
|
||
v-for="balance in balanceList"
|
||
:key="balance.type"
|
||
class="balance-card"
|
||
:class="`balance-card-${balance.type}`"
|
||
>
|
||
<div class="card-header">
|
||
<span class="balance-type">{{ getBalanceTypeName(balance.type) }}</span>
|
||
<span class="balance-id">ID: {{ balance.id }}</span>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="balance-amount">
|
||
<span class="currency">¥</span>
|
||
<span class="amount">{{ (balance.price / 100).toFixed(2) }}</span>
|
||
</div>
|
||
<div class="balance-time">更新于 {{ formatDateTime(balance.UpdatedAt) }}</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<el-button size="small" @click="handleEditBalance(balance.type)">修改余额</el-button>
|
||
<el-button size="small" @click="handleAddRecord(balance.type)">添加记录</el-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 余额记录 -->
|
||
<div class="record-section">
|
||
<div class="section-header">
|
||
<h3 class="section-title">余额变动记录</h3>
|
||
</div>
|
||
<div class="table-wrapper">
|
||
<el-table
|
||
:data="recordList"
|
||
v-loading="loading"
|
||
style="width: 100%"
|
||
:header-cell-style="{ background: '#fafafa', color: '#333', fontWeight: 600 }"
|
||
>
|
||
<el-table-column prop="Id" label="记录ID" width="100" />
|
||
<el-table-column label="余额类型" width="120">
|
||
<template #default="{ row }">
|
||
<el-tag size="small">{{ getBalanceTypeByRecordId(row.BalanceId) }}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="变动类型" width="100">
|
||
<template #default="{ row }">
|
||
<el-tag v-if="row.Change" type="success" size="small">增加</el-tag>
|
||
<el-tag v-else type="danger" size="small">减少</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="变动金额" width="150">
|
||
<template #default="{ row }">
|
||
<span :class="row.Change ? 'amount-plus' : 'amount-minus'">
|
||
{{ row.Change ? '+' : '-' }}¥{{ (row.Price / 100).toFixed(2) }}
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="变动后余额" width="150">
|
||
<template #default="{ row }">
|
||
<span class="balance-after">¥{{ ((row.BalanceAfter || 0) / 100).toFixed(2) }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="Note" label="备注" min-width="200" show-overflow-tooltip />
|
||
<el-table-column label="支付订单ID" width="150" show-overflow-tooltip>
|
||
<template #default="{ row }">
|
||
<el-link v-if="row.PaymentOrderId" type="primary" :underline="false" @click="router.push({ path: '/order/list', query: { key: row.PaymentOrderId } })">{{ row.PaymentOrderId }}</el-link>
|
||
<span v-else>-</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="创建时间" width="180">
|
||
<template #default="{ row }">
|
||
{{ formatDateTime(row.CreatedAt) }}
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<div class="pagination-wrapper">
|
||
<el-pagination
|
||
v-model:current-page="recordParams.page"
|
||
v-model:page-size="recordParams.count"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
:total="recordTotal"
|
||
@size-change="handleRecordSizeChange"
|
||
@current-change="handleRecordCurrentChange"
|
||
background
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 修改余额对话框 -->
|
||
<el-dialog v-model="balanceDialogVisible" title="修改用户余额" width="500px">
|
||
<el-form ref="balanceFormRef" :model="balanceForm" :rules="balanceRules" label-width="100px">
|
||
<el-form-item label="余额类型">
|
||
<el-input :value="getBalanceTypeNameByApiType(balanceForm.balance_type)" disabled />
|
||
</el-form-item>
|
||
<el-form-item label="当前余额">
|
||
<el-input :value="currentBalanceDisplay" disabled>
|
||
<template #prepend>¥</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="变动类型" prop="state">
|
||
<el-radio-group v-model="balanceForm.state">
|
||
<el-radio label="add">增加</el-radio>
|
||
<el-radio label="sub">减少</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item v-if="balanceForm.state === 'add'" label="收益入账">
|
||
<div class="account-amount-field">
|
||
<el-switch
|
||
v-model="balanceForm.account_amount"
|
||
active-text="计入 007pay"
|
||
inactive-text="不计入"
|
||
/>
|
||
<div class="form-tip">加款同时生成 007pay 手工入账记录,用于收益统计。</div>
|
||
</div>
|
||
</el-form-item>
|
||
<el-form-item label="变动金额" prop="price">
|
||
<el-input v-model.number="balanceForm.price" placeholder="请输入变动金额">
|
||
<template #prepend>¥</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="备注" prop="note">
|
||
<el-input v-model="balanceForm.note" type="textarea" :rows="3" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="balanceDialogVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="submitBalanceForm">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<!-- 添加记录对话框 -->
|
||
<el-dialog v-model="recordDialogVisible" title="添加消费记录" width="500px">
|
||
<el-form ref="recordFormRef" :model="recordForm" :rules="recordRules" label-width="120px">
|
||
<el-form-item label="余额类型">
|
||
<el-input :value="getBalanceTypeNameByApiType(recordForm.balance_type)" disabled />
|
||
</el-form-item>
|
||
<el-form-item label="是否执行到余额" prop="apply_balance">
|
||
<el-switch v-model="recordForm.apply_balance" active-text="是" inactive-text="否" />
|
||
</el-form-item>
|
||
<el-form-item label="变动类型" prop="state">
|
||
<el-radio-group v-model="recordForm.state">
|
||
<el-radio label="add">增加</el-radio>
|
||
<el-radio label="sub">减少</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item label="变动金额" prop="price">
|
||
<el-input v-model.number="recordForm.price" placeholder="请输入金额">
|
||
<template #prepend>¥</template>
|
||
</el-input>
|
||
</el-form-item>
|
||
<el-form-item label="支付平台订单id" prop="paymentOrderId">
|
||
<el-input v-model="recordForm.paymentOrderId" placeholder="请输入支付平台订单ID" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="备注" prop="note">
|
||
<el-input v-model="recordForm.note" type="textarea" :rows="3" placeholder="请输入备注" />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button @click="recordDialogVisible = false">取消</el-button>
|
||
<el-button type="primary" @click="submitRecordForm">确定</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, onMounted, computed, watch } from 'vue'
|
||
import { useRoute, useRouter } from 'vue-router'
|
||
import { ElMessage } from 'element-plus'
|
||
import { Refresh, ArrowLeft } from '@element-plus/icons-vue'
|
||
import { getUserBalanceRecord, editUserBalance, addUserConsumption, getUserBalanceCount, getUserList } from '@/api/admin/user'
|
||
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
|
||
// 余额类型映射
|
||
const userBalance = {
|
||
entity: { name: '云钻', type: 'cloud_diamond' },
|
||
general: { name: '云币', type: 'cloud_coin' },
|
||
withdraw: { name: '云点', type: 'cloud_points' }
|
||
}
|
||
|
||
// 查询参数
|
||
const queryParams = reactive({
|
||
user_id: route.query.user_id || ''
|
||
})
|
||
|
||
// 余额记录查询参数
|
||
const recordParams = reactive({
|
||
user_id: '',
|
||
balance_type: '', // 初始化为空字符串,避免 undefined
|
||
page: 1,
|
||
count: 10
|
||
})
|
||
|
||
// 状态数据
|
||
const loading = ref(false)
|
||
const balanceInfo = ref(null)
|
||
const balanceList = ref([])
|
||
const recordList = ref([])
|
||
const recordTotal = ref(0)
|
||
const userList = ref([])
|
||
|
||
// 对话框
|
||
const balanceDialogVisible = ref(false)
|
||
const recordDialogVisible = ref(false)
|
||
const balanceFormRef = ref(null)
|
||
const recordFormRef = ref(null)
|
||
|
||
// 余额表单
|
||
const balanceForm = reactive({
|
||
user_id: '',
|
||
balance_type: '',
|
||
price: 0,
|
||
state: 'add',
|
||
note: '',
|
||
account_amount: false
|
||
})
|
||
|
||
const balanceRules = {
|
||
price: [
|
||
{ required: true, message: '请输入变动金额', trigger: 'blur' },
|
||
{ type: 'number', message: '请输入数字', trigger: 'blur' }
|
||
],
|
||
state: [{ required: true, message: '请选择变动类型', trigger: 'change' }],
|
||
note: [{ required: true, message: '请输入备注', trigger: 'blur' }]
|
||
}
|
||
|
||
// 记录表单
|
||
const recordForm = reactive({
|
||
user_id: '',
|
||
balance_type: '',
|
||
apply_balance: false,
|
||
price: 0,
|
||
state: 'add',
|
||
note: '',
|
||
paymentOrderId: ''
|
||
})
|
||
|
||
const recordRules = {
|
||
price: [
|
||
{ required: true, message: '请输入金额', trigger: 'blur' },
|
||
{ type: 'number', message: '请输入数字', trigger: 'blur' }
|
||
],
|
||
state: [{ required: true, message: '请选择状态类型', trigger: 'change' }],
|
||
note: [{ required: true, message: '请输入备注', trigger: 'blur' }]
|
||
}
|
||
|
||
// 当前余额显示
|
||
const currentBalanceDisplay = computed(() => {
|
||
const balance = balanceList.value.find(b => userBalance[b.type]?.type === balanceForm.balance_type)
|
||
return balance ? (balance.price / 100).toFixed(2) : '0.00'
|
||
})
|
||
|
||
// 获取用户列表(用于显示用户名)
|
||
const getUserListData = async () => {
|
||
try {
|
||
const res = await getUserList({ page: 1, count: 10, key: '' })
|
||
if (res.data.code === 200) {
|
||
userList.value = res.data.data.data || []
|
||
}
|
||
} catch (error) {
|
||
console.error('获取用户列表错误:', error)
|
||
}
|
||
}
|
||
|
||
// 获取当前用户名
|
||
const getCurrentUserName = () => {
|
||
if (!queryParams.user_id) return '未知用户'
|
||
const user = userList.value.find(u => u.UserId === queryParams.user_id)
|
||
return user ? user.UserName : `用户${queryParams.user_id}`
|
||
}
|
||
|
||
// 获取余额类型名称
|
||
const getBalanceTypeName = (type) => {
|
||
return userBalance[type]?.name || type
|
||
}
|
||
|
||
// 通过API类型获取余额类型名称
|
||
const getBalanceTypeNameByApiType = (apiType) => {
|
||
const entry = Object.values(userBalance).find(b => b.type === apiType)
|
||
return entry ? entry.name : apiType
|
||
}
|
||
|
||
// 通过记录的BalanceId获取余额类型名称
|
||
const getBalanceTypeByRecordId = (balanceId) => {
|
||
if (!balanceId) return '未知类型'
|
||
const balance = balanceList.value.find(b => b.id === balanceId)
|
||
return balance ? getBalanceTypeName(balance.type) : '未知类型'
|
||
}
|
||
|
||
// 格式化时间
|
||
const formatDateTime = (dateStr) => {
|
||
if (!dateStr) return '-'
|
||
const date = new Date(dateStr)
|
||
return date.toLocaleString('zh-CN', { hour12: false })
|
||
}
|
||
|
||
// 获取用户余额
|
||
const fetchUserBalance = async () => {
|
||
if (!queryParams.user_id) {
|
||
ElMessage.warning('缺少用户ID参数')
|
||
return
|
||
}
|
||
|
||
loading.value = true
|
||
try {
|
||
const res = await getUserBalanceCount({ user_id: queryParams.user_id })
|
||
if (res.data.code === 200) {
|
||
balanceInfo.value = res.data.data
|
||
const returnedData = Array.isArray(res.data.data) ? res.data.data : []
|
||
|
||
// 定义默认余额
|
||
const defaultBalances = [
|
||
{ id: '-', userId: queryParams.user_id, price: 0, type: 'entity', CreatedAt: new Date().toISOString(), UpdatedAt: new Date().toISOString() },
|
||
{ id: '-', userId: queryParams.user_id, price: 0, type: 'general', CreatedAt: new Date().toISOString(), UpdatedAt: new Date().toISOString() },
|
||
{ id: '-', userId: queryParams.user_id, price: 0, type: 'withdraw', CreatedAt: new Date().toISOString(), UpdatedAt: new Date().toISOString() }
|
||
]
|
||
|
||
// 检查缺失的余额类型
|
||
const requiredTypes = ['entity', 'general', 'withdraw']
|
||
const missingTypes = requiredTypes.filter(type => !returnedData.some(item => item.type === type))
|
||
|
||
// 初始化缺失的余额类型
|
||
if (missingTypes.length > 0) {
|
||
const initPromises = missingTypes.map(type =>
|
||
editUserBalance({
|
||
user_id: queryParams.user_id,
|
||
balance_type: userBalance[type].type,
|
||
price: 0,
|
||
state: 'add',
|
||
note: `系统自动初始化${getBalanceTypeName(type)}余额`
|
||
})
|
||
)
|
||
await Promise.all(initPromises)
|
||
|
||
// 重新获取余额
|
||
const newRes = await getUserBalanceCount({ user_id: queryParams.user_id })
|
||
if (newRes.data.code === 200) {
|
||
const newReturnedData = Array.isArray(newRes.data.data) ? newRes.data.data : []
|
||
balanceList.value = defaultBalances.map(defaultItem =>
|
||
newReturnedData.find(item => item.type === defaultItem.type) || defaultItem
|
||
)
|
||
}
|
||
} else {
|
||
balanceList.value = defaultBalances.map(defaultItem =>
|
||
returnedData.find(item => item.type === defaultItem.type) || defaultItem
|
||
)
|
||
}
|
||
|
||
recordParams.user_id = queryParams.user_id
|
||
fetchBalanceRecord()
|
||
} else {
|
||
ElMessage.error(res.data.message || '获取用户余额失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('获取用户余额错误:', error)
|
||
ElMessage.error('获取用户余额失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 获取余额记录
|
||
const fetchBalanceRecord = async () => {
|
||
loading.value = true
|
||
try {
|
||
const res = await getUserBalanceRecord(recordParams)
|
||
if (res.data.code === 200) {
|
||
recordList.value = res.data.data.data || []
|
||
recordTotal.value = res.data.data.total || 0
|
||
} else {
|
||
ElMessage.error(res.data.message || '获取余额记录失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('获取余额记录错误:', error)
|
||
ElMessage.error('获取余额记录失败')
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 修改余额
|
||
const handleEditBalance = (balanceType) => {
|
||
const apiType = userBalance[balanceType]?.type
|
||
balanceFormRef.value?.resetFields()
|
||
Object.assign(balanceForm, {
|
||
user_id: queryParams.user_id,
|
||
balance_type: apiType,
|
||
price: 0,
|
||
state: 'add',
|
||
note: '',
|
||
account_amount: false
|
||
})
|
||
balanceDialogVisible.value = true
|
||
}
|
||
|
||
// 添加记录
|
||
const handleAddRecord = (balanceType) => {
|
||
const apiType = userBalance[balanceType]?.type
|
||
recordFormRef.value?.resetFields()
|
||
Object.assign(recordForm, {
|
||
user_id: queryParams.user_id,
|
||
balance_type: apiType,
|
||
apply_balance: false,
|
||
price: 0,
|
||
state: 'add',
|
||
note: '',
|
||
paymentOrderId: ''
|
||
})
|
||
recordDialogVisible.value = true
|
||
}
|
||
|
||
// 提交余额修改
|
||
const submitBalanceForm = () => {
|
||
balanceFormRef.value?.validate(async (valid) => {
|
||
if (valid) {
|
||
try {
|
||
const submitData = { ...balanceForm }
|
||
if (submitData.state !== 'add' || !submitData.account_amount) {
|
||
delete submitData.account_amount
|
||
}
|
||
const res = await editUserBalance(submitData)
|
||
if (res.data.code === 200) {
|
||
ElMessage.success('修改成功')
|
||
balanceDialogVisible.value = false
|
||
fetchUserBalance()
|
||
} else {
|
||
ElMessage.error(res.data.message || '修改失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('修改余额错误:', error)
|
||
ElMessage.error('修改失败')
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 提交记录添加
|
||
const submitRecordForm = () => {
|
||
recordFormRef.value?.validate(async (valid) => {
|
||
if (valid) {
|
||
try {
|
||
const res = await addUserConsumption(recordForm)
|
||
if (res.data.code === 200) {
|
||
ElMessage.success('添加成功')
|
||
recordDialogVisible.value = false
|
||
fetchUserBalance()
|
||
} else {
|
||
ElMessage.error(res.data.message || '添加失败')
|
||
}
|
||
} catch (error) {
|
||
console.error('添加记录错误:', error)
|
||
ElMessage.error('添加失败')
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 分页
|
||
const handleRecordSizeChange = () => {
|
||
fetchBalanceRecord()
|
||
}
|
||
|
||
const handleRecordCurrentChange = () => {
|
||
fetchBalanceRecord()
|
||
}
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
getUserListData()
|
||
if (queryParams.user_id) {
|
||
fetchUserBalance()
|
||
} else {
|
||
ElMessage.warning('缺少用户ID参数')
|
||
}
|
||
})
|
||
|
||
// 监听路由参数变化
|
||
watch(
|
||
() => route.query.user_id,
|
||
(newUserId) => {
|
||
if (newUserId && newUserId !== queryParams.user_id) {
|
||
queryParams.user_id = newUserId
|
||
recordParams.user_id = newUserId
|
||
fetchUserBalance()
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
watch(
|
||
() => balanceForm.state,
|
||
(state) => {
|
||
if (state !== 'add') {
|
||
balanceForm.account_amount = false
|
||
}
|
||
}
|
||
)
|
||
</script>
|
||
|
||
<style scoped>
|
||
.user-balance-container {
|
||
padding: 0;
|
||
background: #f5f7fa;
|
||
min-height: 100vh;
|
||
}
|
||
|
||
/* 页面头部 */
|
||
.page-header {
|
||
background: #fff;
|
||
padding: 24px 32px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
border-bottom: 1px solid #e4e7ed;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
.back-btn {
|
||
font-size: 14px;
|
||
color: #606266;
|
||
}
|
||
|
||
.page-title {
|
||
margin: 0;
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.user-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
padding: 8px 16px;
|
||
background: #f5f7fa;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: #303133;
|
||
}
|
||
|
||
.user-id {
|
||
font-size: 13px;
|
||
color: #909399;
|
||
}
|
||
|
||
/* 余额卡片 */
|
||
.balance-cards {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20px;
|
||
padding: 0 32px 24px;
|
||
}
|
||
|
||
.balance-card {
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
padding: 24px;
|
||
border: 1px solid #e4e7ed;
|
||
transition: all 0.3s ease;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.balance-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 4px;
|
||
background: linear-gradient(90deg, #409eff, #66b1ff);
|
||
}
|
||
|
||
.balance-card-entity::before {
|
||
background: linear-gradient(90deg, #67c23a, #85ce61);
|
||
}
|
||
|
||
.balance-card-general::before {
|
||
background: linear-gradient(90deg, #409eff, #66b1ff);
|
||
}
|
||
|
||
.balance-card-withdraw::before {
|
||
background: linear-gradient(90deg, #e6a23c, #f0c78a);
|
||
}
|
||
|
||
.balance-card:hover {
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.balance-card .card-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.balance-type {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.balance-id {
|
||
font-size: 12px;
|
||
color: #909399;
|
||
background: #f5f7fa;
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.balance-card .card-body {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.balance-amount {
|
||
display: flex;
|
||
align-items: baseline;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.balance-amount .currency {
|
||
font-size: 20px;
|
||
color: #606266;
|
||
margin-right: 4px;
|
||
}
|
||
|
||
.balance-amount .amount {
|
||
font-size: 32px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.balance-time {
|
||
font-size: 13px;
|
||
color: #909399;
|
||
}
|
||
|
||
.balance-card .card-footer {
|
||
display: flex;
|
||
gap: 8px;
|
||
}
|
||
|
||
.balance-card .card-footer .el-button {
|
||
flex: 1;
|
||
}
|
||
|
||
/* 记录区域 */
|
||
.record-section {
|
||
background: #fff;
|
||
margin: 0 32px 32px;
|
||
border-radius: 8px;
|
||
border: 1px solid #e4e7ed;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.section-header {
|
||
padding: 20px 24px;
|
||
border-bottom: 1px solid #e4e7ed;
|
||
}
|
||
|
||
.section-title {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.table-wrapper {
|
||
padding: 0;
|
||
}
|
||
|
||
.table-wrapper :deep(.el-table) {
|
||
border: none;
|
||
}
|
||
|
||
.table-wrapper :deep(.el-table td),
|
||
.table-wrapper :deep(.el-table th) {
|
||
border-bottom: 1px solid #f0f2f5;
|
||
}
|
||
|
||
.table-wrapper :deep(.el-table tr:hover > td) {
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.amount-plus {
|
||
color: #67c23a;
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.amount-minus {
|
||
color: #f56c6c;
|
||
font-weight: 600;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.balance-after {
|
||
color: #303133;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.pagination-wrapper {
|
||
padding: 16px 24px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
border-top: 1px solid #e4e7ed;
|
||
background: #fafafa;
|
||
}
|
||
|
||
.form-tip {
|
||
font-size: 12px;
|
||
color: #909399;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
.account-amount-field {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
|
||
/* 响应式 */
|
||
@media (max-width: 1200px) {
|
||
.balance-cards {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.balance-cards {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
|
||
.page-header {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 16px;
|
||
}
|
||
|
||
.header-left {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 12px;
|
||
}
|
||
}
|
||
</style>
|