diff --git a/backend/internal/handler/merchant.go b/backend/internal/handler/merchant.go index 0725b9a..28b16c1 100644 --- a/backend/internal/handler/merchant.go +++ b/backend/internal/handler/merchant.go @@ -204,7 +204,9 @@ func (h *MerchantHandler) GetWallet(c *gin.Context) { func (h *MerchantHandler) ListWalletLedger(c *gin.Context) { page, size := pageParams(c) - list, total, err := h.fulfillmentSvc.ListWalletLedger(middleware.GetMerchantID(c), page, size) + referenceNo := c.Query("reference_no") + entryType := c.Query("type") + list, total, err := h.fulfillmentSvc.ListWalletLedger(middleware.GetMerchantID(c), page, size, referenceNo, entryType) if err != nil { response.ServerError(c, err.Error()) return diff --git a/backend/internal/service/fulfillment.go b/backend/internal/service/fulfillment.go index 748e389..6788105 100644 --- a/backend/internal/service/fulfillment.go +++ b/backend/internal/service/fulfillment.go @@ -694,9 +694,15 @@ func (s *FulfillmentService) GetWallet(merchantID uint) (*model.WalletAccount, e return &wallet, nil } -func (s *FulfillmentService) ListWalletLedger(merchantID uint, page, size int) ([]model.WalletLedgerEntry, int64, error) { +func (s *FulfillmentService) ListWalletLedger(merchantID uint, page, size int, referenceNo, entryType string) ([]model.WalletLedgerEntry, int64, error) { page, size = normalizePage(page, size) tx := s.db.Model(&model.WalletLedgerEntry{}).Where("merchant_id = ?", merchantID) + if referenceNo != "" { + tx = tx.Where("reference_no LIKE ?", "%"+referenceNo+"%") + } + if entryType != "" { + tx = tx.Where("type = ?", entryType) + } var total int64 if err := tx.Count(&total).Error; err != nil { return nil, 0, err diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d0f6dd8..ab99453 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -40,7 +40,7 @@ function AppRoutes() { } /> } /> } /> - } /> + } /> } /> } /> } /> diff --git a/frontend/src/layouts/MainLayout.tsx b/frontend/src/layouts/MainLayout.tsx index 27e25ac..a8aa4ac 100644 --- a/frontend/src/layouts/MainLayout.tsx +++ b/frontend/src/layouts/MainLayout.tsx @@ -78,7 +78,7 @@ const adminSections: SidebarSection[] = [ key: 'funds', label: '资金', icon: , - children: [{ key: 'merchant-wallet', label: '钱包', path: '/merchant-wallet' }], + children: [{ key: 'merchant-wallet', label: '积分明细', path: '/merchant-wallet' }], }, { key: 'open-api', @@ -116,7 +116,7 @@ const merchantSections: SidebarSection[] = [ key: 'funds', label: '资金', icon: , - children: [{ key: 'merchant-wallet', label: '钱包', path: '/merchant-wallet' }], + children: [{ key: 'merchant-wallet', label: '积分明细', path: '/merchant-wallet' }], }, { key: 'staff', diff --git a/frontend/src/pages/MerchantCenter.tsx b/frontend/src/pages/MerchantCenter.tsx index a64babe..16eda37 100644 --- a/frontend/src/pages/MerchantCenter.tsx +++ b/frontend/src/pages/MerchantCenter.tsx @@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { useLocation } from 'react-router-dom' import { Button, + Card, Descriptions, Form, Input, @@ -112,6 +113,7 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer const [testOrderResult, setTestOrderResult] = useState(null) const [productForm] = Form.useForm() const [walletForm] = Form.useForm() + const [walletFilterForm] = Form.useForm() const [apiClientForm] = Form.useForm() const [callbackForm] = Form.useForm() const [memberForm] = Form.useForm() @@ -192,11 +194,12 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer page = ledger.page, size = ledger.size, role = merchantRole, + filters?: { reference_no?: string; type?: string }, ) => { const walletData = await merchantApi.wallet() setWallet(walletData) if (role === 'owner' || role === 'finance') { - const ledgerData = await merchantApi.ledger({ page, size }) + const ledgerData = await merchantApi.ledger({ page, size, ...filters }) setLedger(ledgerData) } else { setLedger({ list: [], total: 0, page, size }) @@ -337,6 +340,19 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer } } + const handleWalletFilter = async () => { + const values = await walletFilterForm.validateFields() + loadWallet(1, ledger.size, merchantRole, { + reference_no: values.reference_no || undefined, + type: values.type || undefined, + }) + } + + const handleWalletFilterReset = () => { + walletFilterForm.resetFields() + loadWallet(1, ledger.size, merchantRole, {}) + } + const openTestOrderCreate = () => { testOrderForm.resetFields() testOrderForm.setFieldsValue({ @@ -515,13 +531,13 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer ] const ledgerColumns: ColumnsType = [ - { title: '流水号', dataIndex: 'entry_no', width: 210, ellipsis: true }, - { title: '类型', dataIndex: 'type', width: 90, render: ledgerTypeTag }, - { title: '金额', dataIndex: 'amount', width: 110, render: moneyWithSign }, - { title: '余额', dataIndex: 'balance_after', width: 110, render: money }, - { title: '关联单号', dataIndex: 'reference_no', ellipsis: true }, - { title: '备注', dataIndex: 'note', ellipsis: true, render: (v) => v || '-' }, - { title: '时间', dataIndex: 'created_at', width: 180, render: formatDateTime }, + { title: '流水号', dataIndex: 'entry_no', width: 300, render: (v) => {v} }, + { title: '类型', dataIndex: 'type', width: 80, render: ledgerTypeTag }, + { title: '金额', dataIndex: 'amount', width: 120, render: moneyWithSign }, + { title: '余额', dataIndex: 'balance_after', width: 120, render: money }, + { title: '关联单号', dataIndex: 'reference_no', width: 200, ellipsis: true, render: (v) => v ? {v} : '-' }, + { title: '备注', dataIndex: 'note', width: 150, ellipsis: { showTitle: false }, render: (v) => {v || '-'} }, + { title: '时间', dataIndex: 'created_at', width: 170, render: formatDateTime }, ] const apiClientColumns: ColumnsType = [ @@ -612,14 +628,15 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer const walletContent = ( - - + + {money(wallet?.available_balance ?? 0)} {money(wallet?.frozen_balance ?? 0)} {wallet?.currency || 'POINT'} {canFinance && ( )} + {canFinance && ( + +
+ + + + + + + + + + + + +
+
+ )} {canFinance ? ( { + const values = walletFilterForm.getFieldsValue() + loadWallet(page, size, merchantRole, { + reference_no: values.reference_no || undefined, + type: values.type || undefined, + }) + })} /> ) : ( 当前角色可查看余额,钱包流水仅财务或负责人可见。 @@ -705,9 +752,11 @@ export default function MerchantCenter({ fixedTab, title = '商户中心' }: Mer {title} - - {merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'} - + {!fixedTab && ( + + {merchant ? `${merchant.name} / ${merchant.code}` : '加载中'} · {merchantRole ? roleText(merchantRole) : '-'} + + )}