diff --git a/pages-user/orders/detail.vue b/pages-user/orders/detail.vue
index 50dae82..e521592 100644
--- a/pages-user/orders/detail.vue
+++ b/pages-user/orders/detail.vue
@@ -184,20 +184,6 @@
算法版本
{{ receipt.algo_version }}
-
- 服务端种子哈希
-
- {{ receipt.server_seed_hash }}
- 复制
-
-
-
- 子种子
-
- {{ receipt.server_sub_seed }}
- 复制
-
-
客户端种子
{{ receipt.client_seed }}
@@ -219,6 +205,11 @@
🔒
以上数据可用于验证抽奖结果的公正性
+
+
+ 📋
+ 复制验证凭据
+
@@ -445,6 +436,92 @@ function showProofHelp() {
showCancel: false
})
}
+
+// 导出验证凭据JSON
+function exportReceipt() {
+ if (!order.value || !order.value.draw_receipts || order.value.draw_receipts.length === 0) {
+ uni.showToast({ title: '无抽奖凭据', icon: 'none' })
+ return
+ }
+
+ // 构建验证凭据JSON
+ const receipts = order.value.draw_receipts.map((r, idx) => {
+ // 解析items_snapshot
+ let weightsStr = ''
+ let rewardsStr = ''
+ let salt = ''
+ let randValue = 0
+
+ if (r.items_snapshot) {
+ try {
+ const snapshot = typeof r.items_snapshot === 'string'
+ ? JSON.parse(r.items_snapshot)
+ : r.items_snapshot
+
+ // 从snapshot中提取salt和rand(后端存储的实际值)
+ if (snapshot.salt) {
+ salt = snapshot.salt
+ }
+ if (snapshot.rand !== undefined) {
+ randValue = snapshot.rand
+ }
+
+ // 提取并排序items
+ let items = []
+ if (Array.isArray(snapshot)) {
+ items = snapshot
+ } else if (snapshot.items && Array.isArray(snapshot.items)) {
+ items = snapshot.items
+ }
+
+ if (items.length > 0) {
+ // 必须按ID排序以匹配后端计算逻辑
+ items.sort((a, b) => {
+ const idA = Number(a.id || a.ID || 0)
+ const idB = Number(b.id || b.ID || 0)
+ return idA - idB
+ })
+
+ weightsStr = items.map(item => `${item.id || item.ID}:${item.weight || item.Weight || item.count || 1}`).join(',')
+ rewardsStr = items.map(item => `${item.id || item.ID}:${item.count || item.Count || 1}`).join(',')
+ }
+ } catch (e) {
+ console.warn('items_snapshot解析失败:', e)
+ }
+ }
+
+ return {
+ mode: r.selected_index > 0 ? 'ichiban' : 'unlimited',
+ version: r.algo_version || 'v1.0',
+ seed: r.server_sub_seed || '',
+ issue_id: r.round_id || 0,
+ user_id: r.client_id || 0,
+ salt: salt, // 使用items_snapshot中的salt
+ rand_value: randValue, // 实际随机数(用于验证比对)
+ slot_index: r.selected_index || 0,
+ weights: weightsStr,
+ rewards: rewardsStr,
+ weights_total: r.weights_total || 0,
+ timestamp: r.timestamp || 0,
+ draw_index: idx + 1,
+ items_snapshot: r.items_snapshot
+ }
+ })
+
+ // 如果只有一条凭据,直接导出单个对象;否则导出数组
+ const exportData = receipts.length === 1 ? receipts[0] : receipts
+ const jsonStr = JSON.stringify(exportData, null, 2)
+
+ uni.setClipboardData({
+ data: jsonStr,
+ success: () => {
+ uni.showToast({ title: '凭据已复制', icon: 'success' })
+ },
+ fail: () => {
+ uni.showToast({ title: '复制失败', icon: 'none' })
+ }
+ })
+}