diff --git a/frontend/src/components/account/AccountTable.vue b/frontend/src/components/account/AccountTable.vue index 6818a99..79b8a18 100644 --- a/frontend/src/components/account/AccountTable.vue +++ b/frontend/src/components/account/AccountTable.vue @@ -5,6 +5,11 @@ import { useAccounts } from '@/composables/useAccounts' import { useProducts } from '@/composables/useProducts' import type { Product } from '@/composables/useProducts' import { useActivity } from '@/composables/useActivity' +import { useToast } from '@/composables/useToast' +import { + QueryXiaodianAccountExchangeRecords, + QueryXiaodianExchangeRecords +} from '@wails/go/app/App' const { accounts, @@ -23,11 +28,14 @@ const { setAccountProduct } = useAccounts() -const { products, selectedProductName } = useProducts() +const { products, selectedProductId, selectedProductName, selectProduct, clearSelection } = useProducts() const { currentActivity } = useActivity() +const { showToast } = useToast() const isXiaodian = computed(() => currentActivity.value?.id === 'xiaodian') const productFilterMap = ref>({}) const qrImage = ref('') +const recordsModal = ref<{ accountName: string; loading: boolean; error: string; records: any[] } | null>(null) +const exchangeLookup = ref<{ productId: string; productName: string; loading: boolean; results: Record } | null>(null) watch(xiaodianQRCode, async (value) => { qrImage.value = '' @@ -38,6 +46,10 @@ watch(xiaodianQRCode, async (value) => { } }) +watch(selectedProductId, () => { + exchangeLookup.value = null +}) + const roleChannel = (type?: string) => type === 'wx' ? '微信' : type === 'qq' ? '手Q' : (type || '') const handleBind = async () => { @@ -79,6 +91,54 @@ const filteredAccountProducts = (accountName: string) => { return matched } +const selectedLookupProduct = computed(() => + products.value.find(product => product.commodityId === selectedProductId.value) +) + +const handleLookupProductChange = (event: Event) => { + const productID = (event.target as HTMLSelectElement).value + const product = products.value.find(item => item.commodityId === productID) + if (product) { + selectProduct(product.commodityId, product.commodityName) + } else { + clearSelection() + } +} + +const querySelectedExchangeRecords = async () => { + if (!selectedLookupProduct.value) { + showToast('提示', '请先选择要查询的商品', 'warn') + return + } + + const { commodityId, commodityName } = selectedLookupProduct.value + exchangeLookup.value = { productId: commodityId, productName: commodityName, loading: true, results: {} } + try { + const result = await QueryXiaodianExchangeRecords(commodityId, commodityName) + if (!exchangeLookup.value || exchangeLookup.value.productId !== commodityId) return + exchangeLookup.value.loading = false + exchangeLookup.value.results = result.results || {} + if (!result.success) { + showToast('查询失败', result.error || '兑换记录接口未返回成功', 'error') + return + } + const matched = Object.values(result.results || {}).filter((item: any) => item.success && item.matched).length + const failed = Object.values(result.results || {}).filter((item: any) => !item.success).length + showToast('查询完成', `${commodityName}:${matched} 个账号有兑换记录${failed ? `,${failed} 个查询失败` : ''}`, failed ? 'warn' : 'success') + } catch (e: any) { + if (exchangeLookup.value?.productId === commodityId) exchangeLookup.value.loading = false + showToast('查询失败', e?.message || '兑换记录查询失败', 'error') + } +} + +const getLookupResult = (accountName: string) => exchangeLookup.value?.results[accountName] + +const getMatchedRecord = (accountName: string) => { + const lookup = getLookupResult(accountName) + if (!lookup?.matched || !exchangeLookup.value) return null + return lookup.records?.find((record: any) => record.commodityId === exchangeLookup.value?.productId) || null +} + // 状态信息计算 const getStatusInfo = (name: string, selected: boolean) => { const st = statusMap.value[name] @@ -115,6 +175,41 @@ const getResultMessage = (name: string) => { if (!msg) return '-' return msg.length > 46 ? msg.slice(0, 46) + '...' : msg } + +const formatTime = (value: string) => value ? value.replace('T', ' ') : '-' + +const orderStatus = (status: string) => { + const labels: Record = { + '0': { text: '待支付', cls: 'order-pending' }, + '1': { text: '处理中', cls: 'order-pending' }, + '2': { text: '已支付', cls: 'order-processing' }, + '3': { text: '已完成', cls: 'order-complete' }, + '4': { text: '已取消', cls: 'order-cancelled' }, + '5': { text: '已退款', cls: 'order-cancelled' } + } + return labels[status] || { text: status ? `状态 ${status}` : '未知', cls: 'order-unknown' } +} + +const openExchangeRecords = async (accountName: string) => { + recordsModal.value = { accountName, loading: true, error: '', records: [] } + try { + const result = await QueryXiaodianAccountExchangeRecords(accountName) + if (!recordsModal.value || recordsModal.value.accountName !== accountName) return + recordsModal.value.loading = false + recordsModal.value.error = result.error || '' + recordsModal.value.records = result.records || [] + if (result.error) showToast('查询兑换记录失败', result.error, 'error') + } catch (e: any) { + if (!recordsModal.value || recordsModal.value.accountName !== accountName) return + recordsModal.value.loading = false + recordsModal.value.error = e?.message || '查询失败' + showToast('查询兑换记录失败', recordsModal.value.error, 'error') + } +} + +const closeExchangeRecords = () => { + recordsModal.value = null +}