refactor(admin): drop the SPA credits asset record browser
「用户近期资产记录」卡片在 SPA 积分配置页里按用户 ID + 资产类型 + 日期查 user meta 历史,再伪装成统一账本行(entries / operation_key / ref_key)。SPA 只承载配置,运营记录归原生 用户 → 积分/余额 屏幕 (CreditsAdmin / BalanceAdmin),这条平行路径删除,不留双读或迁移。 - CmsCredits.vue: 移除卡片、表格、分页及 ledger* 状态与 formatAssetValue/loadLedger/searchLedger/resetLedger - users.js: 删除仅服务该卡片的 getCreditLog() - UserController: 删除 /assets/transactions 路由、rest_get_credits_log() 及其唯一调用方 asset_value_to_minor() - 契约测试改为断言该能力不得回归 points_record / balance_record 本身保留,前端账本与原生后台仍在消费。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
324bcfdadc
commit
1c95f94bca
4 files changed
+15
-179
No files matched your search
@@ -27,8 +27,4 @@ export const usersApiMethods = {
|
||||
adjustUserCredits(id, asset, delta, remark) {
|
||||
return this.request(`/assets/accounts/${id}/adjust`, { method: 'POST', body: JSON.stringify({ asset, delta, remark }) })
|
||||
},
|
||||
getCreditLog(params = {}) {
|
||||
const qs = new URLSearchParams(params).toString()
|
||||
return this.request('/assets/transactions' + (qs ? `?${qs}` : ''))
|
||||
},
|
||||
}
|
||||
@@ -23,33 +23,6 @@
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<n-card title="用户近期资产记录" class="aksrt-section-card">
|
||||
<n-space vertical :size="12">
|
||||
<n-space wrap>
|
||||
<n-input v-model:value="ledgerFilters.user_id" placeholder="用户 ID" clearable style="width: 130px" />
|
||||
<n-select v-model:value="ledgerFilters.asset" :options="assetOptions" placeholder="资产" style="width: 130px" />
|
||||
<n-input v-model:value="ledgerFilters.date_from" type="date" placeholder="开始日期" style="width: 160px" />
|
||||
<n-input v-model:value="ledgerFilters.date_to" type="date" placeholder="结束日期" style="width: 160px" />
|
||||
<n-button type="primary" :loading="ledgerLoading" @click="searchLedger">查询</n-button>
|
||||
<n-button @click="resetLedger">重置</n-button>
|
||||
</n-space>
|
||||
<n-data-table
|
||||
:columns="ledgerColumns"
|
||||
:data="ledgerRows"
|
||||
:loading="ledgerLoading"
|
||||
:row-key="row => row.id"
|
||||
:scroll-x="1100"
|
||||
size="small"
|
||||
/>
|
||||
<n-pagination
|
||||
v-model:page="ledgerPage"
|
||||
:page-count="ledgerPageCount"
|
||||
:page-size="10"
|
||||
@update:page="loadLedger"
|
||||
/>
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header"><h3>每日签到</h3></div>
|
||||
<n-form :model="cfg.daily_signin" label-placement="left" label-width="200" class="aksrt-form">
|
||||
@@ -162,79 +135,6 @@ const cfg = reactive({
|
||||
})
|
||||
const streakJson = ref('{}')
|
||||
const saving = ref(false)
|
||||
const ledgerLoading = ref(false)
|
||||
const ledgerRows = ref([])
|
||||
const ledgerPage = ref(1)
|
||||
const ledgerPageCount = ref(1)
|
||||
const ledgerFilters = reactive({
|
||||
user_id: '',
|
||||
asset: 'points',
|
||||
date_from: '',
|
||||
date_to: '',
|
||||
})
|
||||
const assetOptions = [
|
||||
{ label: '积分', value: 'points' },
|
||||
{ label: '余额', value: 'balance' },
|
||||
]
|
||||
const ledgerColumns = [
|
||||
{ title: '类型', key: 'reason', width: 150 },
|
||||
{ title: '订单号', key: 'ref_key', width: 200 },
|
||||
{ title: '变动 / 变动后', key: 'delta_label', width: 190 },
|
||||
{ title: '说明', key: 'remark', width: 240, ellipsis: { tooltip: true } },
|
||||
{ title: '时间', key: 'created_at', width: 170 },
|
||||
]
|
||||
|
||||
function formatAssetValue(asset, value) {
|
||||
const raw = Number(value ?? 0)
|
||||
if (!Number.isFinite(raw)) return asset === 'balance' ? '0.00' : '0'
|
||||
if (asset !== 'balance') return String(raw)
|
||||
const negative = raw < 0
|
||||
const digits = String(Math.abs(Math.trunc(raw))).padStart(3, '0')
|
||||
const whole = digits.slice(0, -2).replace(/^0+(?=\d)/, '')
|
||||
return (negative ? '-' : '') + whole + '.' + digits.slice(-2)
|
||||
}
|
||||
|
||||
async function loadLedger() {
|
||||
ledgerLoading.value = true
|
||||
try {
|
||||
if (!/^\d+$/.test(String(ledgerFilters.user_id).trim())) {
|
||||
message.warning('请输入用户 ID 后查询该用户近期记录')
|
||||
return
|
||||
}
|
||||
const params = { page: ledgerPage.value, per_page: 10 }
|
||||
Object.entries(ledgerFilters).forEach(([key, value]) => {
|
||||
if (value !== null && String(value).trim() !== '') params[key] = value
|
||||
})
|
||||
const response = await api.getCreditLog(params)
|
||||
const data = response?.data || response || {}
|
||||
ledgerRows.value = (data.items || []).map((row) => {
|
||||
const entries = Array.isArray(row.entries) ? row.entries : []
|
||||
const entry = entries[0] || {}
|
||||
return {
|
||||
...row,
|
||||
delta_label: `${formatAssetValue(entry.asset, entry.delta)} / ${formatAssetValue(entry.asset, entry.balance_after)}`,
|
||||
remark: row.remark || '—',
|
||||
}
|
||||
})
|
||||
ledgerPageCount.value = Math.max(1, Math.ceil(Number(data.total || 0) / Number(data.per_page || 10)))
|
||||
} catch (e) {
|
||||
message.error(e.message || '加载资产记录失败')
|
||||
} finally {
|
||||
ledgerLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function searchLedger() {
|
||||
ledgerPage.value = 1
|
||||
loadLedger()
|
||||
}
|
||||
|
||||
function resetLedger() {
|
||||
Object.assign(ledgerFilters, { user_id: '', asset: 'points', date_from: '', date_to: '' })
|
||||
ledgerRows.value = []
|
||||
ledgerPage.value = 1
|
||||
ledgerPageCount.value = 1
|
||||
}
|
||||
|
||||
async function loadCfg() {
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user