feat: 用户管理页增强——星尘余额列+调整星尘按钮(免搜openid)+查看订单弹窗+保留加额度
This commit is contained in:
+103
-9
@@ -5,30 +5,75 @@
|
||||
<el-button type="primary" @click="search">搜索</el-button>
|
||||
</div>
|
||||
<el-table :data="list" stripe v-loading="loading">
|
||||
<el-table-column prop="nickName" label="昵称" min-width="110" />
|
||||
<el-table-column label="OpenID" min-width="150">
|
||||
<template #default="{ row }">{{ (row.openid || '').slice(0, 14) }}…</template>
|
||||
<el-table-column prop="nickName" label="昵称" min-width="100" />
|
||||
<el-table-column label="OpenID" min-width="130">
|
||||
<template #default="{ row }">{{ (row.openid || '').slice(0, 12) }}…</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册时间" width="160">
|
||||
<el-table-column label="星尘" width="70" align="center">
|
||||
<template #default="{ row }">
|
||||
<span :style="{ fontWeight: 700, color: (row.vpayCoins || 0) > 0 ? '#5b5ff8' : '#999' }">{{ row.vpayCoins || 0 }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="注册时间" width="150">
|
||||
<template #default="{ row }">{{ fmt(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="最近登录" width="160">
|
||||
<el-table-column label="最近登录" width="150">
|
||||
<template #default="{ row }">{{ fmt(row.lastLoginAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80">
|
||||
<el-table-column label="状态" width="60">
|
||||
<template #default="{ row }"><el-tag :type="(row.status || 'active') === 'active' ? 'success' : 'info'" size="small">{{ (row.status || 'active') === 'active' ? '正常' : row.status }}</el-tag></template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="110">
|
||||
<el-table-column label="操作" width="220">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" @click="openQuota(row)">加问答额度</el-button>
|
||||
<el-button size="small" type="primary" @click="openAdjust(row)">调整星尘</el-button>
|
||||
<el-button size="small" @click="viewOrders(row)">订单</el-button>
|
||||
<el-button size="small" @click="openQuota(row)">加额度</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination background layout="total, prev, pager, next" :total="total" :page-size="pageSize" v-model:current-page="page" @current-change="load" style="margin-top: 12px" />
|
||||
|
||||
<!-- 调整星尘 -->
|
||||
<el-dialog v-model="adjustDlg" title="调整星尘余额" width="min(400px, 92%)" style="max-width: 400px">
|
||||
<div class="adjust-user-info">
|
||||
<b>{{ adjustUser?.nickName || '未命名' }}</b>
|
||||
<span>当前星尘:{{ adjustUser?.vpayCoins || 0 }}</span>
|
||||
</div>
|
||||
<el-form label-width="70px" style="margin-top: 12px">
|
||||
<el-form-item label="变动值">
|
||||
<el-input-number v-model="adjustAmount" :min="-100000" :max="100000" />
|
||||
<span class="adjust-hint">正=赠送 负=扣减</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="原因"><el-input v-model="adjustReason" placeholder="如:活动赠送/异常补偿" /></el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="adjustDlg = false">取消</el-button>
|
||||
<el-button type="primary" @click="doAdjust">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户订单 -->
|
||||
<el-dialog v-model="ordersDlg" :title="(ordersUser?.nickName || '用户') + '的订单'" width="min(520px, 94%)" style="max-width: 520px">
|
||||
<el-table :data="ordersList" stripe v-loading="ordersLoading" size="small">
|
||||
<el-table-column prop="orderNo" label="订单号" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="productName" label="商品" width="100" />
|
||||
<el-table-column label="金额" width="60"><template #default="{ row }">"¥" + row.amount</template></el-table-column>
|
||||
<el-table-column label="状态" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 'paid' ? 'success' : row.status === 'refunded' ? 'danger' : 'warning'" size="small">
|
||||
{{ row.status === 'paid' ? '已支付' : row.status === 'refunded' ? '已退款' : row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时间" width="140"><template #default="{ row }">{{ fmt(row.createdAt) }}</template></el-table-column>
|
||||
</el-table>
|
||||
<p v-if="!ordersLoading && !ordersList.length" style="text-align:center;color:#999;padding:20px 0">暂无订单</p>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 加问答额度(保留原有) -->
|
||||
<el-dialog v-model="quotaDlg" title="增加问答额度" width="min(360px, 92%)" style="max-width: 360px">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="用户">{{ quotaUser?.nickName }}</el-form-item>
|
||||
<el-form-item label="OpenID">{{ (quotaUser?.openid || '').slice(0, 16) }}…</el-form-item>
|
||||
<el-form-item label="增加次数">
|
||||
<el-input-number v-model="quotaAmount" :min="1" :max="100" />
|
||||
</el-form-item>
|
||||
@@ -44,10 +89,15 @@
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import { apiGet, apiPost } from '../api'
|
||||
|
||||
const list = ref([]), total = ref(0), page = ref(1), pageSize = 20, q = ref(''), loading = ref(false)
|
||||
const quotaDlg = ref(false), quotaUser = ref(null), quotaAmount = ref(5)
|
||||
const adjustDlg = ref(false), adjustUser = ref(null), adjustAmount = ref(100), adjustReason = ref('')
|
||||
|
||||
function fmt(t) { return t ? new Date(t).toLocaleString('zh-CN', { hour12: false }) : '—' }
|
||||
|
||||
function search() { page.value = 1; load() }
|
||||
async function load() {
|
||||
loading.value = true
|
||||
@@ -57,6 +107,42 @@ async function load() {
|
||||
total.value = r.pagination?.total || 0
|
||||
} finally { loading.value = false }
|
||||
}
|
||||
|
||||
// 调整星尘
|
||||
function openAdjust(row) {
|
||||
adjustUser.value = row
|
||||
adjustAmount.value = 100
|
||||
adjustReason.value = ''
|
||||
adjustDlg.value = true
|
||||
}
|
||||
async function doAdjust() {
|
||||
if (!adjustUser.value) return
|
||||
try {
|
||||
await apiPost('/api/admin/vpay/adjust', {
|
||||
openid: adjustUser.value.openid,
|
||||
amount: adjustAmount.value,
|
||||
reason: adjustReason.value || '管理员调整',
|
||||
})
|
||||
ElMessage.success(`已${adjustAmount.value > 0 ? '赠送' : '扣减'} ${Math.abs(adjustAmount.value)} 星尘`)
|
||||
adjustDlg.value = false
|
||||
load() // 刷新列表更新余额列
|
||||
} catch (e) { ElMessage.error(e.message || '调整失败') }
|
||||
}
|
||||
|
||||
// 查看该用户的订单(弹窗展示)
|
||||
const ordersDlg = ref(false), ordersUser = ref(null), ordersList = ref([]), ordersLoading = ref(false)
|
||||
async function viewOrders(row) {
|
||||
ordersUser.value = row
|
||||
ordersDlg.value = true
|
||||
ordersLoading.value = true
|
||||
try {
|
||||
const r = await apiGet(`/api/admin/vpay/orders?keyword=${encodeURIComponent(row.openid)}&limit=20`)
|
||||
ordersList.value = r.items || []
|
||||
} catch (e) { ordersList.value = [] }
|
||||
finally { ordersLoading.value = false }
|
||||
}
|
||||
|
||||
// 加问答额度(保留原有)
|
||||
function openQuota(row) { quotaUser.value = row; quotaAmount.value = 5; quotaDlg.value = true }
|
||||
async function addQuota() {
|
||||
try {
|
||||
@@ -65,10 +151,18 @@ async function addQuota() {
|
||||
quotaDlg.value = false
|
||||
} catch (e) { ElMessage.error(e.message || '操作失败') }
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page { background: #fff; border-radius: 12px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,.06); }
|
||||
.toolbar { display: flex; gap: 8px; margin-bottom: 12px; }
|
||||
.adjust-user-info {
|
||||
display: flex; align-items: center; gap: 12px;
|
||||
background: #f8f9fb; border-radius: 8px; padding: 10px 14px;
|
||||
}
|
||||
.adjust-user-info b { font-size: 15px; color: #1f2333; }
|
||||
.adjust-user-info span { font-size: 13px; color: #5b5ff8; font-weight: 600; }
|
||||
.adjust-hint { margin-left: 8px; font-size: 11px; color: #999; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user