Browse Source

后台重要数据样式修改

pxb 4 weeks ago
parent
commit
a7e4f8862a

+ 0 - 12
src/router/index.js

@@ -376,12 +376,6 @@ export const constantRoutes = [
         name: 'DigitalNumberManage',
         name: 'DigitalNumberManage',
         meta: { title: '号码管理' }
         meta: { title: '号码管理' }
       },
       },
-      {
-        path: 'DigitalDetail',
-        component: () => import('@/views/Digital/detail/index'),
-        name: 'DigitalDetail',
-        meta: { title: '详情' }
-      },
       {
       {
         path: 'MacauMarkSix',
         path: 'MacauMarkSix',
         component: () => import('@/views/Digital/MacauMarkSix/index'),
         component: () => import('@/views/Digital/MacauMarkSix/index'),
@@ -529,12 +523,6 @@ export const constantRoutes = [
         name: 'EventErrorList',
         name: 'EventErrorList',
         meta: { title: '异常赛事' }
         meta: { title: '异常赛事' }
       },
       },
-      {
-        path: 'EventDetail',
-        component: () => import('@/views/orderManage/EventDetail/index.vue'),
-        name: 'EventDetail',
-        meta: { title: '赛事详情' }
-      },
       {
       {
         path: 'orderDetail',
         path: 'orderDetail',
         component: () => import('@/views/orderManage/Detail/index.vue'),
         component: () => import('@/views/orderManage/Detail/index.vue'),

+ 306 - 40
src/views/A_NewPage/Finance/TopUpList/index.vue

@@ -39,7 +39,8 @@
         </el-form-item>
         </el-form-item>
         <el-form-item label="状态">
         <el-form-item label="状态">
           <el-select v-model="topupSearch.status" placeholder="请选择" clearable>
           <el-select v-model="topupSearch.status" placeholder="请选择" clearable>
-            <el-option v-for="item in topupStatusOpt" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            <el-option v-for="item in topupStatusOpt" :key="item.value" :label="item.label"
+              :value="item.value"></el-option>
           </el-select>
           </el-select>
         </el-form-item>
         </el-form-item>
         <el-form-item label="类型">
         <el-form-item label="类型">
@@ -56,47 +57,172 @@
     </div>
     </div>
 
 
     <div v-show="activeTab === 'payment'">
     <div v-show="activeTab === 'payment'">
-      <YMTable
-        ref="paymentTable"
-        :table-key="1"
-        :index="true"
-        :selection="false"
-        :table-options="paymentTableOptions"
-        :edit-form="paymentEditForm"
-        :edit-config="paymentEditConfig"
-        :columns="paymentColumns"
-        :rows-actions="paymentRowsActions"
-        :show-summary="false"
-        :apis="paymentApis"
-        :actionsWidth="120"
-        :alertTip="paymentAlertTip"
-        :custom-style="{ height: 'calc(100vh - 200px)' }"
-        @onResponse="onPaymentResponse"
-      />
+      <YMTable ref="paymentTable" :table-key="1" :index="true" :selection="false" :table-options="paymentTableOptions"
+        :edit-form="paymentEditForm" :edit-config="paymentEditConfig" :columns="paymentColumns"
+        :rows-actions="paymentRowsActions" :show-summary="false" :apis="paymentApis" :actionsWidth="160"
+        :alertTip="paymentAlertTip" :custom-style="{ height: 'calc(100vh - 200px)' }" @onResponse="onPaymentResponse">
+        <!-- 金额列插槽 -->
+        <template #amount="{ row }">
+          <div style="color: #18C80A;">
+            <template v-if="row.exchange_rate !== undefined">
+              <div>{{ formatNumber(row.amount) }} USDT</div>
+              <div>{{ formatNumber(row.amount * row.exchange_rate) }} RMB</div>
+            </template>
+            <template v-else>
+              {{ row.amount != null ? row.amount : '--' }}
+            </template>
+          </div>
+        </template>
+        <!-- 手续费插槽 -->
+        <template #fee="{ row }">
+          <span style="color: #18C80A;">
+            {{ row.fee != null ? formatNumber(row.fee) : '--' }}
+          </span>
+        </template>
+        <!-- 渠道插槽 -->
+        <template #bank_name="{ row }">
+          <span style="color: #0B17FF;">
+            {{ row.bank_name || '--' }}
+          </span>
+        </template>
+        <!-- 状态插槽 -->
+        <template #status="{ row }">
+          <span :style="{
+            color: (formatPaymentStatus(row).includes('超时') ? '#F56C6C' :
+              row.status === 2 ? '#67C23A' :
+                row.status === 3 ? '#F56C6C' :
+                  row.status === 1 ? '#409EFF' :
+                    row.status === 0 ? '#E6A23C' :
+                      '#606266')
+          }">
+            {{ formatPaymentStatus(row) }}
+          </span>
+        </template>
+      </YMTable>
     </div>
     </div>
 
 
     <div v-show="activeTab === 'topup'">
     <div v-show="activeTab === 'topup'">
-      <YMTable
-        ref="topupTable"
-        :table-key="2"
-        :index="true"
-        :selection="false"
-        :table-options="topupTableOptions"
-        :edit-form="topupEditForm"
-        :edit-config="topupEditConfig"
-        :columns="topupColumns"
-        :actions-width="120"
-        :rows-actions="topupRowsActions"
-        :show-summary="false"
-        :apis="topupApis"
-        :alertTip="topupAlertTip"
-        :custom-style="{ height: 'calc(100vh - 200px)' }"
-        @onResponse="onTopupResponse"
-      />
+      <YMTable ref="topupTable" :table-key="2" :index="true" :selection="false" :table-options="topupTableOptions"
+        :edit-form="topupEditForm" :edit-config="topupEditConfig" :columns="topupColumns" :actions-width="160"
+        :rows-actions="topupRowsActions" :show-summary="false" :apis="topupApis" :alertTip="topupAlertTip"
+        :custom-style="{ height: 'calc(100vh - 200px)' }" @onResponse="onTopupResponse">
+        <!-- 金额列插槽 -->
+        <template #amount="{ row }">
+          <div style="color: #18C80A;">
+            <template v-if="row.exchange_rate !== undefined">
+              <div>{{ formatNumber(row.amount) }} USDT</div>
+              <div>{{ formatNumber(row.amount * row.exchange_rate) }} RMB</div>
+            </template>
+            <template v-else>
+              {{ row.amount != null ? row.amount : '--' }}
+            </template>
+          </div>
+        </template>
+        <!-- 费率插槽 -->
+        <template #exchange_rate="{ row }">
+          <span style="color: #18C80A;">
+            {{ row.exchange_rate != null ? formatNumber(row.exchange_rate, 2) : '--' }}
+          </span>
+        </template>
+        <!-- 币种插槽 -->
+        <template #coin="{ row }">
+          <span style="color: #0B17FF;">
+            {{ row.coin || '--' }}
+          </span>
+        </template>
+        <!-- 状态插槽 -->
+        <template #status="{ row }">
+          <span :style="{
+            color: row.status === 1 ? '#67C23A' :
+              row.status === 2 ? '#F56C6C' :
+                row.status === 3 ? '#909399' :
+                  row.status === 0 ? '#E6A23C' :
+                    '#606266'
+          }">
+            {{(topupStatusOpt.find(item => item.value === row.status) || { label: '--' }).label}}
+          </span>
+        </template>
+      </YMTable>
     </div>
     </div>
 
 
+    <!-- 通用空 Dialog(保留) -->
     <Dialog ref="dialog">
     <Dialog ref="dialog">
-      <template slot="content"/>
+      <template slot="content" />
+    </Dialog>
+
+    <!-- ========== Payment(RMB)查看弹窗 ========== -->
+    <Dialog ref="paymentViewDialog" :dialog-actions="{
+      width: '800px',
+      title: '充值订单详情(RMB)',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in paymentViewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 金额特殊处理 -->
+            <div v-if="field.type === 'amount'" style="color: #18C80A; font-size: 15px;" v-html="field.value"></div>
+            <!-- 手续费 -->
+            <div v-else-if="field.type === 'fee'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <!-- 渠道 -->
+            <div v-else-if="field.type === 'bank_name'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}</div>
+            <!-- 状态(含超时) -->
+            <div v-else-if="field.type === 'status'" :style="{ color: field.color || '#606266', fontSize: '15px' }">{{
+              field.value }}</div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <!-- 操作按钮(复用列表逻辑) -->
+        <div style="margin-top: 20px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 订单同步(仅当 type=1 且 status=1) -->
+          <el-button v-if="paymentViewRow && paymentViewRow.type === 1 && paymentViewRow.status === 1" type="primary"
+            size="small" @click="handlePaymentViewAction('sync')">订单同步</el-button>
+        </div>
+      </template>
+    </Dialog>
+
+    <!-- ========== Topup(USDT)查看弹窗 ========== -->
+    <Dialog ref="topupViewDialog" :dialog-actions="{
+      width: '800px',
+      title: '充值订单详情(USDT)',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in topupViewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 金额(USDT/RMB双行) -->
+            <div v-if="field.type === 'amount'" style="color: #18C80A; font-size: 15px;" v-html="field.value"></div>
+            <!-- 费率 -->
+            <div v-else-if="field.type === 'exchange_rate'" style="color: #18C80A; font-size: 15px;">{{ field.value }}
+            </div>
+            <!-- 币种 -->
+            <div v-else-if="field.type === 'coin'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}</div>
+            <!-- 状态 -->
+            <div v-else-if="field.type === 'status'" :style="{ color: field.color || '#606266', fontSize: '15px' }">{{
+              field.value }}</div>
+            <!-- 图片 -->
+            <div v-else-if="field.type === 'image'">
+              <el-image v-if="field.value" style="width: 60px; height: 60px" :src="field.value"
+                :preview-src-list="[field.value]"></el-image>
+              <span v-else style="color: #909399; font-size: 15px;">无</span>
+            </div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <!-- 操作按钮 -->
+        <div style="margin-top: 20px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 通过/驳回(仅当 status=0 且 type=2 手动) -->
+          <el-button v-if="topupViewRow && topupViewRow.status === 0 && topupViewRow.type === 2" type="primary"
+            size="small" @click="handleTopupViewAction('pass')">通过</el-button>
+          <el-button v-if="topupViewRow && topupViewRow.status === 0 && topupViewRow.type === 2" type="danger"
+            size="small" @click="handleTopupViewAction('reject')">驳回</el-button>
+        </div>
+      </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
 </template>
 </template>
@@ -131,7 +257,7 @@ export default {
           options: [
           options: [
             { label: '会员ID', value: ['member_id'] },
             { label: '会员ID', value: ['member_id'] },
             { label: '用户名称', value: ['username'] },
             { label: '用户名称', value: ['username'] },
-            { label: '异常信息', vShow: (row) => row?.user_admin_note ? true : false, value: ['user_admin_note'] }
+            { label: '备注', vShow: (row) => row?.user_admin_note ? true : false, value: ['user_admin_note'] }
           ]
           ]
         },
         },
         { label: '订单号', prop: 'order_no' },
         { label: '订单号', prop: 'order_no' },
@@ -144,6 +270,15 @@ export default {
         { label: '创建时间', prop: 'created_at' }
         { label: '创建时间', prop: 'created_at' }
       ],
       ],
       paymentRowsActions: [
       paymentRowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.paymentViewRow = { ...row };
+            this.$refs.paymentViewDialog.open();
+          }
+        },
         {
         {
           key: 'check',
           key: 'check',
           label: '订单同步',
           label: '订单同步',
@@ -204,7 +339,7 @@ export default {
           options: [
           options: [
             { label: '会员ID', value: ['member.member_id'] },
             { label: '会员ID', value: ['member.member_id'] },
             { label: '用户名称', value: ['member.username'] },
             { label: '用户名称', value: ['member.username'] },
-            { label: '异常信息', vShow: (row) => row?.member.admin_note ? true : false, value: ['member.admin_note'] }
+            { label: '备注', vShow: (row) => row?.member.admin_note ? true : false, value: ['member.admin_note'] }
           ]
           ]
         },
         },
         { label: '链接类型', prop: 'net' },
         { label: '链接类型', prop: 'net' },
@@ -235,6 +370,15 @@ export default {
         { label: '创建时间', prop: 'created_at' }
         { label: '创建时间', prop: 'created_at' }
       ],
       ],
       topupRowsActions: [
       topupRowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.topupViewRow = { ...row };
+            this.$refs.topupViewDialog.open();
+          }
+        },
         {
         {
           key: 'no',
           key: 'no',
           label: '驳回',
           label: '驳回',
@@ -289,7 +433,77 @@ export default {
       topupEditConfig: {
       topupEditConfig: {
         addTip: '注:备注',
         addTip: '注:备注',
         editTip: '注:备注'
         editTip: '注:备注'
+      },
+
+      // ---------- 查看弹窗数据 ----------
+      paymentViewRow: null,
+      topupViewRow: null,
+    }
+  },
+  computed: {
+    // Payment 查看字段
+    paymentViewFields() {
+      if (!this.paymentViewRow) return []
+      const row = this.paymentViewRow
+      // 处理金额显示(可能双行)
+      let amountHtml = row.amount != null ? row.amount : '--'
+      if (row.exchange_rate !== undefined) {
+        amountHtml = `${this.formatNumber(row.amount)} USDT<br/>${this.formatNumber(row.amount * row.exchange_rate)} RMB`
       }
       }
+      // 状态颜色
+      const statusText = this.formatPaymentStatus(row)
+      let statusColor = '#606266'
+      if (statusText.includes('超时')) statusColor = '#F56C6C'
+      else if (row.status === 2) statusColor = '#67C23A'
+      else if (row.status === 3) statusColor = '#F56C6C'
+      else if (row.status === 1) statusColor = '#409EFF'
+      else if (row.status === 0) statusColor = '#E6A23C'
+
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '订单号', prop: 'order_no', value: row.order_no || '--' },
+        { label: '金额', prop: 'amount', value: amountHtml, type: 'amount' },
+        { label: '渠道', prop: 'bank_name', value: row.bank_name || '--', type: 'bank_name' },
+        { label: '手续费', prop: 'fee', value: row.fee != null ? this.formatNumber(row.fee) : '--', type: 'fee' },
+        { label: '状态', prop: 'status', value: statusText, type: 'status', color: statusColor },
+        { label: '备注', prop: 'remark', value: row.remark || '--' },
+        { label: '更新时间', prop: 'updated_at', value: row.updated_at || '--' },
+        { label: '创建时间', prop: 'created_at', value: row.created_at || '--' },
+      ]
+    },
+    // Topup 查看字段
+    topupViewFields() {
+      if (!this.topupViewRow) return []
+      const row = this.topupViewRow
+      const amount = row.amount || 0
+      const exchangeRate = row.exchange_rate || 1
+      const convertedAmount = amount * exchangeRate
+      const amountHtml = `${this.formatNumber(amount)} USDT<br/>${this.formatNumber(convertedAmount)} RMB`
+
+      let statusColor = '#606266'
+      if (row.status === 1) statusColor = '#67C23A'
+      else if (row.status === 2) statusColor = '#F56C6C'
+      else if (row.status === 3) statusColor = '#909399'
+      else if (row.status === 0) statusColor = '#E6A23C'
+
+      const statusLabel = this.topupStatusOpt.find(item => item.value === row.status)?.label || '--'
+      const typeLabel = row.type === 1 ? '自动' : row.type === 2 ? '手动' : '其他'
+
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '链接类型', prop: 'net', value: row.net || '--' },
+        { label: '币种', prop: 'coin', value: row.coin || '--', type: 'coin' },
+        { label: '费率', prop: 'exchange_rate', value: row.exchange_rate != null ? this.formatNumber(row.exchange_rate, 2) : '--', type: 'exchange_rate' },
+        { label: '充值数量', prop: 'amount', value: amountHtml, type: 'amount' },
+        { label: '充值地址(平台地址)', prop: 'to_address', value: row.to_address || '--' },
+        { label: '状态', prop: 'status', value: statusLabel, type: 'status', color: statusColor },
+        { label: '图片', prop: 'image', value: row.image, type: 'image' },
+        { label: '类型', prop: 'type', value: typeLabel },
+        { label: '更新时间', prop: 'updated_at', value: row.updated_at || '--' },
+        { label: '创建时间', prop: 'created_at', value: row.created_at || '--' },
+      ]
     }
     }
   },
   },
   mounted() {
   mounted() {
@@ -406,6 +620,56 @@ export default {
     formatNumber(num, decimals = 2) {
     formatNumber(num, decimals = 2) {
       if (isNaN(num)) return '0.00'
       if (isNaN(num)) return '0.00'
       return Number(num).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
       return Number(num).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
+    },
+
+    // ---------- Payment 查看弹窗操作 ----------
+    handlePaymentViewAction(action) {
+      const row = this.paymentViewRow
+      if (!row) return
+      if (action === 'sync') {
+        this.$confirm('确定同步该订单,是否继续?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(() => {
+          paymentOrder({ id: row.id }).then((res) => {
+            this.$message({ type: 'success', message: res.msg })
+            this.onPaymentSubmit()
+            this.$refs.paymentViewDialog.close()
+          })
+        }).catch(() => { })
+      }
+    },
+
+    // ---------- Topup 查看弹窗操作 ----------
+    handleTopupViewAction(action) {
+      const row = this.topupViewRow
+      if (!row) return
+      const closeDialog = () => {
+        this.$refs.topupViewDialog.close()
+      }
+      if (action === 'pass') {
+        this.$confirm('确定通过审核?', '提示', { type: 'warning' }).then(() => {
+          verifyRecharge({ id: row.id.toString(), status: 1 }).then(() => {
+            this.onTopupSubmit()
+            this.$message({ type: 'success', message: '操作成功' })
+            closeDialog()
+          })
+        }).catch(() => { })
+      } else if (action === 'reject') {
+        this.$prompt('请输入原因', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          inputPattern: /^\S+$/,
+          inputErrorMessage: '请输入原因'
+        }).then(({ value }) => {
+          verifyRecharge({ id: row.id.toString(), status: 2, remark: value }).then(() => {
+            this.onTopupSubmit()
+            this.$message({ type: 'success', message: '操作成功' })
+            closeDialog()
+          })
+        }).catch(() => { })
+      }
     }
     }
   }
   }
 }
 }
@@ -422,10 +686,12 @@ export default {
   padding-left: 20px;
   padding-left: 20px;
   box-sizing: border-box;
   box-sizing: border-box;
 }
 }
+
 .tab-group {
 .tab-group {
-  margin-top: 3px; /* 稍微往下微调,使其与表单项在视觉上对齐 */
+  margin-top: 3px;
 }
 }
+
 .search-form {
 .search-form {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
-</style>
+</style>

+ 443 - 66
src/views/A_NewPage/Finance/WithdrawList/index.vue

@@ -17,7 +17,8 @@
         </el-form-item>
         </el-form-item>
         <el-form-item label="状态">
         <el-form-item label="状态">
           <el-select v-model="rmbSearch.status" placeholder="请选择" clearable>
           <el-select v-model="rmbSearch.status" placeholder="请选择" clearable>
-            <el-option v-for="item in rmbStatusOpt" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            <el-option v-for="item in rmbStatusOpt" :key="item.value" :label="item.label"
+              :value="item.value"></el-option>
           </el-select>
           </el-select>
         </el-form-item>
         </el-form-item>
         <el-form-item>
         <el-form-item>
@@ -36,7 +37,8 @@
         </el-form-item>
         </el-form-item>
         <el-form-item label="状态">
         <el-form-item label="状态">
           <el-select v-model="usdtSearch.status" placeholder="请选择" clearable>
           <el-select v-model="usdtSearch.status" placeholder="请选择" clearable>
-            <el-option v-for="item in usdtStatusOpt" :key="item.value" :label="item.label" :value="item.value"></el-option>
+            <el-option v-for="item in usdtStatusOpt" :key="item.value" :label="item.label"
+              :value="item.value"></el-option>
           </el-select>
           </el-select>
         </el-form-item>
         </el-form-item>
         <el-form-item>
         <el-form-item>
@@ -48,47 +50,189 @@
 
 
     <!-- 提现订单(RMB)板块 -->
     <!-- 提现订单(RMB)板块 -->
     <div v-show="activeTab === 'rmb'">
     <div v-show="activeTab === 'rmb'">
-      <YMTable
-        ref="rmbTable"
-        :table-key="1"
-        :index="true"
-        :selection="true"
-        :table-options="rmbTableOptions"
-        :edit-form="rmbEditForm"
-        :edit-config="rmbEditConfig"
-        :columns="rmbColumns"
-        :actions-width="120"
-        :rows-actions="rmbRowsActions"
-        :show-summary="false"
-        :apis="rmbApis"
-        :alertTip="rmbAlertTip"
-        :custom-style="{ height: 'calc(100vh - 150px)' }"
-        @onResponse="onRmbResponse"
-      />
+      <YMTable ref="rmbTable" :table-key="1" :index="true" :selection="true" :table-options="rmbTableOptions"
+        :edit-form="rmbEditForm" :edit-config="rmbEditConfig" :columns="rmbColumns" :actions-width="160"
+        :rows-actions="rmbRowsActions" :show-summary="false" :apis="rmbApis" :alertTip="rmbAlertTip"
+        :custom-style="{ height: 'calc(100vh - 150px)' }" @onResponse="onRmbResponse">
+        <!-- 提现金额 -->
+        <template #amount="{ row }">
+          <span style="color: #18C80A;">
+            {{ row.amount != null ? Number(row.amount).toFixed(2) : '--' }}
+          </span>
+        </template>
+
+        <!-- 手续费 -->
+        <template #fee="{ row }">
+          <span style="color: #F56C6C;">
+            {{ row.fee != null ? Number(row.fee).toFixed(2) : '--' }}
+          </span>
+        </template>
+
+        <!-- 是否加锁 -->
+        <template #is_locked="{ row }">
+          <span :style="{ color: row.is_locked === 1 ? '#F3061F' : '#18C80A' }">
+            {{ row.is_locked === 1 ? '是' : '否' }}
+          </span>
+        </template>
+
+        <!-- 状态 -->
+        <template #status="{ row }">
+          <span :style="{ color: rmbStatusColorMap[row.status] || '#606266' }">
+            {{(rmbStatusOpt.find(item => item.value === row.status) || { label: '--' }).label}}
+          </span>
+        </template>
+      </YMTable>
     </div>
     </div>
 
 
     <!-- 提现订单(USDT)板块 -->
     <!-- 提现订单(USDT)板块 -->
     <div v-show="activeTab === 'usdt'">
     <div v-show="activeTab === 'usdt'">
-      <YMTable
-        ref="usdtTable"
-        :table-key="2"
-        :index="false"
-        :selection="true"
-        :table-options="usdtTableOptions"
-        :edit-form="usdtEditForm"
-        :edit-config="usdtEditConfig"
-        :columns="usdtColumns"
-        :rows-actions="usdtRowsActions"
-        :show-summary="false"
-        :apis="usdtApis"
-        :custom-style="{ height: 'calc(100vh - 150px)' }"
-        :alertTip="usdtAlertTip"
-        @onResponse="onUsdtResponse"
-      />
+      <YMTable ref="usdtTable" :table-key="2" :index="false" :selection="true" :table-options="usdtTableOptions"
+        :edit-form="usdtEditForm" :edit-config="usdtEditConfig" :columns="usdtColumns" :rows-actions="usdtRowsActions"
+        :show-summary="false" :apis="usdtApis" :custom-style="{ height: 'calc(100vh - 150px)' }"
+        :alertTip="usdtAlertTip" @onResponse="onUsdtResponse">
+        <!-- 提现金额 -->
+        <template #amount="{ row }">
+          <span style="color: #18C80A;">
+            {{ row.amount != null ? Number(row.amount).toFixed(2) : '--' }} USDT
+          </span>
+        </template>
+
+        <!-- 手续费 -->
+        <template #service_charge="{ row }">
+          <span style="color: #F56C6C;">
+            {{ row.service_charge != null ? Number(row.service_charge).toFixed(2) : '--' }} USDT
+          </span>
+        </template>
+
+        <!-- 是否加锁 -->
+        <template #is_locked="{ row }">
+          <span :style="{ color: row.is_locked === 1 ? '#F3061F' : '#18C80A' }">
+            {{ row.is_locked === 1 ? '是' : '否' }}
+          </span>
+        </template>
+
+        <!-- 状态 -->
+        <template #status="{ row }">
+          <span :style="{ color: usdtStatusColorMap[row.status] || '#606266' }">
+            {{(usdtStatusOpt.find(item => item.value === row.status) || { label: '--' }).label}}
+          </span>
+        </template>
+
+        <!-- 费率 -->
+        <template #exchange_rate="{ row }">
+          <span style="color: #0B17FF;">
+            {{ row.exchange_rate != null ? formatNumber(row.exchange_rate, 2) : '--' }}
+          </span>
+        </template>
+
+        <!-- 提现后余额 -->
+        <template #after_balance="{ row }">
+          <span style="color: #0B17FF;">
+            {{ row.after_balance != null ? Number(row.after_balance).toFixed(2) : '--' }} RMB
+          </span>
+        </template>
+      </YMTable>
     </div>
     </div>
 
 
+    <!-- 通用空 Dialog(保留) -->
     <Dialog ref="dialog">
     <Dialog ref="dialog">
-      <template slot="content"/>
+      <template slot="content" />
+    </Dialog>
+
+    <!-- ========== RMB 查看弹窗 ========== -->
+    <Dialog ref="rmbViewDialog" :dialog-actions="{
+      width: '800px',
+      title: '提现订单详情(RMB)',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <!-- 字段展示(flex 网格) -->
+          <div v-for="field in rmbViewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 特殊字段样式 -->
+            <div v-if="field.type === 'amount'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <div v-else-if="field.type === 'fee'" style="color: #F56C6C; font-size: 15px;">{{ field.value }}</div>
+            <div v-else-if="field.type === 'is_locked'"
+              :style="{ color: field.rawValue === 1 ? '#F3061F' : '#18C80A', fontSize: '15px' }">{{ field.value }}</div>
+            <div v-else-if="field.type === 'status'"
+              :style="{ color: rmbStatusColorMap[field.rawValue] || '#606266', fontSize: '15px' }">{{ field.value }}
+            </div>
+            <div v-else-if="field.type === 'info'" style="font-size: 15px; color: #0B17FF; line-height: 1.6;"
+              v-html="field.value"></div>
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <!-- 操作按钮(复用列表逻辑) -->
+        <div style="margin-top: 20px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 上锁 -->
+          <el-button v-if="rmbViewRow && rmbViewRow.status === 0 && rmbViewRow.is_locked === 0" type="warning"
+            size="small" @click="handleRmbViewAction('lock')">上锁</el-button>
+          <!-- 解锁 -->
+          <el-button v-if="rmbViewRow && rmbViewRow.status === 0 && rmbViewRow.is_locked === 1" type="success"
+            size="small" @click="handleRmbViewAction('unlock')">解锁</el-button>
+          <!-- 通过 -->
+          <el-button v-if="rmbViewRow && rmbViewRow.status === 0 && rmbViewRow.type === 2" type="primary" size="small"
+            @click="handleRmbViewAction('pass')">通过</el-button>
+          <!-- 驳回 -->
+          <el-button v-if="rmbViewRow && rmbViewRow.status === 0 && rmbViewRow.type === 2" type="danger" size="small"
+            @click="handleRmbViewAction('reject')">驳回</el-button>
+          <!-- 备注 -->
+          <el-button type="info" size="small" @click="handleRmbViewAction('note')">备注</el-button>
+        </div>
+      </template>
+    </Dialog>
+
+    <!-- ========== USDT 查看弹窗 ========== -->
+    <Dialog ref="usdtViewDialog" :dialog-actions="{
+      width: '800px',
+      title: '提现订单详情(USDT)',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in usdtViewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 特殊字段样式 -->
+            <div v-if="field.type === 'amount'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <div v-else-if="field.type === 'service_charge'" style="color: #F56C6C; font-size: 15px;">{{ field.value }}
+            </div>
+            <div v-else-if="field.type === 'is_locked'"
+              :style="{ color: field.rawValue === 1 ? '#F3061F' : '#18C80A', fontSize: '15px' }">{{ field.value }}</div>
+            <div v-else-if="field.type === 'status'"
+              :style="{ color: usdtStatusColorMap[field.rawValue] || '#606266', fontSize: '15px' }">{{ field.value }}
+            </div>
+            <div v-else-if="field.type === 'exchange_rate'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}
+            </div>
+            <div v-else-if="field.type === 'after_balance'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}
+            </div>
+            <div v-else-if="field.type === 'to_account'" style="color: #18C80A; font-size: 15px;" v-html="field.value">
+            </div>
+            <div v-else-if="field.type === 'deduct_amount'" style="color: #E6A23C; font-size: 15px;"
+              v-html="field.value"></div>
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <!-- 操作按钮 -->
+        <div style="margin-top: 20px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 上锁 -->
+          <el-button v-if="usdtViewRow && usdtViewRow.status === 0 && usdtViewRow.is_locked === 0" type="warning"
+            size="small" @click="handleUsdtViewAction('lock')">上锁</el-button>
+          <!-- 解锁 -->
+          <el-button v-if="usdtViewRow && usdtViewRow.status === 0 && usdtViewRow.is_locked === 1" type="success"
+            size="small" @click="handleUsdtViewAction('unlock')">解锁</el-button>
+          <!-- 通过 -->
+          <el-button v-if="usdtViewRow && usdtViewRow.status === 0" type="primary" size="small"
+            @click="handleUsdtViewAction('pass')">通过</el-button>
+          <!-- 驳回 -->
+          <el-button v-if="usdtViewRow && usdtViewRow.status === 0" type="danger" size="small"
+            @click="handleUsdtViewAction('reject')">驳回</el-button>
+          <!-- 备注 -->
+          <el-button type="info" size="small" @click="handleUsdtViewAction('note')">备注</el-button>
+        </div>
+      </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
 </template>
 </template>
@@ -133,25 +277,41 @@ export default {
           options: [
           options: [
             { label: '会员ID', value: ['member_id'] },
             { label: '会员ID', value: ['member_id'] },
             { label: '用户名称', value: ['first_name'] },
             { label: '用户名称', value: ['first_name'] },
-            { label: '异常信息', vShow: (row) => row?.admin_note ? true : false, value: ['admin_note'] }
+            { label: '备注', vShow: (row) => row?.admin_note ? true : false, value: ['admin_note'] }
           ]
           ]
         },
         },
         { label: '订单号', prop: 'order_no' },
         { label: '订单号', prop: 'order_no' },
         { label: '提现金额', prop: 'amount', method: (row) => Number(row.amount)?.toFixed(2) },
         { label: '提现金额', prop: 'amount', method: (row) => Number(row.amount)?.toFixed(2) },
         {
         {
-          label: '银行卡',
+          label: '信息',
           width: '180px',
           width: '180px',
           html: true,
           html: true,
-          method: (row) => `${row?.account}(${row?.bank_name})<br/>账户:${row?.card_no} `
+          method: (row) => `<span style="color: #0B17FF;">${row.account || ''}(${row.bank_name || ''})<br/>账户:${row.card_no || ''}</span>`
         },
         },
         { label: '手续费', prop: 'fee', method: (row) => Number(row.fee)?.toFixed(2) },
         { label: '手续费', prop: 'fee', method: (row) => Number(row.fee)?.toFixed(2) },
         { label: '是否加锁', prop: 'is_locked', method: (row) => row.is_locked === 1 ? '是' : '否' },
         { label: '是否加锁', prop: 'is_locked', method: (row) => row.is_locked === 1 ? '是' : '否' },
-        { label: '状态', method: (row) => { return this.rmbStatusOpt.filter(item => item.value === row.status)[0]?.label } },
+        {
+          label: '状态',
+          prop: 'status',
+          method: (row) => {
+            const found = this.rmbStatusOpt.find(item => item.value === row.status);
+            return found ? found.label : '--';
+          }
+        },
         { label: '原因', prop: 'remark' },
         { label: '原因', prop: 'remark' },
         { label: '备注', prop: 'admin_note' },
         { label: '备注', prop: 'admin_note' },
         { label: '申请时间', prop: 'created_at' }
         { label: '申请时间', prop: 'created_at' }
       ],
       ],
       rmbRowsActions: [
       rmbRowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.rmbViewRow = { ...row };
+            this.$refs.rmbViewDialog.open();
+          }
+        },
         {
         {
           key: 'lock',
           key: 'lock',
           label: '上锁',
           label: '上锁',
@@ -166,7 +326,7 @@ export default {
                 this.onRmbSubmit()
                 this.onRmbSubmit()
                 this.$message({ type: 'success', message: '操作成功' })
                 this.$message({ type: 'success', message: '操作成功' })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -183,7 +343,7 @@ export default {
                 this.onRmbSubmit()
                 this.onRmbSubmit()
                 this.$message({ type: 'success', message: '操作成功' })
                 this.$message({ type: 'success', message: '操作成功' })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -255,7 +415,7 @@ export default {
           options: [
           options: [
             { label: '会员ID', value: ['member_id'] },
             { label: '会员ID', value: ['member_id'] },
             { label: '用户名称', value: ['username'] },
             { label: '用户名称', value: ['username'] },
-            { label: '异常信息', vShow: (row) => row?.user_admin_note ? true : false, value: ['user_admin_note'] }
+            { label: '备注', vShow: (row) => row?.user_admin_note ? true : false, value: ['user_admin_note'] }
           ]
           ]
         },
         },
         { label: '提现金额', prop: 'amount', method: (row) => Number(row.amount)?.toFixed(2) + ' USDT' },
         { label: '提现金额', prop: 'amount', method: (row) => Number(row.amount)?.toFixed(2) + ' USDT' },
@@ -263,39 +423,46 @@ export default {
         { label: '费率', width: 50, prop: 'exchange_rate', method: (row) => this.formatNumber(row.exchange_rate, 2) },
         { label: '费率', width: 50, prop: 'exchange_rate', method: (row) => this.formatNumber(row.exchange_rate, 2) },
         {
         {
           label: '到账金额',
           label: '到账金额',
-          prop: 'to_account',
           html: true,
           html: true,
           method: (row) => {
           method: (row) => {
-            return `
-              <div class="amount-display">
-                <div class="usd-amount">${this.formatNumber(row.to_account_usdt)} USDT</div>
-              </div>
-            `
+            return `<span style="color: #18C80A;">${this.formatNumber(row.to_account_usdt)} USDT</span>`;
           }
           }
         },
         },
         {
         {
           label: '扣除金额',
           label: '扣除金额',
           html: true,
           html: true,
           method: (row) => {
           method: (row) => {
-            const amount = row.amount || 0
-            const exchangeRate = row.exchange_rate || 1
-            const convertedAmount = amount * exchangeRate
-            return `
-              <div class="amount-display">
-                <div class="cny-amount">${this.formatNumber(convertedAmount)} RMB</div>
-              </div>
-            `
+            const amount = row.amount || 0;
+            const exchangeRate = row.exchange_rate || 1;
+            const convertedAmount = amount * exchangeRate;
+            return `<span style="color: #E6A23C;">${this.formatNumber(convertedAmount)} RMB</span>`;
           }
           }
         },
         },
         { label: '提现后余额', prop: 'after_balance', method: (row) => Number(row.after_balance)?.toFixed(2) + ' RMB' },
         { label: '提现后余额', prop: 'after_balance', method: (row) => Number(row.after_balance)?.toFixed(2) + ' RMB' },
         { label: '钱包地址', prop: 'address', width: 130 },
         { label: '钱包地址', prop: 'address', width: 130 },
         { label: '是否加锁', prop: 'is_locked', method: (row) => row.is_locked === 1 ? '是' : '否' },
         { label: '是否加锁', prop: 'is_locked', method: (row) => row.is_locked === 1 ? '是' : '否' },
-        { label: '状态', method: (row) => { return this.usdtStatusOpt.filter(item => item.value === row.status)[0]?.label } },
+        {
+          label: '状态',
+          prop: 'status',
+          method: (row) => {
+            const found = this.usdtStatusOpt.find(item => item.value === row.status);
+            return found ? found.label : '--';
+          }
+        },
         { label: '原因', prop: 'remark' },
         { label: '原因', prop: 'remark' },
         { label: '申请时间', prop: 'created_at' },
         { label: '申请时间', prop: 'created_at' },
         { label: '备注', prop: 'admin_note' }
         { label: '备注', prop: 'admin_note' }
       ],
       ],
       usdtRowsActions: [
       usdtRowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.usdtViewRow = { ...row };
+            this.$refs.usdtViewDialog.open();
+          }
+        },
         {
         {
           key: 'lock',
           key: 'lock',
           label: '上锁',
           label: '上锁',
@@ -310,7 +477,7 @@ export default {
                 this.onUsdtSubmit()
                 this.onUsdtSubmit()
                 this.$message({ type: 'success', message: '操作成功' })
                 this.$message({ type: 'success', message: '操作成功' })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -327,7 +494,7 @@ export default {
                 this.onUsdtSubmit()
                 this.onUsdtSubmit()
                 this.$message({ type: 'success', message: '操作成功' })
                 this.$message({ type: 'success', message: '操作成功' })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -374,7 +541,76 @@ export default {
         pass: { show: false }
         pass: { show: false }
       },
       },
       usdtEditForm: [],
       usdtEditForm: [],
-      usdtEditConfig: {}
+      usdtEditConfig: {},
+
+      // RMB 状态颜色映射
+      rmbStatusColorMap: {
+        0: '#E6A23C',
+        1: '#409EFF',
+        2: '#67C23A',
+        3: '#F56C6C',
+        4: '#909399',
+        5: '#E6A23C',
+        6: '#909399'
+      },
+      // USDT 状态颜色映射
+      usdtStatusColorMap: {
+        0: '#409EFF',
+        1: '#67C23A',
+        2: '#F56C6C',
+        3: '#909399'
+      },
+
+      // ---------- 查看弹窗数据 ----------
+      rmbViewRow: null,
+      usdtViewRow: null,
+    }
+  },
+  computed: {
+    // RMB 查看字段
+    rmbViewFields() {
+      if (!this.rmbViewRow) return []
+      const row = this.rmbViewRow
+      const infoHtml = `${row.account || ''}(${row.bank_name || ''})<br/>账户:${row.card_no || ''}`
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '订单号', prop: 'order_no', value: row.order_no || '--' },
+        { label: '提现金额', prop: 'amount', value: row.amount != null ? Number(row.amount).toFixed(2) : '--', type: 'amount' },
+        { label: '信息', prop: 'info', value: infoHtml, type: 'info' },
+        { label: '手续费', prop: 'fee', value: row.fee != null ? Number(row.fee).toFixed(2) : '--', type: 'fee' },
+        { label: '是否加锁', prop: 'is_locked', value: row.is_locked === 1 ? '是' : '否', type: 'is_locked', rawValue: row.is_locked },
+        { label: '状态', prop: 'status', value: (this.rmbStatusOpt.find(item => item.value === row.status) || { label: '--' }).label, type: 'status', rawValue: row.status },
+        { label: '原因', prop: 'remark', value: row.remark || '--' },
+        { label: '备注', prop: 'admin_note', value: row.admin_note || '--' },
+        { label: '申请时间', prop: 'created_at', value: row.created_at || '--' },
+      ]
+    },
+    // USDT 查看字段
+    usdtViewFields() {
+      if (!this.usdtViewRow) return []
+      const row = this.usdtViewRow
+      const toAccountHtml = `<span style="color: #18C80A;">${this.formatNumber(row.to_account_usdt)} USDT</span>`
+      const amount = row.amount || 0
+      const exchangeRate = row.exchange_rate || 1
+      const deductAmount = amount * exchangeRate
+      const deductHtml = `<span style="color: #E6A23C;">${this.formatNumber(deductAmount)} RMB</span>`
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '提现金额', prop: 'amount', value: row.amount != null ? Number(row.amount).toFixed(2) + ' USDT' : '--', type: 'amount' },
+        { label: '手续费', prop: 'service_charge', value: row.service_charge != null ? Number(row.service_charge).toFixed(2) + ' USDT' : '--', type: 'service_charge' },
+        { label: '费率', prop: 'exchange_rate', value: row.exchange_rate != null ? this.formatNumber(row.exchange_rate, 2) : '--', type: 'exchange_rate' },
+        { label: '到账金额', prop: 'to_account', value: toAccountHtml, type: 'to_account' },
+        { label: '扣除金额', prop: 'deduct_amount', value: deductHtml, type: 'deduct_amount' },
+        { label: '提现后余额', prop: 'after_balance', value: row.after_balance != null ? Number(row.after_balance).toFixed(2) + ' RMB' : '--', type: 'after_balance' },
+        { label: '钱包地址', prop: 'address', value: row.address || '--' },
+        { label: '是否加锁', prop: 'is_locked', value: row.is_locked === 1 ? '是' : '否', type: 'is_locked', rawValue: row.is_locked },
+        { label: '状态', prop: 'status', value: (this.usdtStatusOpt.find(item => item.value === row.status) || { label: '--' }).label, type: 'status', rawValue: row.status },
+        { label: '原因', prop: 'remark', value: row.remark || '--' },
+        { label: '申请时间', prop: 'created_at', value: row.created_at || '--' },
+        { label: '备注', prop: 'admin_note', value: row.admin_note || '--' },
+      ]
     }
     }
   },
   },
   mounted() {
   mounted() {
@@ -387,7 +623,7 @@ export default {
     })
     })
   },
   },
   methods: {
   methods: {
-    // Tab栏点击跳转方法
+    // Tab切换
     handleTabChange(val) {
     handleTabChange(val) {
       if (val === 'rmb') {
       if (val === 'rmb') {
         this.onRmbSubmit()
         this.onRmbSubmit()
@@ -396,13 +632,13 @@ export default {
       }
       }
     },
     },
 
 
-    // 公用格式化方法
+    // 公用格式化
     formatNumber(num, decimals = 2) {
     formatNumber(num, decimals = 2) {
       if (isNaN(num)) return '0.00'
       if (isNaN(num)) return '0.00'
       return Number(num).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
       return Number(num).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
     },
     },
 
 
-    // RMB 相关方法
+    // ---------- RMB 列表方法 ----------
     onRmbResponse(data) {
     onRmbResponse(data) {
       this.rmbAlertTip = `总金额:${data.total_amount}(RMB);已处理:${data.total_success}(RMB);失败金额:${data.total_fail}(RMB)`
       this.rmbAlertTip = `总金额:${data.total_amount}(RMB);已处理:${data.total_success}(RMB);失败金额:${data.total_fail}(RMB)`
     },
     },
@@ -445,7 +681,7 @@ export default {
       }
       }
     },
     },
 
 
-    // USDT 相关方法
+    // ---------- USDT 列表方法 ----------
     onUsdtResponse(data) {
     onUsdtResponse(data) {
       this.usdtAlertTip = `总金额:${data.total_amount}(USTD);已处理:${data.total_success}(USTD);失败金额:${data.total_fail}(USTD)`
       this.usdtAlertTip = `总金额:${data.total_amount}(USTD);已处理:${data.total_success}(USTD);失败金额:${data.total_fail}(USTD)`
     },
     },
@@ -486,6 +722,145 @@ export default {
           })
           })
         })
         })
       }
       }
+    },
+
+    // ---------- RMB 查看弹窗操作 ----------
+    handleRmbViewAction(action) {
+      const row = this.rmbViewRow
+      if (!row) return
+      const closeDialog = () => {
+        this.$refs.rmbViewDialog.close()
+      }
+      switch (action) {
+        case 'lock':
+          this.$confirm('确定要上锁吗?', '提示', { type: 'warning' }).then(() => {
+            rmbPaymentOrderSetIsLocked({ ids: [row.id], is_locked: 1 }).then(() => {
+              this.onRmbSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'unlock':
+          this.$confirm('确定要解锁吗?', '提示', { type: 'warning' }).then(() => {
+            rmbPaymentOrderSetIsLocked({ ids: [row.id], is_locked: 0 }).then(() => {
+              this.onRmbSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'pass':
+          this.setRmbStatus({ ids: [row.id], status: 1 })
+          // 在 setRmbStatus 成功后关闭弹窗(但该方法内部无 close,需额外处理)
+          // 改造:直接调用 audit 并关闭
+          this.$confirm('确定通过审核?', '提示', { type: 'warning' }).then(() => {
+            audit({ ids: [row.id], status: 1 }).then(() => {
+              this.onRmbSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'reject':
+          this.$prompt('请输入原因', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            inputPattern: /^\S+$/,
+            inputErrorMessage: '请输入原因'
+          }).then(({ value }) => {
+            audit({ ids: [row.id], status: 3, remark: value }).then(() => {
+              this.onRmbSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'note':
+          this.$prompt('请输入备注', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            inputPattern: /^\S+$/,
+            inputErrorMessage: '请输入备注'
+          }).then(({ value }) => {
+            withdrawssetRmbNote({ id: row.id, admin_note: value }).then(() => {
+              this.onRmbSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        default:
+          break
+      }
+    },
+
+    // ---------- USDT 查看弹窗操作 ----------
+    handleUsdtViewAction(action) {
+      const row = this.usdtViewRow
+      if (!row) return
+      const closeDialog = () => {
+        this.$refs.usdtViewDialog.close()
+      }
+      switch (action) {
+        case 'lock':
+          this.$confirm('确定要上锁吗?', '提示', { type: 'warning' }).then(() => {
+            usdtWithdrawSetIsLocked({ ids: [row.id], is_locked: 1 }).then(() => {
+              this.onUsdtSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'unlock':
+          this.$confirm('确定要解锁吗?', '提示', { type: 'warning' }).then(() => {
+            usdtWithdrawSetIsLocked({ ids: [row.id], is_locked: 0 }).then(() => {
+              this.onUsdtSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'pass':
+          this.$confirm('确定通过审核?', '提示', { type: 'warning' }).then(() => {
+            withdrawStatus({ ids: [row.id], status: 1 }).then(() => {
+              this.onUsdtSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'reject':
+          this.$prompt('请输入原因', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            inputPattern: /^\S+$/,
+            inputErrorMessage: '请输入原因'
+          }).then(({ value }) => {
+            withdrawStatus({ ids: [row.id], status: 2, remark: value }).then(() => {
+              this.onUsdtSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        case 'note':
+          this.$prompt('请输入备注', '提示', {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            inputPattern: /^\S+$/,
+            inputErrorMessage: '请输入备注'
+          }).then(({ value }) => {
+            withdrawsetNote({ id: row.id, admin_note: value }).then(() => {
+              this.onUsdtSubmit()
+              this.$message({ type: 'success', message: '操作成功' })
+              closeDialog()
+            })
+          }).catch(() => { })
+          break
+        default:
+          break
+      }
     }
     }
   }
   }
 }
 }
@@ -502,10 +877,12 @@ export default {
   padding-left: 20px;
   padding-left: 20px;
   box-sizing: border-box;
   box-sizing: border-box;
 }
 }
+
 .tab-group {
 .tab-group {
   margin-top: 3px;
   margin-top: 3px;
 }
 }
+
 .search-form {
 .search-form {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
-</style>
+</style>

+ 1 - 1
src/views/Activity/ActivityUser/index.vue

@@ -102,7 +102,7 @@ export default {
               value: ['member.username']
               value: ['member.username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.member.admin_note ? true : false,
               vShow: (row) => row?.member.admin_note ? true : false,
               value: ['member.admin_note']
               value: ['member.admin_note']
             }
             }

+ 295 - 92
src/views/Digital/detail/index.vue

@@ -1,21 +1,22 @@
 <template>
 <template>
   <div class="unified-admin-detail-container">
   <div class="unified-admin-detail-container">
-    <el-card shadow="never" class="detail-card">
-      <div slot="header" class="header-section">
-        <el-button size="small" icon="el-icon-back" @click="goBack">返回列表</el-button>
-        <span class="page-title">订单详情</span>
-      </div>
-
-      <div v-loading="loading" class="content-section" v-if="orderInfo && orderInfo.id">
-
-        <div class="section-title">基本信息</div>
-        <table class="detail-table">
-          <tbody>
+    <!-- 独立页面模式下显示返回按钮,弹窗模式下隐藏(由父组件控制标题) -->
+    <div v-if="!isDialogMode" class="header-section">
+      <el-button size="small" icon="el-icon-back" @click="goBack">返回列表</el-button>
+      <span class="page-title">订单详情</span>
+    </div>
+
+    <div v-loading="loading" class="content-section" v-if="orderInfo && orderInfo.id">
+      <!-- 基本信息 -->
+      <div class="section-title">基本信息</div>
+      <table class="detail-table">
+        <tbody>
           <tr>
           <tr>
             <td class="label">订单号</td>
             <td class="label">订单号</td>
             <td class="value">
             <td class="value">
               <span class="text-bold">{{ orderInfo.ordernum || '--' }}</span>
               <span class="text-bold">{{ orderInfo.ordernum || '--' }}</span>
-              <el-link type="primary" :underline="false" style="margin-left: 10px;" @click="copyText(orderInfo.ordernum)">复制</el-link>
+              <el-link type="primary" :underline="false" style="margin-left: 10px;"
+                @click="copyText(orderInfo.ordernum)">复制</el-link>
             </td>
             </td>
             <td class="label">订单状态</td>
             <td class="label">订单状态</td>
             <td class="value">
             <td class="value">
@@ -44,12 +45,13 @@
             <td class="label">更新时间</td>
             <td class="label">更新时间</td>
             <td class="value">{{ orderInfo.updated_at || '--' }}</td>
             <td class="value">{{ orderInfo.updated_at || '--' }}</td>
           </tr>
           </tr>
-          </tbody>
-        </table>
+        </tbody>
+      </table>
 
 
-        <div class="section-title">投注与结算信息</div>
-        <table class="detail-table">
-          <tbody>
+      <!-- 投注与结算信息 -->
+      <div class="section-title">投注与结算信息</div>
+      <table class="detail-table">
+        <tbody>
           <tr>
           <tr>
             <td class="label">投注玩法</td>
             <td class="label">投注玩法</td>
             <td class="value">
             <td class="value">
@@ -63,17 +65,19 @@
             <td class="label">投注内容</td>
             <td class="label">投注内容</td>
             <td class="value" colspan="3">
             <td class="value" colspan="3">
               <el-tag type="warning" size="medium" style="font-weight: bold; font-size: 14px;">
               <el-tag type="warning" size="medium" style="font-weight: bold; font-size: 14px;">
-                {{ orderInfo.number || '--' }}
+                {{(orderInfo.items || []).map(item => item.number).filter(n => n !== undefined && n !== null && n !==
+                  '').join(',')}}
               </el-tag>
               </el-tag>
             </td>
             </td>
           </tr>
           </tr>
           <tr>
           <tr>
             <td class="label">下注本金</td>
             <td class="label">下注本金</td>
-            <td class="value">¥{{ parseFloat(orderInfo.amount || 0).toFixed(2) }}</td>
+            <td class="value" style="color: #0B17FF;">¥{{ parseFloat(orderInfo.total_amount || 0).toFixed(2) }}</td>
             <td class="label">派彩金额</td>
             <td class="label">派彩金额</td>
             <td class="value">
             <td class="value">
               <span :class="Number(orderInfo.lottery_status) === 2 ? 'win-text' : ''">
               <span :class="Number(orderInfo.lottery_status) === 2 ? 'win-text' : ''">
-                ¥{{ Number(orderInfo.lottery_status) === 2 ? parseFloat(orderInfo.win_amount || 0).toFixed(2) : '0.00' }}
+                ¥{{ Number(orderInfo.lottery_status) === 2 ? parseFloat(orderInfo.win_amount || 0).toFixed(2) : '0.00'
+                }}
               </span>
               </span>
             </td>
             </td>
           </tr>
           </tr>
@@ -86,36 +90,38 @@
               </span>
               </span>
             </td>
             </td>
           </tr>
           </tr>
-          </tbody>
-        </table>
+        </tbody>
+      </table>
 
 
-        <div class="section-title">开奖结果</div>
-        <table class="detail-table">
-          <tbody>
+      <!-- 开奖结果 -->
+      <div class="section-title">开奖结果</div>
+      <table class="detail-table">
+        <tbody>
           <tr>
           <tr>
             <td class="label">开奖号码</td>
             <td class="label">开奖号码</td>
             <td class="value" colspan="3">
             <td class="value" colspan="3">
               <div v-if="openCodes.length > 0" class="table-balls">
               <div v-if="openCodes.length > 0" class="table-balls">
-
+                <!-- 六合彩 -->
                 <template v-if="[1, 2, 3, 4].includes(Number(orderInfo.type))">
                 <template v-if="[1, 2, 3, 4].includes(Number(orderInfo.type))">
                   <template v-for="(code, idx) in openCodes">
                   <template v-for="(code, idx) in openCodes">
-                    <span v-if="idx === openCodes.length - 1" class="plus-sign" :key="'plus-'+idx">+</span>
-                    <div :key="'lhc-'+idx" class="lhc-ball" :class="getLhcBallColor(code)">{{ code }}</div>
+                    <span v-if="idx === openCodes.length - 1" class="plus-sign" :key="'plus-' + idx">+</span>
+                    <div :key="'lhc-' + idx" class="lhc-ball" :class="getLhcBallColor(code)">{{ code }}</div>
                   </template>
                   </template>
                 </template>
                 </template>
-
+                <!-- 快3 -->
                 <template v-else-if="[12, 13].includes(Number(orderInfo.type))">
                 <template v-else-if="[12, 13].includes(Number(orderInfo.type))">
-                  <div v-for="(num, idx) in openCodes" :key="'dice-'+idx" :class="['dice-box', 'dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']">
+                  <div v-for="(num, idx) in openCodes" :key="'dice-' + idx"
+                    :class="['dice-box', 'dice-' + num, (num == 1 || num == 4) ? 'dice-red' : '']">
                     <span v-for="dot in Number(num)" :key="dot" class="dice-dot"></span>
                     <span v-for="dot in Number(num)" :key="dot" class="dice-dot"></span>
                   </div>
                   </div>
                 </template>
                 </template>
-
+                <!-- 其他彩种 -->
                 <template v-else>
                 <template v-else>
-                  <div v-for="(num, idx) in openCodes" :key="'jisu-'+idx" class="jisu-ball" :class="getJisuBallColor(num, orderInfo.type)">
+                  <div v-for="(num, idx) in openCodes" :key="'jisu-' + idx" class="jisu-ball"
+                    :class="getJisuBallColor(num, orderInfo.type)">
                     {{ num }}
                     {{ num }}
                   </div>
                   </div>
                 </template>
                 </template>
-
               </div>
               </div>
               <span v-else>--</span>
               <span v-else>--</span>
             </td>
             </td>
@@ -129,26 +135,25 @@
               <span v-else>--</span>
               <span v-else>--</span>
             </td>
             </td>
           </tr>
           </tr>
-          </tbody>
-        </table>
+        </tbody>
+      </table>
 
 
-        <template v-if="orderInfo.remark">
-          <div class="section-title">其他信息</div>
-          <table class="detail-table">
-            <tbody>
+      <!-- 备注 -->
+      <template v-if="orderInfo.remark">
+        <div class="section-title">其他信息</div>
+        <table class="detail-table">
+          <tbody>
             <tr>
             <tr>
               <td class="label">备注说明</td>
               <td class="label">备注说明</td>
               <td class="value" colspan="3">
               <td class="value" colspan="3">
                 <span class="remark-text">{{ orderInfo.remark }}</span>
                 <span class="remark-text">{{ orderInfo.remark }}</span>
               </td>
               </td>
             </tr>
             </tr>
-            </tbody>
-          </table>
-        </template>
-
-      </div>
-      <el-empty v-else-if="!loading" description="暂无订单数据"></el-empty>
-    </el-card>
+          </tbody>
+        </table>
+      </template>
+    </div>
+    <el-empty v-else-if="!loading" description="暂无订单数据"></el-empty>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -157,14 +162,24 @@ import { lhcDetail } from '@/api/data'
 
 
 export default {
 export default {
   name: 'UnifiedOrderDetail',
   name: 'UnifiedOrderDetail',
+  // ---------- 新增 prop:接收父组件传入的订单ID ----------
+  props: {
+    orderId: {
+      type: [String, Number],
+      default: null
+    }
+  },
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
-      orderId: null,
       orderInfo: {}
       orderInfo: {}
     }
     }
   },
   },
   computed: {
   computed: {
+    // ---------- 新增:判断是否为弹窗模式(有 orderId prop 即认为弹窗模式) ----------
+    isDialogMode() {
+      return this.orderId !== null
+    },
     openCodes() {
     openCodes() {
       const str = this.orderInfo.lottery?.open_code || this.orderInfo.open_code || '';
       const str = this.orderInfo.lottery?.open_code || this.orderInfo.open_code || '';
       return str ? str.split(',') : [];
       return str ? str.split(',') : [];
@@ -175,33 +190,54 @@ export default {
     }
     }
   },
   },
   created() {
   created() {
-    this.orderId = this.$route.query.id || this.$route.params.id;
-    if (this.orderId) {
+    // ---------- 优先使用 prop,否则从路由获取 ----------
+    const id = this.orderId || this.$route.query.id || this.$route.params.id;
+    if (id) {
+      // 避免直接修改 prop,使用一个临时变量存储 ID 用于请求
+      this.orderInfo.id = id;
       this.getDetail();
       this.getDetail();
     } else {
     } else {
       this.$message.error('未获取到有效的订单ID');
       this.$message.error('未获取到有效的订单ID');
-      this.goBack();
+      // ---------- 弹窗模式下通知父组件关闭 ----------
+      if (this.isDialogMode) {
+        this.$emit('close');
+      } else {
+        this.goBack();
+      }
     }
     }
   },
   },
   methods: {
   methods: {
     async getDetail() {
     async getDetail() {
       this.loading = true;
       this.loading = true;
       try {
       try {
-        const res = await lhcDetail({ id: this.orderId });
+        const res = await lhcDetail({ id: this.orderInfo.id });
         if (res && res.code === 0 && res.data) {
         if (res && res.code === 0 && res.data) {
           this.orderInfo = res.data;
           this.orderInfo = res.data;
         } else {
         } else {
           this.$message.error(res.msg || '获取详情失败');
           this.$message.error(res.msg || '获取详情失败');
+          // 获取失败时,若为弹窗模式则通知关闭
+          if (this.isDialogMode) {
+            this.$emit('close');
+          }
         }
         }
       } catch (error) {
       } catch (error) {
         console.error('获取订单详情失败:', error);
         console.error('获取订单详情失败:', error);
+        this.$message.error('请求异常');
+        if (this.isDialogMode) {
+          this.$emit('close');
+        }
       } finally {
       } finally {
         this.loading = false;
         this.loading = false;
       }
       }
     },
     },
 
 
+    // ---------- 返回列表:弹窗模式下触发 close,独立页面使用 router.back ----------
     goBack() {
     goBack() {
-      this.$router.back();
+      if (this.isDialogMode) {
+        this.$emit('close');
+      } else {
+        this.$router.back();
+      }
     },
     },
 
 
     copyText(text) {
     copyText(text) {
@@ -215,6 +251,7 @@ export default {
       this.$message.success('复制成功');
       this.$message.success('复制成功');
     },
     },
 
 
+    // 以下为原有的工具方法(未改动)
     getGameTypeLabel(type) {
     getGameTypeLabel(type) {
       const map = {
       const map = {
         1: '新澳门六合彩', 2: '香港六合彩', 3: '澳门六合彩', 4: '极速六合彩',
         1: '新澳门六合彩', 2: '香港六合彩', 3: '澳门六合彩', 4: '极速六合彩',
@@ -237,16 +274,17 @@ export default {
 
 
     getProfitText(data) {
     getProfitText(data) {
       const status = Number(data.lottery_status);
       const status = Number(data.lottery_status);
-      if (status === 1) return `-${parseFloat(data.amount || 0).toFixed(2)}`;
-      if (status === 2) return `+${parseFloat(data.profit_and_loss || data.win_amount || 0).toFixed(2)}`;
-      return '0.00';
+      if (status === 0 || status === 3) return '--';
+      const profit = Number(data.profit_and_loss);
+      if (isNaN(profit)) return '0.00';
+      return (profit > 0 ? '+' : '') + profit.toFixed(2);
     },
     },
 
 
     getProfitClass(data) {
     getProfitClass(data) {
+      const profit = Number(data.profit_and_loss);
       const status = Number(data.lottery_status);
       const status = Number(data.lottery_status);
-      if (status === 2) return 'profit-win';
-      if (status === 1) return 'profit-loss';
-      return '';
+      if (status === 0 || status === 3 || isNaN(profit) || profit === 0) return '';
+      return profit > 0 ? 'profit-win' : 'profit-loss';
     },
     },
 
 
     getLhcBallColor(numStr) {
     getLhcBallColor(numStr) {
@@ -274,11 +312,9 @@ export default {
 .unified-admin-detail-container {
 .unified-admin-detail-container {
   background: #fff;
   background: #fff;
   padding: 20px;
   padding: 20px;
-  margin: 20px;
   box-sizing: border-box;
   box-sizing: border-box;
   border-radius: 6px;
   border-radius: 6px;
-  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
-  min-height: calc(100vh - 100px);
+  min-height: 100%;
 }
 }
 
 
 .header-section {
 .header-section {
@@ -333,12 +369,31 @@ export default {
   background-color: #fff;
   background-color: #fff;
 }
 }
 
 
-.text-bold { font-weight: bold; }
-.odds-text { color: #FF7600; font-weight: bold; }
-.win-text { color: #67C23A; font-weight: bold; }
-.profit-win { color: #67C23A; }
-.profit-loss { color: #F56C6C; }
-.remark-text { color: #E6A23C; }
+.text-bold {
+  font-weight: bold;
+}
+
+.odds-text {
+  color: #FF7600;
+  font-weight: bold;
+}
+
+.win-text {
+  color: #67C23A;
+  font-weight: bold;
+}
+
+.profit-win {
+  color: #67C23A;
+}
+
+.profit-loss {
+  color: #F56C6C;
+}
+
+.remark-text {
+  color: #E6A23C;
+}
 
 
 .table-balls {
 .table-balls {
   display: flex;
   display: flex;
@@ -364,14 +419,25 @@ export default {
   font-size: 14px;
   font-size: 14px;
   font-weight: 900;
   font-weight: 900;
   color: #fff;
   color: #fff;
-  box-shadow: 0 2px 5px rgba(0,0,0,0.3), inset 0 -2px 2px rgba(0,0,0,0.2);
-  text-shadow: 0 1px 2px rgba(0,0,0,0.3);
+  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3), inset 0 -2px 2px rgba(0, 0, 0, 0.2);
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
 }
 }
 
 
-.lhc-ball.bg-red { background: linear-gradient(135deg, #ff6b6b 0%, #dc2626 100%); }
-.lhc-ball.bg-blue { background: linear-gradient(135deg, #60a5fa 0%, #2563eb 100%); }
-.lhc-ball.bg-green { background: linear-gradient(135deg, #34d399 0%, #059669 100%); }
-.lhc-ball.bg-gray { background: linear-gradient(135deg, #9ca3af 0%, #4b5563 100%); }
+.lhc-ball.bg-red {
+  background: linear-gradient(135deg, #ff6b6b 0%, #dc2626 100%);
+}
+
+.lhc-ball.bg-blue {
+  background: linear-gradient(135deg, #60a5fa 0%, #2563eb 100%);
+}
+
+.lhc-ball.bg-green {
+  background: linear-gradient(135deg, #34d399 0%, #059669 100%);
+}
+
+.lhc-ball.bg-gray {
+  background: linear-gradient(135deg, #9ca3af 0%, #4b5563 100%);
+}
 
 
 .jisu-ball {
 .jisu-ball {
   display: inline-flex;
   display: inline-flex;
@@ -386,17 +452,51 @@ export default {
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
   box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 }
 }
 
 
-.wave-blue { background: linear-gradient(135deg, #42a5f5, #1e88e5); border-color: #1e88e5; }
-.color-1 { background: #E6DE00; text-shadow: 0 1px 1px rgba(0,0,0,0.3); }
-.color-2 { background: #0092FF; }
-.color-3 { background: #4D4D4D; }
-.color-4 { background: #FF7600; }
-.color-5 { background: #17E2E5; }
-.color-6 { background: #5234FF; }
-.color-7 { background: #BFBFBF; }
-.color-8 { background: #FF2600; }
-.color-9 { background: #780B00; }
-.color-10 { background: #07BF00; }
+.wave-blue {
+  background: linear-gradient(135deg, #42a5f5, #1e88e5);
+  border-color: #1e88e5;
+}
+
+.color-1 {
+  background: #E6DE00;
+  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
+}
+
+.color-2 {
+  background: #0092FF;
+}
+
+.color-3 {
+  background: #4D4D4D;
+}
+
+.color-4 {
+  background: #FF7600;
+}
+
+.color-5 {
+  background: #17E2E5;
+}
+
+.color-6 {
+  background: #5234FF;
+}
+
+.color-7 {
+  background: #BFBFBF;
+}
+
+.color-8 {
+  background: #FF2600;
+}
+
+.color-9 {
+  background: #780B00;
+}
+
+.color-10 {
+  background: #07BF00;
+}
 
 
 .dice-box {
 .dice-box {
   width: 28px;
   width: 28px;
@@ -408,7 +508,7 @@ export default {
   padding: 3px;
   padding: 3px;
   grid-template-columns: repeat(3, 1fr);
   grid-template-columns: repeat(3, 1fr);
   grid-template-rows: repeat(3, 1fr);
   grid-template-rows: repeat(3, 1fr);
-  box-shadow: inset 0 -2px 0 rgba(0,0,0,0.05);
+  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.05);
   box-sizing: border-box;
   box-sizing: border-box;
 }
 }
 
 
@@ -421,13 +521,116 @@ export default {
   align-self: center;
   align-self: center;
 }
 }
 
 
-.dice-red .dice-dot { background-color: #F56C6C; }
-.dice-1 .dice-dot:nth-child(1) { grid-column: 2; grid-row: 2; width: 8px; height: 8px; }
-.dice-2 .dice-dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dice-2 .dice-dot:nth-child(2) { grid-column: 3; grid-row: 3; }
-.dice-3 .dice-dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dice-3 .dice-dot:nth-child(2) { grid-column: 2; grid-row: 2; } .dice-3 .dice-dot:nth-child(3) { grid-column: 3; grid-row: 3; }
-.dice-4 .dice-dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dice-4 .dice-dot:nth-child(2) { grid-column: 3; grid-row: 1; } .dice-4 .dice-dot:nth-child(3) { grid-column: 1; grid-row: 3; } .dice-4 .dice-dot:nth-child(4) { grid-column: 3; grid-row: 3; }
-.dice-5 .dice-dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dice-5 .dice-dot:nth-child(2) { grid-column: 3; grid-row: 1; } .dice-5 .dice-dot:nth-child(3) { grid-column: 2; grid-row: 2; } .dice-5 .dice-dot:nth-child(4) { grid-column: 1; grid-row: 3; } .dice-5 .dice-dot:nth-child(5) { grid-column: 3; grid-row: 3; }
-.dice-6 .dice-dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dice-6 .dice-dot:nth-child(2) { grid-column: 1; grid-row: 2; } .dice-6 .dice-dot:nth-child(3) { grid-column: 1; grid-row: 3; } .dice-6 .dice-dot:nth-child(4) { grid-column: 3; grid-row: 1; } .dice-6 .dice-dot:nth-child(5) { grid-column: 3; grid-row: 2; } .dice-6 .dice-dot:nth-child(6) { grid-column: 3; grid-row: 3; }
+.dice-red .dice-dot {
+  background-color: #F56C6C;
+}
+
+.dice-1 .dice-dot:nth-child(1) {
+  grid-column: 2;
+  grid-row: 2;
+  width: 8px;
+  height: 8px;
+}
+
+.dice-2 .dice-dot:nth-child(1) {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.dice-2 .dice-dot:nth-child(2) {
+  grid-column: 3;
+  grid-row: 3;
+}
+
+.dice-3 .dice-dot:nth-child(1) {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.dice-3 .dice-dot:nth-child(2) {
+  grid-column: 2;
+  grid-row: 2;
+}
+
+.dice-3 .dice-dot:nth-child(3) {
+  grid-column: 3;
+  grid-row: 3;
+}
+
+.dice-4 .dice-dot:nth-child(1) {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.dice-4 .dice-dot:nth-child(2) {
+  grid-column: 3;
+  grid-row: 1;
+}
+
+.dice-4 .dice-dot:nth-child(3) {
+  grid-column: 1;
+  grid-row: 3;
+}
+
+.dice-4 .dice-dot:nth-child(4) {
+  grid-column: 3;
+  grid-row: 3;
+}
+
+.dice-5 .dice-dot:nth-child(1) {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.dice-5 .dice-dot:nth-child(2) {
+  grid-column: 3;
+  grid-row: 1;
+}
+
+.dice-5 .dice-dot:nth-child(3) {
+  grid-column: 2;
+  grid-row: 2;
+}
+
+.dice-5 .dice-dot:nth-child(4) {
+  grid-column: 1;
+  grid-row: 3;
+}
+
+.dice-5 .dice-dot:nth-child(5) {
+  grid-column: 3;
+  grid-row: 3;
+}
+
+.dice-6 .dice-dot:nth-child(1) {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.dice-6 .dice-dot:nth-child(2) {
+  grid-column: 1;
+  grid-row: 2;
+}
+
+.dice-6 .dice-dot:nth-child(3) {
+  grid-column: 1;
+  grid-row: 3;
+}
+
+.dice-6 .dice-dot:nth-child(4) {
+  grid-column: 3;
+  grid-row: 1;
+}
+
+.dice-6 .dice-dot:nth-child(5) {
+  grid-column: 3;
+  grid-row: 2;
+}
+
+.dice-6 .dice-dot:nth-child(6) {
+  grid-column: 3;
+  grid-row: 3;
+}
 
 
 .other-code-container {
 .other-code-container {
   display: flex;
   display: flex;

+ 228 - 57
src/views/Digital/order/index.vue

@@ -1,11 +1,6 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch
-      :loading="loading"
-      :search-form="searchForm"
-      @onValueChange="onValueChange"
-      @submit="onSubmit"
-    />
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
 
 
     <div class="tab-container">
     <div class="tab-container">
       <el-tabs v-model="activeType" @tab-click="handleTabClick">
       <el-tabs v-model="activeType" @tab-click="handleTabClick">
@@ -13,22 +8,27 @@
       </el-tabs>
       </el-tabs>
     </div>
     </div>
 
 
-    <YMTable
-      ref="table"
-      :apis="apis"
-      :columns="columns"
-      :custom-style="{ height: 'calc(100vh - 250px)' }"
-      :index="true"
-      :rows-actions="rowsActions"
-      :selection="false"
-      :show-summary="false"
-      :table-key="1"
-      :table-options="tableOptions"
-    />
+    <YMTable ref="table" :apis="apis" :columns="columns" :custom-style="{ height: 'calc(100vh - 250px)' }" :index="true"
+      :rows-actions="rowsActions" :selection="false" :show-summary="false" :table-key="1"
+      :table-options="tableOptions" />
+
+    <!-- ========== 详情弹窗(使用 Dialog 组件,直接复用 UnifiedOrderDetail) ========== -->
+    <Dialog ref="detailDialog" :dialog-actions="{
+      width: '95%',
+      title: '订单详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <UnifiedOrderDetail v-if="detailId" :key="detailId" :orderId="detailId" @close="closeDetailDialog" />
+      </template>
+    </Dialog>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
+import Dialog from '@/components/Dialog/index.vue'
+import UnifiedOrderDetail from '../detail/index.vue' // 根据实际路径调整
+
 const lotteryStatusOptions = [
 const lotteryStatusOptions = [
   { value: 0, label: '待开奖' },
   { value: 0, label: '待开奖' },
   { value: 1, label: '未中奖' },
   { value: 1, label: '未中奖' },
@@ -56,11 +56,16 @@ const lotteryTypeOptions = [
 
 
 export default {
 export default {
   name: 'UnifiedOrderList',
   name: 'UnifiedOrderList',
+  components: {
+    Dialog,
+    UnifiedOrderDetail
+  },
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
       queryData: {},
       queryData: {},
       activeType: '',
       activeType: '',
+      detailId: null, // 详情弹窗使用的订单ID
       lotteryTypeTabs: [{ label: '全部', value: '' }, ...lotteryTypeOptions],
       lotteryTypeTabs: [{ label: '全部', value: '' }, ...lotteryTypeOptions],
 
 
       searchForm: [
       searchForm: [
@@ -78,7 +83,9 @@ export default {
         { label: 'ID', prop: 'id', width: '80' },
         { label: 'ID', prop: 'id', width: '80' },
         {
         {
           label: '订单号', prop: 'ordernum', width: '180', link: true, click: (row) => {
           label: '订单号', prop: 'ordernum', width: '180', link: true, click: (row) => {
-            this.$router.push({ name: 'DigitalDetail', query: { id: row.id } })
+            // 改为弹窗展示(点击订单号与详情按钮逻辑一致)
+            this.detailId = row.id
+            this.$refs.detailDialog.open()
           }
           }
         },
         },
         { label: '期号', prop: 'issue', width: '110' },
         { label: '期号', prop: 'issue', width: '110' },
@@ -113,8 +120,13 @@ export default {
         },
         },
         {
         {
           label: '下注金额',
           label: '下注金额',
-          prop: 'amount',
-          method: (row) => row.amount ? `¥ ${parseFloat(row.amount).toFixed(2)}` : '--'
+          prop: 'total_amount',
+          html: true,
+          method: (row) => {
+            return row.total_amount
+              ? `<span style="color: #0B17FF; font-weight: bold;">¥ ${parseFloat(row.total_amount).toFixed(2)}</span>`
+              : '--';
+          }
         },
         },
         {
         {
           label: '开奖结果',
           label: '开奖结果',
@@ -174,7 +186,8 @@ export default {
           key: 'detail',
           key: 'detail',
           label: '详情',
           label: '详情',
           method: (row) => {
           method: (row) => {
-            this.$router.push({ name: 'DigitalDetail', query: { id: row.id } })
+            this.detailId = row.id
+            this.$refs.detailDialog.open()
           }
           }
         }
         }
       ]
       ]
@@ -194,7 +207,7 @@ export default {
     handleTabClick() {
     handleTabClick() {
       this.onSubmit(this.queryData)
       this.onSubmit(this.queryData)
     },
     },
-    onValueChange(val) {},
+    onValueChange(val) { },
     onSubmit(params = {}) {
     onSubmit(params = {}) {
       const validParams = Object.keys(params).reduce((acc, key) => {
       const validParams = Object.keys(params).reduce((acc, key) => {
         if (params[key] !== '' && params[key] !== null && params[key] !== undefined) {
         if (params[key] !== '' && params[key] !== null && params[key] !== undefined) {
@@ -211,6 +224,13 @@ export default {
       this.$refs.table.getList(this.queryData)
       this.$refs.table.getList(this.queryData)
     },
     },
 
 
+    // 关闭详情弹窗
+    closeDetailDialog() {
+      this.$refs.detailDialog.close()
+      this.detailId = null
+    },
+
+    // 以下为渲染开奖结果的方法(与页面B保持一致)
     renderOpenCode(row) {
     renderOpenCode(row) {
       const openCodeStr = row.lottery?.open_code || row.open_code || ''
       const openCodeStr = row.lottery?.open_code || row.open_code || ''
       const otherTagsStr = row.lottery?.open_code_other || row.open_code_other || ''
       const otherTagsStr = row.lottery?.open_code_other || row.open_code_other || ''
@@ -232,7 +252,7 @@ export default {
       else if ([12, 13].includes(type) && codes.length > 0) {
       else if ([12, 13].includes(type) && codes.length > 0) {
         ballsHtml = codes.map((num) => {
         ballsHtml = codes.map((num) => {
           let dotsHtml = ''
           let dotsHtml = ''
-          for(let i = 0; i < Number(num); i++) {
+          for (let i = 0; i < Number(num); i++) {
             dotsHtml += '<i class="dot"></i>'
             dotsHtml += '<i class="dot"></i>'
           }
           }
           const isRed = (num == 1 || num == 4) ? 'dice-red' : ''
           const isRed = (num == 1 || num == 4) ? 'dice-red' : ''
@@ -287,21 +307,25 @@ export default {
 </script>
 </script>
 
 
 <style scoped lang="scss">
 <style scoped lang="scss">
+/* 样式与原来一致 */
 .tab-container {
 .tab-container {
   background: #ffffff;
   background: #ffffff;
   padding: 0 15px;
   padding: 0 15px;
   margin: 0 15px;
   margin: 0 15px;
   border-radius: 6px;
   border-radius: 6px;
 }
 }
+
 ::v-deep .el-table {
 ::v-deep .el-table {
   font-size: 13px;
   font-size: 13px;
 }
 }
+
 ::v-deep .result-wrapper {
 ::v-deep .result-wrapper {
   display: flex;
   display: flex;
   flex-direction: column;
   flex-direction: column;
   gap: 6px;
   gap: 6px;
   align-items: center;
   align-items: center;
   justify-content: center;
   justify-content: center;
+
   .balls-row {
   .balls-row {
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
@@ -309,12 +333,14 @@ export default {
     justify-content: center;
     justify-content: center;
     gap: 4px;
     gap: 4px;
   }
   }
+
   .tags-row {
   .tags-row {
     display: flex;
     display: flex;
     flex-wrap: wrap;
     flex-wrap: wrap;
     justify-content: center;
     justify-content: center;
     gap: 4px;
     gap: 4px;
   }
   }
+
   .other-tag {
   .other-tag {
     font-size: 12px;
     font-size: 12px;
     background: #f4f4f5;
     background: #f4f4f5;
@@ -323,12 +349,14 @@ export default {
     border-radius: 4px;
     border-radius: 4px;
     border: 1px solid #e9e9eb;
     border: 1px solid #e9e9eb;
   }
   }
+
   .plus-sign {
   .plus-sign {
     font-size: 16px;
     font-size: 16px;
     font-weight: bold;
     font-weight: bold;
     color: #909399;
     color: #909399;
     margin: 0 2px;
     margin: 0 2px;
   }
   }
+
   .lhc-ball {
   .lhc-ball {
     width: 26px;
     width: 26px;
     height: 26px;
     height: 26px;
@@ -339,12 +367,25 @@ export default {
     font-size: 13px;
     font-size: 13px;
     font-weight: 900;
     font-weight: 900;
     color: #fff;
     color: #fff;
-    box-shadow: 0 1px 3px rgba(0,0,0,0.3), inset 0 -2px 2px rgba(0,0,0,0.2);
-    &.bg-red { background: linear-gradient(135deg, #ff6b6b 0%, #dc2626 100%); }
-    &.bg-blue { background: linear-gradient(135deg, #60a5fa 0%, #2563eb 100%); }
-    &.bg-green { background: linear-gradient(135deg, #34d399 0%, #059669 100%); }
-    &.bg-gray { background: linear-gradient(135deg, #9ca3af 0%, #4b5563 100%); }
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), inset 0 -2px 2px rgba(0, 0, 0, 0.2);
+
+    &.bg-red {
+      background: linear-gradient(135deg, #ff6b6b 0%, #dc2626 100%);
+    }
+
+    &.bg-blue {
+      background: linear-gradient(135deg, #60a5fa 0%, #2563eb 100%);
+    }
+
+    &.bg-green {
+      background: linear-gradient(135deg, #34d399 0%, #059669 100%);
+    }
+
+    &.bg-gray {
+      background: linear-gradient(135deg, #9ca3af 0%, #4b5563 100%);
+    }
   }
   }
+
   .jisu-ball {
   .jisu-ball {
     width: 22px;
     width: 22px;
     height: 22px;
     height: 22px;
@@ -358,18 +399,54 @@ export default {
     justify-content: center;
     justify-content: center;
     background: #ccc;
     background: #ccc;
     box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
     box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-    &.wave-blue { background: linear-gradient(135deg, #42a5f5, #1e88e5); box-shadow: 0 1px 3px rgba(66, 165, 245, 0.3); }
-    &.color-1 { background: #E6DE00; text-shadow: 0 1px 1px rgba(0,0,0,0.3); }
-    &.color-2 { background: #0092FF; }
-    &.color-3 { background: #4D4D4D; }
-    &.color-4 { background: #FF7600; }
-    &.color-5 { background: #17E2E5; }
-    &.color-6 { background: #5234FF; }
-    &.color-7 { background: #BFBFBF; }
-    &.color-8 { background: #FF2600; }
-    &.color-9 { background: #780B00; }
-    &.color-10 { background: #07BF00; }
+
+    &.wave-blue {
+      background: linear-gradient(135deg, #42a5f5, #1e88e5);
+      box-shadow: 0 1px 3px rgba(66, 165, 245, 0.3);
+    }
+
+    &.color-1 {
+      background: #E6DE00;
+      text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
+    }
+
+    &.color-2 {
+      background: #0092FF;
+    }
+
+    &.color-3 {
+      background: #4D4D4D;
+    }
+
+    &.color-4 {
+      background: #FF7600;
+    }
+
+    &.color-5 {
+      background: #17E2E5;
+    }
+
+    &.color-6 {
+      background: #5234FF;
+    }
+
+    &.color-7 {
+      background: #BFBFBF;
+    }
+
+    &.color-8 {
+      background: #FF2600;
+    }
+
+    &.color-9 {
+      background: #780B00;
+    }
+
+    &.color-10 {
+      background: #07BF00;
+    }
   }
   }
+
   .dice-item {
   .dice-item {
     width: 24px;
     width: 24px;
     height: 24px;
     height: 24px;
@@ -380,8 +457,9 @@ export default {
     padding: 2px;
     padding: 2px;
     grid-template-columns: repeat(3, 1fr);
     grid-template-columns: repeat(3, 1fr);
     grid-template-rows: repeat(3, 1fr);
     grid-template-rows: repeat(3, 1fr);
-    box-shadow: inset 0 -2px 0 rgba(0,0,0,0.05);
+    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.05);
     box-sizing: border-box;
     box-sizing: border-box;
+
     .dot {
     .dot {
       width: 4px;
       width: 4px;
       height: 4px;
       height: 4px;
@@ -390,24 +468,117 @@ export default {
       justify-self: center;
       justify-self: center;
       align-self: center;
       align-self: center;
     }
     }
-    &.dice-1 { .dot:nth-child(1) { grid-column: 2; grid-row: 2; width: 6px; height: 6px; } }
-    &.dice-2 { .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 3; grid-row: 3; } }
-    &.dice-3 { .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 2; grid-row: 2; } .dot:nth-child(3) { grid-column: 3; grid-row: 3; } }
-    &.dice-4 {
-      .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 3; grid-row: 1; }
-      .dot:nth-child(3) { grid-column: 1; grid-row: 3; } .dot:nth-child(4) { grid-column: 3; grid-row: 3; }
+
+    &.dice-1 .dot:nth-child(1) {
+      grid-column: 2;
+      grid-row: 2;
+      width: 6px;
+      height: 6px;
+    }
+
+    &.dice-2 .dot:nth-child(1) {
+      grid-column: 1;
+      grid-row: 1;
+    }
+
+    &.dice-2 .dot:nth-child(2) {
+      grid-column: 3;
+      grid-row: 3;
+    }
+
+    &.dice-3 .dot:nth-child(1) {
+      grid-column: 1;
+      grid-row: 1;
+    }
+
+    &.dice-3 .dot:nth-child(2) {
+      grid-column: 2;
+      grid-row: 2;
+    }
+
+    &.dice-3 .dot:nth-child(3) {
+      grid-column: 3;
+      grid-row: 3;
+    }
+
+    &.dice-4 .dot:nth-child(1) {
+      grid-column: 1;
+      grid-row: 1;
+    }
+
+    &.dice-4 .dot:nth-child(2) {
+      grid-column: 3;
+      grid-row: 1;
+    }
+
+    &.dice-4 .dot:nth-child(3) {
+      grid-column: 1;
+      grid-row: 3;
+    }
+
+    &.dice-4 .dot:nth-child(4) {
+      grid-column: 3;
+      grid-row: 3;
+    }
+
+    &.dice-5 .dot:nth-child(1) {
+      grid-column: 1;
+      grid-row: 1;
+    }
+
+    &.dice-5 .dot:nth-child(2) {
+      grid-column: 3;
+      grid-row: 1;
+    }
+
+    &.dice-5 .dot:nth-child(3) {
+      grid-column: 2;
+      grid-row: 2;
+    }
+
+    &.dice-5 .dot:nth-child(4) {
+      grid-column: 1;
+      grid-row: 3;
+    }
+
+    &.dice-5 .dot:nth-child(5) {
+      grid-column: 3;
+      grid-row: 3;
+    }
+
+    &.dice-6 .dot:nth-child(1) {
+      grid-column: 1;
+      grid-row: 1;
+    }
+
+    &.dice-6 .dot:nth-child(2) {
+      grid-column: 1;
+      grid-row: 2;
     }
     }
-    &.dice-5 {
-      .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 3; grid-row: 1; }
-      .dot:nth-child(3) { grid-column: 2; grid-row: 2; }
-      .dot:nth-child(4) { grid-column: 1; grid-row: 3; } .dot:nth-child(5) { grid-column: 3; grid-row: 3; }
+
+    &.dice-6 .dot:nth-child(3) {
+      grid-column: 1;
+      grid-row: 3;
+    }
+
+    &.dice-6 .dot:nth-child(4) {
+      grid-column: 3;
+      grid-row: 1;
     }
     }
-    &.dice-6 {
-      .dot:nth-child(1) { grid-column: 1; grid-row: 1; } .dot:nth-child(2) { grid-column: 1; grid-row: 2; }
-      .dot:nth-child(3) { grid-column: 1; grid-row: 3; } .dot:nth-child(4) { grid-column: 3; grid-row: 1; }
-      .dot:nth-child(5) { grid-column: 3; grid-row: 2; } .dot:nth-child(6) { grid-column: 3; grid-row: 3; }
+
+    &.dice-6 .dot:nth-child(5) {
+      grid-column: 3;
+      grid-row: 2;
+    }
+
+    &.dice-6 .dot:nth-child(6) {
+      grid-column: 3;
+      grid-row: 3;
+    }
+
+    &.dice-red .dot {
+      background-color: #f56c6c;
     }
     }
-    &.dice-red .dot { background-color: #f56c6c; }
   }
   }
 }
 }
-</style>
+</style>

+ 107 - 30
src/views/balance/log/index.vue

@@ -1,28 +1,72 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit"/>
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="false"
-      :table-options="tableOptions"
-      :edit-form="editForm"
-      :edit-config="editConfig"
-      :columns="columns"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :alertTip="alertTip"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-      @onResponse="onResponse"
-    />
-    <!-- 自定义弹窗 -->
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="true" :selection="false" :table-options="tableOptions"
+      :edit-form="editForm" :edit-config="editConfig" :columns="columns" :rows-actions="rowsActions"
+      :show-summary="false" :apis="apis" :alertTip="alertTip" :custom-style="{ height: 'calc(100vh - 150px)' }"
+      :actions-width="120" @onResponse="onResponse">
+      <!-- 变动后余额(实际列名是 before_balance,但模板中插槽名为 before_balance,对应 prop: before_balance) -->
+      <template #before_balance="{ row }">
+        <span style="color: #18C80A;">
+          {{ row.before_balance != null ? Number(row.before_balance).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 变动金额 -->
+      <template #amount="{ row }">
+        <span :style="{
+          color: Number(row.amount) > 0 ? '#18C80A' : Number(row.amount) < 0 ? '#F56C6C' : '#909399'
+        }">
+          {{ row.amount != null ? Number(row.amount).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 类型(change_type) -->
+      <template #change_type="{ row }">
+        <span style="color: #0B17FF;">
+          {{ row.change_type || '--' }}
+        </span>
+      </template>
+    </YMTable>
+
+    <!-- 原有的空弹窗(保留) -->
     <Dialog ref="dialog">
     <Dialog ref="dialog">
-      <template slot="content"/>
+      <template slot="content" />
+    </Dialog>
+
+    <!-- ========== 新增:查看详情弹窗 ========== -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '800px',
+      title: '余额变动详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 变动前余额 / 变动后余额:绿色 -->
+            <div v-if="field.type === 'balance'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <!-- 变动金额:正绿负红 -->
+            <div v-else-if="field.type === 'amount'"
+              :style="{ color: field.rawValue > 0 ? '#18C80A' : field.rawValue < 0 ? '#F56C6C' : '#909399', fontSize: '15px' }">
+              {{ field.value }}</div>
+            <!-- 类型(change_type):蓝色 -->
+            <div v-else-if="field.type === 'change_type'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}
+            </div>
+            <!-- 资金类型:显示“可用余额”/“冻结金额” -->
+            <div v-else-if="field.type === 'fund_type'" style="color: #303133; font-size: 15px;">{{ field.value }}</div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <div style="margin-top: 20px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+        </div>
+      </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
 </template>
 </template>
+
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
 
 
@@ -35,6 +79,8 @@ export default {
       loading: false,
       loading: false,
       visibleBasicDrawer: false,
       visibleBasicDrawer: false,
       alertTip: '',
       alertTip: '',
+      // 新增:存储当前查看的行数据
+      viewRow: null,
       searchForm: [
       searchForm: [
         {
         {
           label: '会员ID',
           label: '会员ID',
@@ -43,7 +89,7 @@ export default {
           default: '',
           default: '',
           clearable: true
           clearable: true
         },
         },
-         {
+        {
           label: '会员昵称',
           label: '会员昵称',
           type: 'input',
           type: 'input',
           prop: 'first_name',
           prop: 'first_name',
@@ -61,8 +107,8 @@ export default {
           type: 'select',
           type: 'select',
           prop: 'type',
           prop: 'type',
           options: [
           options: [
-            {label: '可用余额', value: 1},
-            {label: '冻结金额', value: 2}
+            { label: '可用余额', value: 1 },
+            { label: '冻结金额', value: 2 }
           ],
           ],
           clearable: true
           clearable: true
         },
         },
@@ -76,7 +122,7 @@ export default {
 
 
       ],
       ],
       columns: [
       columns: [
-          {
+        {
           label: '会员ID',
           label: '会员ID',
           prop: 'member_id',
           prop: 'member_id',
           width: 120
           width: 120
@@ -96,7 +142,7 @@ export default {
               value: ['member.username']
               value: ['member.username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.member.admin_note ? true : false,
               vShow: (row) => row?.member.admin_note ? true : false,
               value: ['member.admin_note']
               value: ['member.admin_note']
             }
             }
@@ -105,7 +151,7 @@ export default {
         {
         {
           label: '变动前余额',
           label: '变动前余额',
           prop: 'after_balance',
           prop: 'after_balance',
-          method: (row) => Number(row.before_balance)?.toFixed(2)
+          method: (row) => Number(row.after_balance)?.toFixed(2)
         },
         },
         {
         {
           label: '变动金额',
           label: '变动金额',
@@ -116,16 +162,16 @@ export default {
         {
         {
           label: '变动后余额',
           label: '变动后余额',
           prop: 'before_balance',
           prop: 'before_balance',
-          method: (row) => Number(row.after_balance)?.toFixed(2)
+          method: (row) => Number(row.before_balance)?.toFixed(2)
         },
         },
         {
         {
           label: '时间',
           label: '时间',
           prop: 'created_at'
           prop: 'created_at'
         },
         },
-          {
+        {
           label: '资金类型',
           label: '资金类型',
           prop: 'type',
           prop: 'type',
-             method: (row) => Number(row.type) === 1 ? '可用余额' : '冻结金额'
+          method: (row) => Number(row.type) === 1 ? '可用余额' : '冻结金额'
         },
         },
         {
         {
           label: '类型',
           label: '类型',
@@ -140,7 +186,17 @@ export default {
           prop: 'remark'
           prop: 'remark'
         }
         }
       ],
       ],
-      rowsActions: [],
+      rowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.viewRow = { ...row };
+            this.$refs.viewDialog.open();
+          }
+        }
+      ],
       apis: {
       apis: {
         list: {
         list: {
           url: 'balance/log',
           url: 'balance/log',
@@ -158,6 +214,26 @@ export default {
       member_id: ''
       member_id: ''
     }
     }
   },
   },
+  computed: {
+    // 新增:详情弹窗字段列表
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+      const fundTypeMap = { 1: '可用余额', 2: '冻结金额' }
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '变动前余额', prop: 'after_balance', value: row.after_balance != null ? Number(row.after_balance).toFixed(2) : '--', type: 'balance' },
+        { label: '变动金额', prop: 'amount', value: row.amount != null ? Number(row.amount).toFixed(2) : '--', type: 'amount', rawValue: Number(row.amount) },
+        { label: '变动后余额', prop: 'before_balance', value: row.before_balance != null ? Number(row.before_balance).toFixed(2) : '--', type: 'balance' },
+        { label: '时间', prop: 'created_at', value: row.created_at || '--' },
+        { label: '资金类型', prop: 'type', value: fundTypeMap[row.type] || '--', type: 'fund_type' },
+        { label: '类型', prop: 'change_type', value: row.change_type || '--', type: 'change_type' },
+        { label: '关联ID', prop: 'related_id', value: row.related_id || '--' },
+        { label: '说明', prop: 'remark', value: row.remark || '--' },
+      ]
+    }
+  },
   created() {
   created() {
     // 获取参数
     // 获取参数
     this.member_id = this.$route.query.member_id
     this.member_id = this.$route.query.member_id
@@ -170,6 +246,7 @@ export default {
   },
   },
   methods: {
   methods: {
     initDateRange() {
     initDateRange() {
+      // 注释掉的逻辑保留
       // const endDate = new Date()
       // const endDate = new Date()
       // const startDate = new Date()
       // const startDate = new Date()
       // startDate.setDate(startDate.getDate() - 7)
       // startDate.setDate(startDate.getDate() - 7)
@@ -217,4 +294,4 @@ export default {
     }
     }
   }
   }
 }
 }
-</script>
+</script>

+ 1 - 1
src/views/order/list/index.vue

@@ -138,7 +138,7 @@ export default {
               value: ['user.username']
               value: ['user.username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.user.admin_note ? true : false,
               vShow: (row) => row?.user.admin_note ? true : false,
               value: ['user.admin_note']
               value: ['user.admin_note']
             }
             }

+ 116 - 74
src/views/orderManage/EventDetail/index.vue

@@ -2,8 +2,9 @@
   <div class="sport-detail-container">
   <div class="sport-detail-container">
     <el-card shadow="never" v-loading="isLoading" style="height: 100%">
     <el-card shadow="never" v-loading="isLoading" style="height: 100%">
       <div slot="header" class="clearfix">
       <div slot="header" class="clearfix">
-        <el-button icon="el-icon-back" size="mini" @click="$router.back()">返回列表</el-button>
-        <span class="header-title">赛事详情</span>
+        <!-- 弹窗模式下隐藏返回按钮(由父组件控制标题),独立页面显示 -->
+        <el-button v-if="!isDialogMode" icon="el-icon-back" size="mini" @click="goBack">返回列表</el-button>
+        <span class="header-title">{{ isDialogMode ? '' : '赛事详情' }}</span>
       </div>
       </div>
 
 
       <div class="detail-content" v-if="matchInfo.id">
       <div class="detail-content" v-if="matchInfo.id">
@@ -30,10 +31,7 @@
           <el-col :span="12">
           <el-col :span="12">
             <div class="item flex-item">
             <div class="item flex-item">
               <span class="label">联赛Logo:</span>
               <span class="label">联赛Logo:</span>
-              <el-image
-                v-if="matchInfo.league_data.logo"
-                :src="matchInfo.league_data.logo"
-                class="team-logo">
+              <el-image v-if="matchInfo.league_data.logo" :src="matchInfo.league_data.logo" class="team-logo">
               </el-image>
               </el-image>
               <span v-else class="value">--</span>
               <span v-else class="value">--</span>
             </div>
             </div>
@@ -72,7 +70,7 @@
               </span>
               </span>
             </div>
             </div>
           </el-col>
           </el-col>
-              <el-col :span="12">
+          <el-col :span="12">
             <div class="item">
             <div class="item">
               <span class="label">比赛时间:</span>
               <span class="label">比赛时间:</span>
               <span class="value">{{ matchInfo.game_time || '--' }}</span>
               <span class="value">{{ matchInfo.game_time || '--' }}</span>
@@ -84,10 +82,7 @@
           <el-col :span="12">
           <el-col :span="12">
             <div class="item flex-item">
             <div class="item flex-item">
               <span class="label">主队:</span>
               <span class="label">主队:</span>
-              <el-image
-                v-if="matchInfo.home_team_logo"
-                :src="matchInfo.home_team_logo"
-                class="team-logo">
+              <el-image v-if="matchInfo.home_team_logo" :src="matchInfo.home_team_logo" class="team-logo">
               </el-image>
               </el-image>
               <span class="value text-bold">{{ matchInfo.home_team }}</span>
               <span class="value text-bold">{{ matchInfo.home_team }}</span>
             </div>
             </div>
@@ -95,10 +90,7 @@
           <el-col :span="12">
           <el-col :span="12">
             <div class="item flex-item">
             <div class="item flex-item">
               <span class="label">客队:</span>
               <span class="label">客队:</span>
-              <el-image
-                v-if="matchInfo.guest_team_logo"
-                :src="matchInfo.guest_team_logo"
-                class="team-logo">
+              <el-image v-if="matchInfo.guest_team_logo" :src="matchInfo.guest_team_logo" class="team-logo">
               </el-image>
               </el-image>
               <span class="value text-bold">{{ matchInfo.guest_team }}</span>
               <span class="value text-bold">{{ matchInfo.guest_team }}</span>
             </div>
             </div>
@@ -129,9 +121,7 @@
           <el-col :span="12">
           <el-col :span="12">
             <div class="item">
             <div class="item">
               <span class="label">赛事阶段:</span>
               <span class="label">赛事阶段:</span>
-              <el-tag
-                type="success"
-                size="small">
+              <el-tag type="success" size="small">
                 {{ matchInfo.fixture_status.long }}
                 {{ matchInfo.fixture_status.long }}
               </el-tag>
               </el-tag>
             </div>
             </div>
@@ -179,21 +169,12 @@
           <el-collapse-transition>
           <el-collapse-transition>
             <div v-show="isEventsExpanded">
             <div v-show="isEventsExpanded">
               <el-timeline>
               <el-timeline>
-                <el-timeline-item
-                  v-for="evt in processedEvents"
-                  :key="evt.id"
-                  :timestamp="evt.timeDisplay"
-                  placement="top"
-                  :color="evt.iconColor"
-                >
+                <el-timeline-item v-for="evt in processedEvents" :key="evt.id" :timestamp="evt.timeDisplay"
+                  placement="top" :color="evt.iconColor">
                   <el-card shadow="hover" class="event-card">
                   <el-card shadow="hover" class="event-card">
                     <div class="event-card-content">
                     <div class="event-card-content">
                       <div class="team-info" :class="evt.isHome ? 'is-home' : 'is-guest'">
                       <div class="team-info" :class="evt.isHome ? 'is-home' : 'is-guest'">
-                        <el-image
-                          v-if="evt.teamLogo"
-                          :src="evt.teamLogo"
-                          class="event-team-logo"
-                          fit="contain">
+                        <el-image v-if="evt.teamLogo" :src="evt.teamLogo" class="event-team-logo" fit="contain">
                         </el-image>
                         </el-image>
                         <span class="team-name">{{ evt.teamName }}</span>
                         <span class="team-name">{{ evt.teamName }}</span>
                       </div>
                       </div>
@@ -226,12 +207,16 @@
               <el-table :data="processedStatistics" border style="width: 100%" size="small">
               <el-table :data="processedStatistics" border style="width: 100%" size="small">
                 <el-table-column prop="label" label="统计项" width="150" align="center"></el-table-column>
                 <el-table-column prop="label" label="统计项" width="150" align="center"></el-table-column>
                 <el-table-column label="上半场" align="center">
                 <el-table-column label="上半场" align="center">
-                  <el-table-column prop="home1" :label="'主队 (' + matchInfo.home_team + ')'" align="center"></el-table-column>
-                  <el-table-column prop="guest1" :label="'客队 (' + matchInfo.guest_team + ')'" align="center"></el-table-column>
+                  <el-table-column prop="home1" :label="'主队 (' + matchInfo.home_team + ')'"
+                    align="center"></el-table-column>
+                  <el-table-column prop="guest1" :label="'客队 (' + matchInfo.guest_team + ')'"
+                    align="center"></el-table-column>
                 </el-table-column>
                 </el-table-column>
                 <el-table-column label="下半场" align="center">
                 <el-table-column label="下半场" align="center">
-                  <el-table-column prop="home2" :label="'主队 (' + matchInfo.home_team + ')'" align="center"></el-table-column>
-                  <el-table-column prop="guest2" :label="'客队 (' + matchInfo.guest_team + ')'" align="center"></el-table-column>
+                  <el-table-column prop="home2" :label="'主队 (' + matchInfo.home_team + ')'"
+                    align="center"></el-table-column>
+                  <el-table-column prop="guest2" :label="'客队 (' + matchInfo.guest_team + ')'"
+                    align="center"></el-table-column>
                 </el-table-column>
                 </el-table-column>
               </el-table>
               </el-table>
             </div>
             </div>
@@ -239,47 +224,33 @@
         </div>
         </div>
 
 
         <div class="odds-section" v-if="matchInfo.odds && matchInfo.odds.length > 0">
         <div class="odds-section" v-if="matchInfo.odds && matchInfo.odds.length > 0">
-          <div class="section-header" style="display: flex; justify-content: space-between; align-items: center; padding-right: 10px;">
+          <div class="section-header"
+            style="display: flex; justify-content: space-between; align-items: center; padding-right: 10px;">
             <span>盘口及赔率信息</span>
             <span>盘口及赔率信息</span>
-            <el-button
-              :icon="isAllLocked ? 'el-icon-lock' : 'el-icon-unlock'"
-              @click="toggleAllOddsLock"
-              size="mini"
-              :type="isAllLocked ? 'danger' : 'success'"
-            >
+            <el-button :icon="isAllLocked ? 'el-icon-lock' : 'el-icon-unlock'" @click="toggleAllOddsLock" size="mini"
+              :type="isAllLocked ? 'danger' : 'success'">
               {{ isAllLocked ? '一键解锁' : '一键上锁' }}
               {{ isAllLocked ? '一键解锁' : '一键上锁' }}
             </el-button>
             </el-button>
           </div>
           </div>
           <div v-for="oddGroup in matchInfo.odds" :key="oddGroup.id" class="odd-group-box">
           <div v-for="oddGroup in matchInfo.odds" :key="oddGroup.id" class="odd-group-box">
             <div class="odd-group-title">
             <div class="odd-group-title">
               {{ oddGroup.name }}
               {{ oddGroup.name }}
-              <el-button
-                :icon="oddGroup.is_locked ? 'el-icon-lock' : 'el-icon-unlock'"
-                @click="toggleOddLock(oddGroup)"
-                size="mini"
-                style="margin-left: 10px;"
-                :type="oddGroup.is_locked ? 'danger' : 'success'"
-              ></el-button>
+              <el-button :icon="oddGroup.is_locked ? 'el-icon-lock' : 'el-icon-unlock'" @click="toggleOddLock(oddGroup)"
+                size="mini" style="margin-left: 10px;" :type="oddGroup.is_locked ? 'danger' : 'success'"></el-button>
             </div>
             </div>
             <el-row :gutter="15">
             <el-row :gutter="15">
               <el-col :span="8" v-for="(val, index) in oddGroup.values" :key="index">
               <el-col :span="8" v-for="(val, index) in oddGroup.values" :key="index">
                 <div class="odd-item" :class="{ 'is-suspended': val.suspended }">
                 <div class="odd-item" :class="{ 'is-suspended': val.suspended }">
                   <span class="odd-label">{{ val.value }}
                   <span class="odd-label">{{ val.value }}
-                  <template v-if="val.handicap">
-                    ({{ val.handicap }})
-                  </template>
+                    <template v-if="val.handicap">
+                      ({{ val.handicap }})
+                    </template>
                   </span>
                   </span>
                   <div style="display: flex; align-items: center;">
                   <div style="display: flex; align-items: center;">
                     <span class="odd-value" style="margin-right: 8px;">{{ val.odd }}</span>
                     <span class="odd-value" style="margin-right: 8px;">{{ val.odd }}</span>
-                    <el-button
-                      v-if="!val.suspended"
-                      :icon="val.is_locked ? 'el-icon-lock' : 'el-icon-unlock'"
-                      @click="toggleValueLock(oddGroup.id, val)"
-                      size="mini"
-                      circle
-                      style="padding: 4px;"
-                      :type="val.is_locked ? 'danger' : 'success'"
-                    ></el-button>
+                    <el-button v-if="!val.suspended" :icon="val.is_locked ? 'el-icon-lock' : 'el-icon-unlock'"
+                      @click="toggleValueLock(oddGroup.id, val)" size="mini" circle style="padding: 4px;"
+                      :type="val.is_locked ? 'danger' : 'success'"></el-button>
                     <div v-if="val.suspended" style="width: 24px;"></div>
                     <div v-if="val.suspended" style="width: 24px;"></div>
                   </div>
                   </div>
                 </div>
                 </div>
@@ -301,6 +272,13 @@ import { sportInfo, setOddsLocked, sportSetValuesLocked } from '@/api/data'
 
 
 export default {
 export default {
   name: 'SportOrderDetail',
   name: 'SportOrderDetail',
+  // ---------- 新增 prop:接收父组件传入的赛事ID ----------
+  props: {
+    matchId: {
+      type: [String, Number],
+      default: null
+    }
+  },
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
@@ -323,6 +301,10 @@ export default {
     isLoading() {
     isLoading() {
       return this.loading && this.loadingConfig
       return this.loading && this.loadingConfig
     },
     },
+    // ---------- 判断是否为弹窗模式 ----------
+    isDialogMode() {
+      return this.matchId !== null
+    },
     isAllLocked() {
     isAllLocked() {
       if (!this.matchInfo.odds || this.matchInfo.odds.length === 0) return false
       if (!this.matchInfo.odds || this.matchInfo.odds.length === 0) return false
       return this.matchInfo.odds.every(group => group.is_locked)
       return this.matchInfo.odds.every(group => group.is_locked)
@@ -430,13 +412,25 @@ export default {
     }
     }
   },
   },
   created() {
   created() {
-    this.fetchDetail()
-    this.timer = setInterval(() => {
-      if (this.matchInfo.state === 0 || this.matchInfo.state === 1) {
-        this.loadingConfig = false
-        this.fetchDetail()
+    // ---------- 优先使用 prop,否则从路由获取 ----------
+    const id = this.matchId || this.$route.query.id || this.$route.params.id
+    if (id) {
+      this.matchInfo.id = id
+      this.fetchDetail()
+      // 定时刷新:仅当状态为未开始或进行中时才自动刷新
+      this.timer = setInterval(() => {
+        if (this.matchInfo.state === 0 || this.matchInfo.state === 1) {
+          this.loadingConfig = false
+          this.fetchDetail()
+        }
+      }, 5000)
+    } else {
+      this.$message.error('赛事ID缺失')
+      // 弹窗模式下通知父组件关闭
+      if (this.isDialogMode) {
+        this.$emit('close')
       }
       }
-    }, 5000)
+    }
   },
   },
   destroyed() {
   destroyed() {
     clearInterval(this.timer)
     clearInterval(this.timer)
@@ -448,7 +442,7 @@ export default {
     },
     },
 
 
     async fetchDetail() {
     async fetchDetail() {
-      const id = this.$route.query.id || this.$route.params.id
+      const id = this.matchInfo.id
       if (!id) {
       if (!id) {
         this.$message.error('赛事ID缺失')
         this.$message.error('赛事ID缺失')
         return
         return
@@ -467,9 +461,17 @@ export default {
           this.matchInfo = res.data
           this.matchInfo = res.data
         } else {
         } else {
           this.$message.error(res.msg || '获取详情失败')
           this.$message.error(res.msg || '获取详情失败')
+          // 获取失败时若为弹窗模式则通知关闭
+          if (this.isDialogMode) {
+            this.$emit('close')
+          }
         }
         }
       } catch (error) {
       } catch (error) {
         console.error('API Error:', error)
         console.error('API Error:', error)
+        this.$message.error('请求异常')
+        if (this.isDialogMode) {
+          this.$emit('close')
+        }
       } finally {
       } finally {
         this.loading = false
         this.loading = false
       }
       }
@@ -513,7 +515,7 @@ export default {
       }
       }
     },
     },
 
 
-    // 新增:单个投注项的上锁/解锁控制
+    // 单个投注项的上锁/解锁控制
     async toggleValueLock(odd_id, val) {
     async toggleValueLock(odd_id, val) {
       try {
       try {
         const res = await sportSetValuesLocked({
         const res = await sportSetValuesLocked({
@@ -532,6 +534,15 @@ export default {
         console.error('API Error:', error)
         console.error('API Error:', error)
         this.$message.error('请求异常')
         this.$message.error('请求异常')
       }
       }
+    },
+
+    // ---------- 返回按钮逻辑 ----------
+    goBack() {
+      if (this.isDialogMode) {
+        this.$emit('close')
+      } else {
+        this.$router.back()
+      }
     }
     }
   }
   }
 }
 }
@@ -542,15 +553,18 @@ export default {
   padding: 20px;
   padding: 20px;
   height: calc(100vh - 60px);
   height: calc(100vh - 60px);
 }
 }
+
 .header-title {
 .header-title {
   margin-left: 15px;
   margin-left: 15px;
   font-weight: bold;
   font-weight: bold;
   font-size: 16px;
   font-size: 16px;
   vertical-align: middle;
   vertical-align: middle;
 }
 }
-::v-deep .el-card__body{
+
+::v-deep .el-card__body {
   height: 100%;
   height: 100%;
 }
 }
+
 .detail-content {
 .detail-content {
   padding: 10px;
   padding: 10px;
   border: 1px solid #EBEEF5;
   border: 1px solid #EBEEF5;
@@ -559,31 +573,38 @@ export default {
   overflow-y: auto;
   overflow-y: auto;
   padding-bottom: 50px;
   padding-bottom: 50px;
 }
 }
+
 .detail-row {
 .detail-row {
   border-bottom: 1px solid #EBEEF5;
   border-bottom: 1px solid #EBEEF5;
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
+
 .item {
 .item {
   padding: 12px 10px;
   padding: 12px 10px;
   font-size: 14px;
   font-size: 14px;
 }
 }
+
 .flex-item {
 .flex-item {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
+
 .label {
 .label {
   color: #909399;
   color: #909399;
   width: 120px;
   width: 120px;
   display: inline-block;
   display: inline-block;
   flex-shrink: 0;
   flex-shrink: 0;
 }
 }
+
 .value {
 .value {
   color: #303133;
   color: #303133;
 }
 }
+
 .text-bold {
 .text-bold {
   font-weight: bold;
   font-weight: bold;
 }
 }
+
 .text-danger {
 .text-danger {
   color: #F56C6C;
   color: #F56C6C;
 }
 }
@@ -611,23 +632,29 @@ export default {
   padding: 20px 10px 10px;
   padding: 20px 10px 10px;
   border-bottom: 1px solid #EBEEF5;
   border-bottom: 1px solid #EBEEF5;
 }
 }
+
 .event-header {
 .event-header {
   display: flex;
   display: flex;
   justify-content: space-between;
   justify-content: space-between;
   align-items: center;
   align-items: center;
-  padding-right: 10px; /* 右侧留白防止紧贴边缘 */
+  padding-right: 10px;
+  /* 右侧留白防止紧贴边缘 */
 }
 }
+
 .event-card {
 .event-card {
   margin-bottom: 0;
   margin-bottom: 0;
 }
 }
+
 ::v-deep .event-card .el-card__body {
 ::v-deep .event-card .el-card__body {
   padding: 12px 15px;
   padding: 12px 15px;
 }
 }
+
 .event-card-content {
 .event-card-content {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
   font-size: 14px;
   font-size: 14px;
 }
 }
+
 /* 修改后的事件队伍信息区 */
 /* 修改后的事件队伍信息区 */
 .team-info {
 .team-info {
   display: flex;
   display: flex;
@@ -635,30 +662,39 @@ export default {
   min-width: 140px;
   min-width: 140px;
   margin-right: 15px;
   margin-right: 15px;
 }
 }
+
 .team-info.is-home {
 .team-info.is-home {
-  color: #409EFF; /* 主队蓝色 */
+  color: #409EFF;
+  /* 主队蓝色 */
 }
 }
+
 .team-info.is-guest {
 .team-info.is-guest {
-  color: #E6A23C; /* 客队橙色 */
+  color: #E6A23C;
+  /* 客队橙色 */
 }
 }
+
 .team-info .team-name {
 .team-info .team-name {
   font-weight: bold;
   font-weight: bold;
 }
 }
+
 .event-team-logo {
 .event-team-logo {
   width: 22px;
   width: 22px;
   height: 22px;
   height: 22px;
   margin-right: 8px;
   margin-right: 8px;
-  border-radius: 50%; /* 如果你想让LOGO变圆形,可保留这行 */
+  border-radius: 50%;
+  /* 如果你想让LOGO变圆形,可保留这行 */
 }
 }
 
 
 .event-type {
 .event-type {
   margin-right: 15px;
   margin-right: 15px;
   min-width: 50px;
   min-width: 50px;
 }
 }
+
 .event-detail {
 .event-detail {
   color: #303133;
   color: #303133;
   font-weight: 500;
   font-weight: 500;
 }
 }
+
 .event-player {
 .event-player {
   margin-left: 8px;
   margin-left: 8px;
   color: #909399;
   color: #909399;
@@ -675,12 +711,14 @@ export default {
 .odds-section {
 .odds-section {
   padding: 20px 10px 10px;
   padding: 20px 10px 10px;
 }
 }
+
 .odd-group-box {
 .odd-group-box {
   background: #F8F9FA;
   background: #F8F9FA;
   padding: 15px;
   padding: 15px;
   border-radius: 4px;
   border-radius: 4px;
   margin-bottom: 15px;
   margin-bottom: 15px;
 }
 }
+
 .odd-group-title {
 .odd-group-title {
   font-size: 14px;
   font-size: 14px;
   color: #606266;
   color: #606266;
@@ -689,6 +727,7 @@ export default {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
+
 .odd-item {
 .odd-item {
   background: #fff;
   background: #fff;
   border: 1px solid #EBEEF5;
   border: 1px solid #EBEEF5;
@@ -699,18 +738,21 @@ export default {
   align-items: center;
   align-items: center;
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
+
 .odd-label {
 .odd-label {
   color: #909399;
   color: #909399;
   font-size: 13px;
   font-size: 13px;
 }
 }
+
 .odd-value {
 .odd-value {
   color: #F56C6C;
   color: #F56C6C;
   font-weight: bold;
   font-weight: bold;
   font-size: 14px;
   font-size: 14px;
 }
 }
+
 .is-suspended {
 .is-suspended {
   background: #f5f7fa;
   background: #f5f7fa;
   opacity: 0.6;
   opacity: 0.6;
   text-decoration: line-through;
   text-decoration: line-through;
 }
 }
-</style>
+</style>

+ 35 - 43
src/views/orderManage/EventList/index.vue

@@ -1,23 +1,13 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch
-      :loading="loading"
-      :search-form="searchForm"
-      @onValueChange="onValueChange"
-      @submit="onSubmit"
-    >
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit">
       <template #extra></template>
       <template #extra></template>
     </YMTableSearch>
     </YMTableSearch>
 
 
     <div class="toolbar">
     <div class="toolbar">
       <div class="segmented-control">
       <div class="segmented-control">
-        <div
-          v-for="item in stateOptions"
-          :key="item.value"
-          :class="{ active: activeState === item.value }"
-          class="segmented-item"
-          @click="handleSegmentChange(item.value)"
-        >
+        <div v-for="item in stateOptions" :key="item.value" :class="{ active: activeState === item.value }"
+          class="segmented-item" @click="handleSegmentChange(item.value)">
           {{ item.label }}
           {{ item.label }}
         </div>
         </div>
       </div>
       </div>
@@ -25,45 +15,42 @@
         <el-button size="small" type="warning" @click="handleBatchState">批量修改状态</el-button>
         <el-button size="small" type="warning" @click="handleBatchState">批量修改状态</el-button>
         <el-button size="small" type="success" @click="handleBatchOnline">批量上架</el-button>
         <el-button size="small" type="success" @click="handleBatchOnline">批量上架</el-button>
         <el-button size="small" type="danger" @click="handleBatchOffline">批量下架</el-button>
         <el-button size="small" type="danger" @click="handleBatchOffline">批量下架</el-button>
-        </div>
+      </div>
     </div>
     </div>
 
 
-    <YMTable
-      ref="table"
-      :apis="apis"
-      :columns="columns"
-      :custom-style="{ height: 'calc(100vh - 270px)' }"
-      :index="true"
-      :loading="loading"
-      :rows-actions="rowsActions"
-      :selection="true"
-      :show-summary="false"
-      :table-key="4"
-      :table-options="tableOptions"
-      :custom-loading="customLoading"
-    />
+    <YMTable ref="table" :apis="apis" :columns="columns" :custom-style="{ height: 'calc(100vh - 270px)' }" :index="true"
+      :loading="loading" :rows-actions="rowsActions" :selection="true" :show-summary="false" :table-key="4"
+      :table-options="tableOptions" :custom-loading="customLoading" />
 
 
+    <!-- 修改状态弹窗 -->
     <Dialog ref="dialog" :dialogActions="{ title: '修改比赛状态', width: '400px' }" @confirm="submitStateEdit">
     <Dialog ref="dialog" :dialogActions="{ title: '修改比赛状态', width: '400px' }" @confirm="submitStateEdit">
       <template slot="content">
       <template slot="content">
         <el-form label-width="100px">
         <el-form label-width="100px">
           <el-form-item :rules="[{ required: true, message: '请选择比赛状态' }]" label="比赛状态">
           <el-form-item :rules="[{ required: true, message: '请选择比赛状态' }]" label="比赛状态">
             <el-select v-model="form.state" style="width: 100%;">
             <el-select v-model="form.state" style="width: 100%;">
-              <el-option
-                v-for="item in validStateOptions"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
+              <el-option v-for="item in validStateOptions" :key="item.value" :label="item.label" :value="item.value" />
             </el-select>
             </el-select>
           </el-form-item>
           </el-form-item>
         </el-form>
         </el-form>
       </template>
       </template>
     </Dialog>
     </Dialog>
+
+    <!-- ========== 详情弹窗(复用 SportsDetail 组件) ========== -->
+    <Dialog ref="detailDialog" :dialog-actions="{
+      width: '95%',
+      title: '赛事详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <SportsDetail v-if="detailId" :key="detailId" :match-id="detailId" @close="closeDetailDialog" />
+      </template>
+    </Dialog>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
+import SportsDetail from '../EventDetail/index.vue' // 请根据实际路径调整
 import { setSportStatus } from '@/api/data'
 import { setSportStatus } from '@/api/data'
 
 
 // 比赛状态枚举
 // 比赛状态枚举
@@ -93,12 +80,14 @@ const lockedOptions = [
 export default {
 export default {
   name: 'SportList',
   name: 'SportList',
   components: {
   components: {
-    Dialog
+    Dialog,
+    SportsDetail
   },
   },
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
       queryData: {},
       queryData: {},
+      detailId: null, // 用于弹窗的赛事ID
 
 
       stateOptions, // 引入供模板分段控制器使用
       stateOptions, // 引入供模板分段控制器使用
       activeState: 1, // 当前选中的比赛状态,默认全部
       activeState: 1, // 当前选中的比赛状态,默认全部
@@ -118,8 +107,6 @@ export default {
         { label: '赛事ID', type: 'input', prop: 'data_id', clearable: true, placeholder: '请输入' },
         { label: '赛事ID', type: 'input', prop: 'data_id', clearable: true, placeholder: '请输入' },
         { label: '球队名称', type: 'input', prop: 'team_name', clearable: true, placeholder: '请输入' },
         { label: '球队名称', type: 'input', prop: 'team_name', clearable: true, placeholder: '请输入' },
         { label: '赛事名称', type: 'input', prop: 'league', clearable: true, placeholder: '请输入' },
         { label: '赛事名称', type: 'input', prop: 'league', clearable: true, placeholder: '请输入' },
-        // { label: '主队名称', type: 'input', prop: 'home_team', clearable: true, placeholder: '请输入主队' },
-        // { label: '客队名称', type: 'input', prop: 'guest_team', clearable: true, placeholder: '请输入客队' },
         {
         {
           label: '赔率玩法',
           label: '赔率玩法',
           type: 'select',
           type: 'select',
@@ -278,17 +265,16 @@ export default {
         { label: '比赛时间', prop: 'game_time', minWidth: '160' }
         { label: '比赛时间', prop: 'game_time', minWidth: '160' }
       ],
       ],
 
 
-      // 分开编辑:独立的操作按钮
+      // 操作按钮(修改查看详情为弹窗)
       rowsActions: [
       rowsActions: [
         {
         {
           key: 'viewDetail',
           key: 'viewDetail',
           label: '查看详情',
           label: '查看详情',
           html: true,
           html: true,
           method: (row) => {
           method: (row) => {
-            this.$router.push({
-              name: 'EventDetail',
-              query: { id: row.id }
-            })
+            // 改为弹窗展示
+            this.detailId = row.id
+            this.$refs.detailDialog.open()
           }
           }
         },
         },
         {
         {
@@ -516,6 +502,12 @@ export default {
         })
         })
       }).catch(() => {
       }).catch(() => {
       })
       })
+    },
+
+    // ---------- 详情弹窗控制 ----------
+    closeDetailDialog() {
+      this.$refs.detailDialog.close()
+      this.detailId = null
     }
     }
   }
   }
 }
 }
@@ -574,4 +566,4 @@ export default {
   display: flex;
   display: flex;
   gap: 10px;
   gap: 10px;
 }
 }
-</style>
+</style>

+ 274 - 211
src/views/orderManage/List/index.vue

@@ -1,135 +1,167 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch
-      :loading="loading"
-      :search-form="searchForm"
-      @onValueChange="onValueChange"
-      @submit="onSubmit"
-    />
-    <YMTable
-      ref="table"
-      :apis="apis"
-      :columns="columns"
-      :custom-style="{ height: 'calc(100vh - 200px)' }"
-      :index="true"
-      :rows-actions="rowsActions"
-      :selection="false"
-      :show-summary="false"
-      :table-key="1"
-      :table-options="tableOptions"
-    >
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :apis="apis" :columns="columns" :custom-style="{ height: 'calc(100vh - 200px)' }" :index="true"
+      :rows-actions="rowsActions" :selection="false" :show-summary="false" :table-key="1" :table-options="tableOptions"
+      :actions-width="140">
+      <!-- 赛事信息插槽(安全处理空值) -->
       <template #game_info="{ row }">
       <template #game_info="{ row }">
-        <div v-if="row" style="line-height: 1.5; font-size: 12px;height: 70px;display: flex;flex-direction: column;justify-content: center;">
+        <div v-if="row"
+          style="line-height: 1.5; font-size: 12px;height: 70px;display: flex;flex-direction: column;justify-content: center;">
           <div>{{ row.detail ? row.detail.game_time : '--' }}</div>
           <div>{{ row.detail ? row.detail.game_time : '--' }}</div>
           <div style="font-weight: bold; color: #303133;">
           <div style="font-weight: bold; color: #303133;">
             {{ row.home_team || '--' }} vs {{ row.guest_team || '--' }}
             {{ row.home_team || '--' }} vs {{ row.guest_team || '--' }}
           </div>
           </div>
-          <div style="opacity: 0;height: 0px;">1</div>
-          <div v-if="(row.detail && row.detail.fixture_status)">
-            赛况: <span v-if="(row.detail && row.detail.fixture_status)">{{ (row.detail && row.detail.fixture_status) ? row.detail.fixture_status.long : '--' }}</span>
-            <span v-if="(row.detail && row.detail.fixture_status) ">
-              ({{ (row.detail && row.detail.fixture_status) ? row.detail.fixture_status.seconds : '--' }})
-            </span>
+          <div v-if="row.detail && row.detail.fixture_status">
+            赛况: <span>{{ row.detail.fixture_status.long || '--' }}</span>
+            <span>({{ row.detail.fixture_status.seconds || '--' }})</span>
           </div>
           </div>
+          <div v-else>赛况: --</div>
           <div>
           <div>
-            <span v-if="row.detail && row.detail.half_score">半场: {{ row.detail ? row.detail.half_score : '--' }}</span>
+            <span v-if="row.detail && row.detail.half_score">半场: {{ row.detail.half_score }}</span>
             <span v-if="row.detail && row.detail.score && row.detail.half_score"> / </span>
             <span v-if="row.detail && row.detail.score && row.detail.half_score"> / </span>
-            <span v-if="row.detail && row.detail.score">
-              全场: {{ row.detail ? row.detail.score : '--' }}
-            </span>
+            <span v-if="row.detail && row.detail.score">全场: {{ row.detail.score }}</span>
+            <span v-if="!row.detail || (!row.detail.half_score && !row.detail.score)">--</span>
           </div>
           </div>
         </div>
         </div>
       </template>
       </template>
 
 
+      <!-- 玩法信息插槽 -->
       <template #odd_name="{ row }">
       <template #odd_name="{ row }">
         <div v-if="row" style="line-height: 1.5; font-size: 12px;height: 70px;">
         <div v-if="row" style="line-height: 1.5; font-size: 12px;height: 70px;">
           <div style="font-weight: bold; color: #303133;">{{ row.odd_name || '--' }}</div>
           <div style="font-weight: bold; color: #303133;">{{ row.odd_name || '--' }}</div>
           <div>玩法: {{ row.odd_value || '--' }}</div>
           <div>玩法: {{ row.odd_value || '--' }}</div>
-           <div style="opacity: 0;height: 0px;">1</div>
+          <div style="opacity: 0;height: 0px;">1</div>
           <div>盘口: {{ row.handicap || '--' }}</div>
           <div>盘口: {{ row.handicap || '--' }}</div>
           <div>赔率: {{ row.odd || '--' }}</div>
           <div>赔率: {{ row.odd || '--' }}</div>
         </div>
         </div>
       </template>
       </template>
     </YMTable>
     </YMTable>
 
 
+    <!-- 扣款弹窗 -->
     <el-dialog :visible.sync="debitDialogVisible" title="扣款操作" width="450px" @close="resetDebitForm">
     <el-dialog :visible.sync="debitDialogVisible" title="扣款操作" width="450px" @close="resetDebitForm">
       <el-form ref="debitForm" :model="debitForm" :rules="debitRules" label-width="100px">
       <el-form ref="debitForm" :model="debitForm" :rules="debitRules" label-width="100px">
         <el-form-item label="扣款金额" prop="amount">
         <el-form-item label="扣款金额" prop="amount">
-          <el-input-number
-            v-model="debitForm.amount"
-            :min="0.01"
-            :precision="2"
-            placeholder="请输入扣款金额"
-            style="width: 100%;"
-          >
+          <el-input-number v-model="debitForm.amount" :min="0.01" :precision="2" placeholder="请输入扣款金额"
+            style="width: 100%;">
           </el-input-number>
           </el-input-number>
         </el-form-item>
         </el-form-item>
         <el-form-item label="备注" prop="remark">
         <el-form-item label="备注" prop="remark">
-          <el-input
-            v-model="debitForm.remark"
-            :rows="3"
-            placeholder="请输入备注信息(选填)"
-            type="textarea"
-          >
+          <el-input v-model="debitForm.remark" :rows="3" placeholder="请输入备注信息(选填)" type="textarea">
           </el-input>
           </el-input>
         </el-form-item>
         </el-form-item>
       </el-form>
       </el-form>
       <span slot="footer" class="dialog-footer">
       <span slot="footer" class="dialog-footer">
-    <el-button @click="debitDialogVisible = false">取 消</el-button>
-    <el-button :loading="loading" type="primary" @click="submitDebitOrder">确 定</el-button>
-  </span>
+        <el-button @click="debitDialogVisible = false">取 消</el-button>
+        <el-button :loading="loading" type="primary" @click="submitDebitOrder">确 定</el-button>
+      </span>
     </el-dialog>
     </el-dialog>
 
 
+    <!-- 充值弹窗 -->
     <el-dialog :visible.sync="rechargeDialogVisible" title="充值操作" width="450px" @close="resetRechargeForm">
     <el-dialog :visible.sync="rechargeDialogVisible" title="充值操作" width="450px" @close="resetRechargeForm">
       <el-form ref="rechargeForm" :model="rechargeForm" :rules="rechargeRules" label-width="100px">
       <el-form ref="rechargeForm" :model="rechargeForm" :rules="rechargeRules" label-width="100px">
         <el-form-item label="充值金额" prop="amount">
         <el-form-item label="充值金额" prop="amount">
-          <el-input-number
-            v-model="rechargeForm.amount"
-            :min="0.01"
-            :precision="2"
-            placeholder="请输入充值金额"
-            style="width: 100%;"
-          >
+          <el-input-number v-model="rechargeForm.amount" :min="0.01" :precision="2" placeholder="请输入充值金额"
+            style="width: 100%;">
           </el-input-number>
           </el-input-number>
         </el-form-item>
         </el-form-item>
         <el-form-item label="备注" prop="remark">
         <el-form-item label="备注" prop="remark">
-          <el-input
-            v-model="rechargeForm.remark"
-            :rows="3"
-            placeholder="请输入备注信息(选填)"
-            type="textarea"
-          >
+          <el-input v-model="rechargeForm.remark" :rows="3" placeholder="请输入备注信息(选填)" type="textarea">
           </el-input>
           </el-input>
         </el-form-item>
         </el-form-item>
       </el-form>
       </el-form>
       <span slot="footer" class="dialog-footer">
       <span slot="footer" class="dialog-footer">
-    <el-button @click="rechargeDialogVisible = false">取 消</el-button>
-    <el-button :loading="loading" type="primary" @click="submitRechargeOrder">确 定</el-button>
-  </span>
+        <el-button @click="rechargeDialogVisible = false">取 消</el-button>
+        <el-button :loading="loading" type="primary" @click="submitRechargeOrder">确 定</el-button>
+      </span>
     </el-dialog>
     </el-dialog>
+
+    <!-- ========== 查看详情弹窗(含操作按钮) ========== -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '820px',
+      title: '订单详情',
+      confirmButtom: false
+    }">
+      <template slot="content">
+        <!-- 详情展示区 -->
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 400px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 赛事信息 -->
+            <div v-if="field.type === 'game_info'" style="font-size: 13px; line-height: 1.6;" v-html="field.value">
+            </div>
+            <!-- 玩法信息 -->
+            <div v-else-if="field.type === 'odd_info'" style="font-size: 13px; line-height: 1.6;" v-html="field.value">
+            </div>
+            <!-- 滚球 -->
+            <div v-else-if="field.type === 'is_roll'"
+              :style="{ color: field.rawValue === 1 ? '#E6A23C' : '#909399', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+            <!-- 订单状态 -->
+            <div v-else-if="field.type === 'status'" :style="{ color: field.color, fontSize: '15px' }">{{ field.value }}
+            </div>
+            <!-- 中奖状态 -->
+            <div v-else-if="field.type === 'is_win'" :style="{ color: field.color, fontSize: '15px' }">{{ field.value }}
+            </div>
+            <!-- 结算状态 -->
+            <div v-else-if="field.type === 'settlement_status'" :style="{ color: field.color, fontSize: '15px' }">{{
+              field.value }}</div>
+            <!-- 支付状态 -->
+            <div v-else-if="field.type === 'pay_status'"
+              :style="{ color: field.rawValue === 1 ? '#67C23A' : '#909399', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+            <!-- 退款状态 -->
+            <div v-else-if="field.type === 'return_status'" :style="{ color: field.color, fontSize: '15px' }">{{
+              field.value }}</div>
+            <!-- 金额字段 -->
+            <div v-else-if="field.type === 'amount'" style="color: #303133; font-size: 15px;">{{ field.value }}</div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+
+        <!-- 操作按钮区(与列表保持一致) -->
+        <div style="margin-top: 16px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 退款按钮 -->
+          <el-button
+            v-if="viewRow && viewRow.pay_status === 1 && viewRow.settlement_status === 0 && viewRow.status === 1 && viewRow.return_status === 0"
+            type="warning" size="small" @click="handleRefundFromView">退款</el-button>
+
+          <!-- 充值按钮 -->
+          <el-button v-if="viewRow && viewRow.pay_status === 1" type="primary" size="small"
+            @click="handleRechargeFromView">充值</el-button>
+
+          <!-- 扣款按钮 -->
+          <el-button v-if="viewRow && viewRow.pay_status === 1" type="danger" size="small"
+            @click="handleDeductionFromView">扣款</el-button>
+        </div>
+      </template>
+    </Dialog>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
+import Dialog from '@/components/Dialog/index.vue'
 import { orderRefund, walletOrderDebiting, walletOrderTopUp } from '@/api/data'
 import { orderRefund, walletOrderDebiting, walletOrderTopUp } from '@/api/data'
 
 
 export default {
 export default {
+  components: {
+    Dialog
+  },
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
       queryData: {},
       queryData: {},
+      viewRow: null,
 
 
       // 搜索表单配置
       // 搜索表单配置
       searchForm: [
       searchForm: [
         { label: 'ID', type: 'input', prop: 'id', clearable: true },
         { label: 'ID', type: 'input', prop: 'id', clearable: true },
         { label: '订单号', prop: 'order_id', type: 'input' },
         { label: '订单号', prop: 'order_id', type: 'input' },
-        // { label: '用户ID', prop: 'user_id', type: 'input' },
-        {
-          label: '会员昵称',
-          type: 'input',
-          prop: 'first_name',
-          clearable: true
-        },
+        { label: '会员昵称', type: 'input', prop: 'first_name', clearable: true },
         { label: '会员ID', prop: 'member_id', type: 'input', clearable: true },
         { label: '会员ID', prop: 'member_id', type: 'input', clearable: true },
         { label: '赛事ID', prop: 'issue', type: 'input' },
         { label: '赛事ID', prop: 'issue', type: 'input' },
         {
         {
@@ -148,7 +180,7 @@ export default {
           options: [
           options: [
             { label: '已取消', value: -1 },
             { label: '已取消', value: -1 },
             { label: '下注中', value: 0 },
             { label: '下注中', value: 0 },
-            { label: '下注成功', value: 1 } // 注:根据你下面的字段映射,这里1对应“已支付”或“已成功”
+            { label: '下注成功', value: 1 }
           ]
           ]
         },
         },
         {
         {
@@ -184,29 +216,21 @@ export default {
         }
         }
       ],
       ],
 
 
-      // API 接口配置
       apis: {
       apis: {
         list: {
         list: {
-          url: 'order/list', // 请将此处替换为实际的接口地址
+          url: 'order/list',
           dataParam: 'data.data',
           dataParam: 'data.data',
           resultParam: 'data',
           resultParam: 'data',
           init: false
           init: false
         }
         }
       },
       },
 
 
-      // 表格整体配置
       tableOptions: {
       tableOptions: {
-        add: {
-          show: false
-        }
+        add: { show: false }
       },
       },
 
 
-      // 表格列配置
       columns: [
       columns: [
-        {
-          label: 'ID',
-          prop: 'id',
-        },
+        { label: 'ID', prop: 'id' },
         {
         {
           label: '订单号',
           label: '订单号',
           prop: 'order_id',
           prop: 'order_id',
@@ -219,36 +243,15 @@ export default {
             })
             })
           }
           }
         },
         },
-        // { label: '用户ID', prop: 'user_id', width: 100 },
-         {
-          label: '会员ID',
-          prop: 'member_id',
-          width: 120
-        },
-          {
-          label: '会员昵称',
-          prop: 'first_name',
-          width: 150
-        },
-        // {
-        //   label: '账户类型',
-        //   prop: 'is_faker',
-        //   width: 90,
-        //   html: true,
-        //   method: (row) => {
-        //     const isFaker = row.is_faker === 1
-        //     const color = isFaker ? '#F56C6C' : '#67C23A'
-        //     const text = isFaker ? '虚拟账户' : '真实账户'
-        //     return `<span style="color: ${color}">${text}</span>`
-        //   }
-        // },
+        { label: '会员ID', prop: 'member_id', width: 120 },
+        { label: '会员昵称', prop: 'first_name', width: 150 },
         { label: '赛事ID', prop: 'issue', width: 120 },
         { label: '赛事ID', prop: 'issue', width: 120 },
         {
         {
           label: '赛事信息',
           label: '赛事信息',
           prop: 'game_info',
           prop: 'game_info',
           width: 220,
           width: 220,
           slot: true,
           slot: true,
-          className: 'custom-game-col' // 给该列表格单元格增加自定义类名
+          className: 'custom-game-col'
         },
         },
         {
         {
           label: '滚球',
           label: '滚球',
@@ -266,9 +269,9 @@ export default {
           label: '玩法',
           label: '玩法',
           prop: 'odd_name',
           prop: 'odd_name',
           width: 180,
           width: 180,
-          slot: true // 开启插槽
+          slot: true
         },
         },
-           {
+        {
           label: '订单状态',
           label: '订单状态',
           prop: 'status',
           prop: 'status',
           width: 90,
           width: 90,
@@ -284,10 +287,8 @@ export default {
             return match ? `<span style="color: ${match.color}">${match.text}</span>` : '--'
             return match ? `<span style="color: ${match.color}">${match.text}</span>` : '--'
           }
           }
         },
         },
-        // 这里移除了原来的 '赔率'(odd)、'赔率玩法'(odd_value)、'盘口'(handicp) 三列
         { label: '下注失败的原因', prop: 'failure' },
         { label: '下注失败的原因', prop: 'failure' },
         { label: '下注金额(RMB)', prop: 'amount', width: 100 },
         { label: '下注金额(RMB)', prop: 'amount', width: 100 },
-        // { label: 'RMB汇率', prop: 'cny_rate', width: 100 },
         { label: '派奖金额(RMB)', prop: 'win_amount', width: 100 },
         { label: '派奖金额(RMB)', prop: 'win_amount', width: 100 },
         { label: '盈亏金额(RMB)', prop: 'profit_and_loss', width: 100 },
         { label: '盈亏金额(RMB)', prop: 'profit_and_loss', width: 100 },
         {
         {
@@ -305,7 +306,6 @@ export default {
             return match ? `<span style="color: ${match.color}">${match.text}</span>` : '--'
             return match ? `<span style="color: ${match.color}">${match.text}</span>` : '--'
           }
           }
         },
         },
-
         {
         {
           label: '结算状态',
           label: '结算状态',
           prop: 'settlement_status',
           prop: 'settlement_status',
@@ -356,161 +356,224 @@ export default {
         { label: '创建时间', prop: 'create_time', width: 160 }
         { label: '创建时间', prop: 'create_time', width: 160 }
       ],
       ],
 
 
-      // 表格右侧操作列
       rowsActions: [
       rowsActions: [
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.viewRow = { ...row }
+            this.$refs.viewDialog.open()
+          }
+        },
         {
         {
           key: 'refund',
           key: 'refund',
           label: '退款',
           label: '退款',
-          // 判断是否禁用按钮
           disabled: (row) => {
           disabled: (row) => {
-            // 条件: 1.支付状态已支付(1) 2.结算状态未结算(0) 3.订单状态已支付(1) 4.退款状态未退款(0)
             const canRefund =
             const canRefund =
               row.pay_status === 1 &&
               row.pay_status === 1 &&
               row.settlement_status === 0 &&
               row.settlement_status === 0 &&
               row.status === 1 &&
               row.status === 1 &&
               row.return_status === 0
               row.return_status === 0
-
-            // disabled 为 true 时禁用按钮,所以这里取反
             return !canRefund
             return !canRefund
           },
           },
           method: (row) => {
           method: (row) => {
             this.handleRefund(row)
             this.handleRefund(row)
           }
           }
         },
         },
-
         {
         {
           key: 'topUp',
           key: 'topUp',
           label: '充值',
           label: '充值',
-          // 判断是否禁用按钮
-          disabled: (row) => {
-            // 条件: 1.支付状态已支付(1) 2.结算状态未结算(0) 3.订单状态已支付(1) 4.退款状态未退款(0)
-            const canRefund =
-              row.pay_status === 1
-
-            // disabled 为 true 时禁用按钮,所以这里取反
-            return !canRefund
-          },
+          disabled: (row) => !(row.pay_status === 1),
           method: (row) => {
           method: (row) => {
             this.handleWalletOrderRecharging(row)
             this.handleWalletOrderRecharging(row)
           }
           }
         },
         },
-
         {
         {
           key: 'deduction',
           key: 'deduction',
           label: '扣款',
           label: '扣款',
-          // 判断是否禁用按钮
-          disabled: (row) => {
-            // 条件: 1.支付状态已支付(1) 2.结算状态未结算(0) 3.订单状态已支付(1) 4.退款状态未退款(0)
-            const canRefund =
-              row.pay_status === 1
-
-            // disabled 为 true 时禁用按钮,所以这里取反
-            return !canRefund
-          },
+          disabled: (row) => !(row.pay_status === 1),
           method: (row) => {
           method: (row) => {
             this.handleWalletOrderDebiting(row)
             this.handleWalletOrderDebiting(row)
           }
           }
         }
         }
-
       ],
       ],
 
 
-      // 扣款弹窗相关的状态
       debitDialogVisible: false,
       debitDialogVisible: false,
       debitForm: {
       debitForm: {
         amount: undefined,
         amount: undefined,
         remark: '',
         remark: '',
         order_id: '',
         order_id: '',
-        order_type: 'sport' // 默认传 sport
+        order_type: 'sport'
       },
       },
       debitRules: {
       debitRules: {
-        amount: [
-          { required: true, message: '请输入扣款金额', trigger: 'blur' }
-        ]
+        amount: [{ required: true, message: '请输入扣款金额', trigger: 'blur' }]
       },
       },
 
 
-      // 充值弹窗相关的状态
       rechargeDialogVisible: false,
       rechargeDialogVisible: false,
       rechargeForm: {
       rechargeForm: {
         amount: undefined,
         amount: undefined,
         remark: '',
         remark: '',
         order_id: '',
         order_id: '',
-        order_type: 'sport' // 默认传 sport
+        order_type: 'sport'
       },
       },
       rechargeRules: {
       rechargeRules: {
-        amount: [
-          { required: true, message: '请输入充值金额', trigger: 'blur' }
-        ]
+        amount: [{ required: true, message: '请输入充值金额', trigger: 'blur' }]
       }
       }
+    }
+  },
+  computed: {
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+
+      // 安全构建赛事信息 HTML
+      const detail = row.detail || {}
+      const fixtureStatus = detail.fixture_status || null
+      const fixtureLong = fixtureStatus ? fixtureStatus.long : '--'
+      const fixtureSeconds = fixtureStatus ? fixtureStatus.seconds : '--'
 
 
+      const gameInfoHtml = `
+        <div style="line-height: 1.6;">
+          <div style="font-weight: bold; color: #303133;">${row.home_team || '--'} vs ${row.guest_team || '--'}</div>
+          <div>比赛时间: ${detail.game_time || '--'}</div>
+          <div>赛况: ${fixtureLong} ${fixtureSeconds !== '--' ? `(${fixtureSeconds})` : ''}</div>
+          <div>
+            ${detail.half_score ? `半场: ${detail.half_score}` : ''}
+            ${detail.score && detail.half_score ? ' / ' : ''}
+            ${detail.score ? `全场: ${detail.score}` : ''}
+            ${!detail.half_score && !detail.score ? '--' : ''}
+          </div>
+        </div>
+      `
+
+      const oddInfoHtml = `
+        <div style="line-height: 1.6;">
+          <div style="font-weight: bold; color: #303133;">${row.odd_name || '--'}</div>
+          <div>玩法: ${row.odd_value || '--'}</div>
+          <div>盘口: ${row.handicap || '--'}</div>
+          <div>赔率: ${row.odd || '--'}</div>
+        </div>
+      `
+
+      const statusMap = {
+        0: { text: '下注中', color: '#909399' },
+        1: { text: '下注成功', color: '#67C23A' },
+        2: { text: '已退款', color: '#E6A23C' },
+        '-1': { text: '已取消', color: '#F56C6C' }
+      }
+      const statusMatch = statusMap[row.status] || { text: '--', color: '#909399' }
+
+      const winMap = {
+        0: { text: '未中奖', color: '#909399' },
+        1: { text: '已中奖', color: '#67C23A' },
+        2: { text: '和局', color: '#E6A23C' }
+      }
+      const winMatch = winMap[row.is_win] || { text: '--', color: '#909399' }
+
+      const settlementMap = {
+        0: { text: '未结算', color: '#909399' },
+        1: { text: '已结算', color: '#67C23A' },
+        2: { text: '已取消', color: '#F56C6C' }
+      }
+      const settlementMatch = settlementMap[row.settlement_status] || { text: '--', color: '#909399' }
+
+      const returnMap = {
+        0: { text: '未退款', color: '#909399' },
+        1: { text: '退款申请中', color: '#E6A23C' },
+        2: { text: '退款已同意', color: '#67C23A' },
+        3: { text: '退款已驳回', color: '#F56C6C' }
+      }
+      const returnMatch = returnMap[row.return_status] || { text: '--', color: '#909399' }
+
+      const payText = row.pay_status === 1 ? '已支付' : '待付款'
+
+      return [
+        { label: 'ID', prop: 'id', value: row.id },
+        { label: '订单号', prop: 'order_id', value: row.order_id || '--' },
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '赛事ID', prop: 'issue', value: row.issue || '--' },
+        { label: '赛事信息', prop: 'game_info', value: gameInfoHtml, type: 'game_info' },
+        { label: '滚球', prop: 'is_roll', value: row.is_roll === 1 ? '滚球' : '非滚球', type: 'is_roll', rawValue: row.is_roll },
+        { label: '玩法', prop: 'odd_info', value: oddInfoHtml, type: 'odd_info' },
+        { label: '订单状态', prop: 'status', value: statusMatch.text, type: 'status', color: statusMatch.color },
+        { label: '下注失败的原因', prop: 'failure', value: row.failure || '--' },
+        { label: '下注金额(RMB)', prop: 'amount', value: row.amount != null ? row.amount : '--', type: 'amount' },
+        { label: '派奖金额(RMB)', prop: 'win_amount', value: row.win_amount != null ? row.win_amount : '--', type: 'amount' },
+        { label: '盈亏金额(RMB)', prop: 'profit_and_loss', value: row.profit_and_loss != null ? row.profit_and_loss : '--', type: 'amount' },
+        { label: '中奖状态', prop: 'is_win', value: winMatch.text, type: 'is_win', color: winMatch.color },
+        { label: '结算状态', prop: 'settlement_status', value: settlementMatch.text, type: 'settlement_status', color: settlementMatch.color },
+        { label: '支付状态', prop: 'pay_status', value: payText, type: 'pay_status', rawValue: row.pay_status },
+        { label: '支付时间', prop: 'pay_time', value: row.pay_time || '--' },
+        { label: '退款状态', prop: 'return_status', value: returnMatch.text, type: 'return_status', color: returnMatch.color },
+        { label: '备注', prop: 'remark', value: row.remark || '--' },
+        { label: '退款申请时间', prop: 'return_apply_time', value: row.return_apply_time || '--' },
+        { label: '退款处理时间', prop: 'return_operation_time', value: row.return_operation_time || '--' },
+        { label: '创建时间', prop: 'create_time', value: row.create_time || '--' },
+      ]
     }
     }
   },
   },
   mounted() {
   mounted() {
     this.onSubmit()
     this.onSubmit()
   },
   },
   methods: {
   methods: {
-    onValueChange(val) {
-      // 可以在此处处理额外的数据联动逻辑
-    },
+    onValueChange(val) { },
     onSubmit(params = {}) {
     onSubmit(params = {}) {
       this.queryData = params
       this.queryData = params
       this.$refs.table.getList(params)
       this.$refs.table.getList(params)
     },
     },
-    // 处理退款逻辑
-    handleRefund(row) {
-      this.$confirm(`确定要对订单号 ${row.order_id} 进行退款操作吗?`, '退款确认', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(async() => {
-        try {
-          this.loading = true
-          // 调用接口,传入参数 id
-          const res = await orderRefund({ id: [row.id] })
 
 
-          // 这里的判断条件 (res.code === 200) 请根据你实际的后端返回格式进行调整
-          if (res.code === 0) {
-            this.$message.success('退款成功')
-            // 刷新当前表格数据
-            this.onSubmit(this.queryData)
-          } else {
-            this.$message.error(res.msg || '退款失败')
+    // ---------- 退款(返回 Promise,便于弹窗关闭) ----------
+    handleRefund(row) {
+      return new Promise((resolve, reject) => {
+        this.$confirm(`确定要对订单号 ${row.order_id} 进行退款操作吗?`, '退款确认', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(async () => {
+          try {
+            this.loading = true
+            const res = await orderRefund({ id: [row.id] })
+            if (res.code === 0) {
+              this.$message.success('退款成功')
+              this.onSubmit(this.queryData)
+              resolve()
+            } else {
+              this.$message.error(res.msg || '退款失败')
+              reject()
+            }
+          } catch (error) {
+            console.error(error)
+            this.$message.error('退款请求异常')
+            reject()
+          } finally {
+            this.loading = false
           }
           }
-        } catch (error) {
-          console.error(error)
-          this.$message.error('退款请求异常')
-        } finally {
-          this.loading = false
-        }
-      }).catch(() => {
-        // 取消弹窗
+        }).catch(() => {
+          reject() // 用户取消
+        })
       })
       })
     },
     },
-    // 1. 点击列表中的【扣款】按钮触发,用于打开弹窗
+
+    // ---------- 扣款(打开弹窗,不返回 Promise) ----------
     handleWalletOrderDebiting(row) {
     handleWalletOrderDebiting(row) {
-      // 初始化表单数据
       this.debitForm = {
       this.debitForm = {
         amount: undefined,
         amount: undefined,
         remark: '',
         remark: '',
-        // 注意:根据你的后端需求,这里取 row.id 还是 row.order_id
         order_id: row.id,
         order_id: row.id,
         order_type: 'sport'
         order_type: 'sport'
       }
       }
       this.debitDialogVisible = true
       this.debitDialogVisible = true
     },
     },
-
-    // 2. 弹窗内的【确定】按钮触发,用于提交接口
     submitDebitOrder() {
     submitDebitOrder() {
-      this.$refs.debitForm.validate(async(valid) => {
+      this.$refs.debitForm.validate(async (valid) => {
         if (valid) {
         if (valid) {
           try {
           try {
             this.loading = true
             this.loading = true
-            // 提交接口,传入拼装好的表单数据
             const res = await walletOrderDebiting(this.debitForm)
             const res = await walletOrderDebiting(this.debitForm)
-
             if (res.code === 0 || res.success) {
             if (res.code === 0 || res.success) {
               this.$message.success('扣款成功')
               this.$message.success('扣款成功')
-              this.debitDialogVisible = false // 关闭弹窗
-              // 刷新当前表格数据
+              this.debitDialogVisible = false
               this.onSubmit(this.queryData)
               this.onSubmit(this.queryData)
             } else {
             } else {
               this.$message.error(res.msg || '扣款失败')
               this.$message.error(res.msg || '扣款失败')
@@ -521,46 +584,32 @@ export default {
           } finally {
           } finally {
             this.loading = false
             this.loading = false
           }
           }
-        } else {
-          return false
         }
         }
       })
       })
     },
     },
-
-    // 3. 弹窗关闭时重置表单校验状态
     resetDebitForm() {
     resetDebitForm() {
-      if (this.$refs.debitForm) {
-        this.$refs.debitForm.resetFields()
-      }
+      if (this.$refs.debitForm) this.$refs.debitForm.resetFields()
     },
     },
 
 
-
-    // 1. 点击列表中的【充值】按钮触发,用于打开弹窗
+    // ---------- 充值(打开弹窗) ----------
     handleWalletOrderRecharging(row) {
     handleWalletOrderRecharging(row) {
-      // 初始化表单数据
       this.rechargeForm = {
       this.rechargeForm = {
         amount: undefined,
         amount: undefined,
         remark: '',
         remark: '',
-        // 注意确认这里是取 row.id 还是 row.order_id
         order_id: row.id,
         order_id: row.id,
         order_type: 'sport'
         order_type: 'sport'
       }
       }
       this.rechargeDialogVisible = true
       this.rechargeDialogVisible = true
     },
     },
-
-    // 2. 弹窗内的【确定】按钮触发,用于提交充值接口
     submitRechargeOrder() {
     submitRechargeOrder() {
       this.$refs.rechargeForm.validate(async (valid) => {
       this.$refs.rechargeForm.validate(async (valid) => {
         if (valid) {
         if (valid) {
           try {
           try {
             this.loading = true
             this.loading = true
-            // 提交接口,注意这里替换为你真实的充值接口方法名
             const res = await walletOrderTopUp(this.rechargeForm)
             const res = await walletOrderTopUp(this.rechargeForm)
-
             if (res.code === 0 || res.success) {
             if (res.code === 0 || res.success) {
               this.$message.success('充值成功')
               this.$message.success('充值成功')
-              this.rechargeDialogVisible = false // 关闭弹窗
-              // 刷新当前表格数据
+              this.rechargeDialogVisible = false
               this.onSubmit(this.queryData)
               this.onSubmit(this.queryData)
             } else {
             } else {
               this.$message.error(res.msg || '充值失败')
               this.$message.error(res.msg || '充值失败')
@@ -571,27 +620,41 @@ export default {
           } finally {
           } finally {
             this.loading = false
             this.loading = false
           }
           }
-        } else {
-          return false
         }
         }
       })
       })
     },
     },
-
-    // 3. 弹窗关闭时重置表单校验状态
     resetRechargeForm() {
     resetRechargeForm() {
-      if (this.$refs.rechargeForm) {
-        this.$refs.rechargeForm.resetFields()
-      }
+      if (this.$refs.rechargeForm) this.$refs.rechargeForm.resetFields()
+    },
+
+    // ---------- 查看弹窗内操作包装 ----------
+    handleRefundFromView() {
+      // 退款操作:执行退款,成功后不关闭查看弹窗(仅刷新列表)
+      this.handleRefund(this.viewRow)
+        .then(() => {
+          // 退款成功,列表已刷新,查看弹窗保持打开
+          // 若希望更新显示的数据,可在此重新获取该行数据(可选)
+        })
+        .catch(() => {
+          // 用户取消或失败,不做任何事
+        })
+    },
+    handleRechargeFromView() {
+      // 充值:直接打开充值弹窗,不关闭查看弹窗
+      this.handleWalletOrderRecharging(this.viewRow)
+    },
+    handleDeductionFromView() {
+      // 扣款:直接打开扣款弹窗,不关闭查看弹窗
+      this.handleWalletOrderDebiting(this.viewRow)
     }
     }
   }
   }
 }
 }
 </script>
 </script>
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
-/* 强制覆盖 element-ui 表格单元格默认的截断样式 */
 ::v-deep .custom-game-col .cell {
 ::v-deep .custom-game-col .cell {
   white-space: normal !important;
   white-space: normal !important;
   overflow: visible !important;
   overflow: visible !important;
   text-overflow: clip !important;
   text-overflow: clip !important;
 }
 }
-</style>
+</style>

+ 5 - 19
src/views/promoteUsersIndex/index.vue

@@ -1,23 +1,9 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch
-      :loading="loading"
-      :search-form="searchForm"
-      @onValueChange="onValueChange"
-      @submit="onSubmit"
-    />
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="true"
-      :table-options="tableOptions"
-      :columns="columns"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-    />
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="false" :selection="true" :table-options="tableOptions"
+      :columns="columns" :rows-actions="rowsActions" :show-summary="false" :apis="apis"
+      :custom-style="{ height: 'calc(100vh - 150px)' }" />
   </div>
   </div>
 </template>
 </template>
 
 
@@ -64,7 +50,7 @@ export default {
       // API 接口配置
       // API 接口配置
       apis: {
       apis: {
         list: {
         list: {
-          url: 'userFeedback/list', 
+          url: 'userFeedback/list',
           dataParam: 'data.data',
           dataParam: 'data.data',
           resultParam: 'data',
           resultParam: 'data',
           init: false
           init: false

+ 1 - 1
src/views/rebate/backflow/index.vue

@@ -79,7 +79,7 @@ export default {
               value: ['username']
               value: ['username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.user_admin_note ? true : false,
               vShow: (row) => row?.user_admin_note ? true : false,
               value: ['user_admin_note']
               value: ['user_admin_note']
             }
             }

+ 1 - 1
src/views/rebate/list/index.vue

@@ -84,7 +84,7 @@ export default {
               value: ['member.first_name']
               value: ['member.first_name']
             },
             },
            {
            {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.user_admin_note ? true : false,
               vShow: (row) => row?.user_admin_note ? true : false,
               value: ['user_admin_note']
               value: ['user_admin_note']
             }
             }

+ 1 - 1
src/views/treePay/list/index.vue

@@ -101,7 +101,7 @@ export default {
               value: ['username']
               value: ['username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.user_admin_note ? true : false,
               vShow: (row) => row?.user_admin_note ? true : false,
               value: ['user_admin_note']
               value: ['user_admin_note']
             }
             }

+ 1 - 1
src/views/user/userLevel/index.vue

@@ -22,7 +22,7 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="recharge" label="累计充值金额" align="center">
       <el-table-column prop="recharge" label="累计充值金额" align="center">
         <template slot-scope="scope">
         <template slot-scope="scope">
-          {{ scope.row.recharge }} 元
+          <span style="color: #18C80A;font-size: 16px;font-weight: bold;">{{ scope.row.recharge }} 元</span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
       <el-table-column prop="updated_at" label="更新时间" align="center" />
       <el-table-column prop="updated_at" label="更新时间" align="center" />

+ 249 - 6
src/views/user/userList/index.vue

@@ -21,20 +21,159 @@
       :rows-actions="rowsActions" :show-summary="false" :apis="apis" :actionsWidth="300" @headerClick="headerClick"
       :rows-actions="rowsActions" :show-summary="false" :apis="apis" :actionsWidth="300" @headerClick="headerClick"
       :custom-style="{ height: 'calc(100vh - 280px)' }">
       :custom-style="{ height: 'calc(100vh - 280px)' }">
       <template #agent="scoped">
       <template #agent="scoped">
-        <div v-if="scoped.row.agent" style="line-height: 1.5">
-          <div style="font-weight: 500; color: #409eff">
+        <div v-if="scoped.row.agent">
+          <div>
             {{ scoped.row.agent.first_name || "--" }}
             {{ scoped.row.agent.first_name || "--" }}
           </div>
           </div>
-          <div style="font-size: 12px; color: #909399">
+          <div>
             ID: {{ scoped.row.agent.member_id }}
             ID: {{ scoped.row.agent.member_id }}
           </div>
           </div>
-          <div style="font-size: 12px; color: #909399">
+          <div>
             邀请码: {{ scoped.row.agent.user_code }}
             邀请码: {{ scoped.row.agent.user_code }}
           </div>
           </div>
         </div>
         </div>
         <span v-else style="color: #c0c4cc">--</span>
         <span v-else style="color: #c0c4cc">--</span>
       </template>
       </template>
+
+      <!-- 注册来源 -->
+      <template #from="{ row }">
+        <span :style="{
+          color: Number(row.from) === 1 ? '#05A58F' : Number(row.from) === 2 ? '#F3061F' : '#606266'
+        }">
+          {{
+            Number(row.from) === 1 ? '真实用户' :
+              Number(row.from) === 2 ? '虚拟用户' :
+                Number(row.from) === -1 ? 'tg用户' :
+                  Number(row.from) === 0 ? '后台客服账号' : '--'
+          }}
+        </span>
+      </template>
+
+      <!-- 冻结金额 -->
+      <template #wallet="{ row }">
+        <span :style="{
+          color: (row.wallet && Number(row.wallet.frozen_balance) > 0) ? '#F3061F' : '#606266'
+        }">
+          {{ row.wallet ? Number(row.wallet.frozen_balance) : '--' }}
+        </span>
+      </template>
+
+      <!-- 余额宝金额 -->
+      <template #yuebao="{ row }">
+        <span :style="{
+          color: (row.wallet && Number(row.wallet.yuebao) > 0) ? '#05A58F' : '#606266'
+        }">
+          {{ row.wallet ? Number(row.wallet.yuebao) : '--' }}
+        </span>
+      </template>
+
+      <!-- 打码量 -->
+      <template #total_consume="{ row }">
+        <span :style="{
+          color: Number(row.total_consume) > 0 ? '#18C80A' : '#606266'
+        }">
+          {{ row.total_consume != null ? Number(row.total_consume) : '--' }}
+        </span>
+      </template>
+
+      <!-- 是否封号 -->
+      <template #is_banned="{ row }">
+        <span :style="{
+          color: Number(row.is_banned) === 0 ? '#18C80A' : '#F3061F',
+          fontWeight: 'bold'
+        }">
+          {{ Number(row.is_banned) === 0 ? '正常' : '封号' }}
+        </span>
+      </template>
+
+      <!-- 是否封号 -->
+      <template #is_banned="{ row }">
+        <span :style="{
+          color: Number(row.is_banned) === 0 ? '#18C80A' : '#F3061F'
+        }">
+          {{ Number(row.is_banned) === 0 ? '正常' : '封号' }}
+        </span>
+      </template>
+
     </YMTable>
     </YMTable>
+
+    <!-- 用户详情弹窗 -->
+    <Dialog ref="dialogDetail" :dialog-actions="{
+      width: '800px',
+      title: '用户详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <!-- 原有详情展示区 -->
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 400px; overflow-y: auto;">
+          <div v-for="item in detailItems" :key="item.label"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ item.label }}</div>
+            <!-- 三方余额:显示数值 + 一键转出按钮 -->
+            <div v-if="item.label === '三方余额'" style="display: flex; align-items: center; gap: 8px;">
+              <span :style="{ color: item.color || '#303133', fontSize: '15px' }">{{ item.value }}</span>
+              <el-button type="primary" size="mini"
+                @click="sfBalanceTransferClick(detailData.member_id)">一键转出</el-button>
+            </div>
+            <!-- 其他字段 -->
+            <div v-else :style="{ color: item.color || '#303133', fontSize: '15px', wordBreak: 'break-all' }">
+              {{ item.value }}
+            </div>
+          </div>
+        </div>
+
+        <!-- ========== 新增:操作按钮区域 ========== -->
+        <div style="margin-top: 16px; text-align: center; border-top: 1px solid #e4e7ed; padding-top: 16px;">
+          <!-- 充值 -->
+          <el-button type="primary" size="small"
+            @click="rowsActions.find(a => a.key === 'upWallet').method(detailData)">
+            充值
+          </el-button>
+          <!-- 扣款 -->
+          <el-button type="danger" size="small" @click="rowsActions.find(a => a.key === 'unWallet').method(detailData)">
+            扣款
+          </el-button>
+          <!-- 提现地址 -->
+          <el-button type="info" size="small" @click="rowsActions.find(a => a.key === 'address').method(detailData)">
+            提现地址
+          </el-button>
+          <!-- 设置通道 -->
+          <el-button type="warning" size="small"
+            @click="rowsActions.find(a => a.key === 'setChannel').method(detailData)">
+            设置通道
+          </el-button>
+          <!-- 修改密码 -->
+          <el-button type="primary" size="small"
+            @click="rowsActions.find(a => a.key === 'modifyPassword').method(detailData)">
+            修改密码
+          </el-button>
+          <!-- 合并用户 -->
+          <el-button type="danger" size="small"
+            @click="rowsActions.find(a => a.key === 'secret_key').method(detailData)">
+            合并用户
+          </el-button>
+          <!-- 备注 -->
+          <el-button type="info" size="small" @click="rowsActions.find(a => a.key === 'note').method(detailData)">
+            备注
+          </el-button>
+          <!-- 用户日志 -->
+          <el-button type="primary" size="small" @click="rowsActions.find(a => a.key === 'log').method(detailData)">
+            用户日志
+          </el-button>
+          <!-- 封号(仅当未封号) -->
+          <el-button v-if="detailData.is_banned === 0" type="danger" size="small"
+            @click="rowsActions.find(a => a.key === 'banned').method(detailData)">
+            封号
+          </el-button>
+          <!-- 解封(仅当已封号) -->
+          <el-button v-if="detailData.is_banned === 1" type="success" size="small"
+            @click="rowsActions.find(a => a.key === 'jiefeng').method(detailData)">
+            解封
+          </el-button>
+        </div>
+      </template>
+    </Dialog>
+
     <Dialog ref="sfLog" :dialog-actions="{
     <Dialog ref="sfLog" :dialog-actions="{
       width: '800px',
       width: '800px',
       title: '三方余额',
       title: '三方余额',
@@ -283,6 +422,65 @@ export default {
         },
         },
       ];
       ];
     },
     },
+    detailItems() {
+      if (!this.detailData || !Object.keys(this.detailData).length) return [];
+      const row = this.detailData;
+      return [
+        { label: '会员ID', value: row.member_id },
+        { label: '邀请码', value: row.user_code },
+        { label: '会员昵称', value: row.first_name || '--' },
+        {
+          label: '注册来源',
+          value: this.getFromText(row.from),
+          color: Number(row.from) === 1 ? '#05A58F' : Number(row.from) === 2 ? '#F3061F' : '#606266'
+        },
+        { label: '飞机账号', value: row.username || '--' },
+        {
+          label: '上级邀请人',
+          value: row.agent ? `${row.agent.first_name} (ID:${row.agent.member_id}, 邀请码:${row.agent.user_code})` : '--'
+        },
+        { label: '会员等级', value: row.level?.level_name || '--' },
+        {
+          label: '钱包余额',
+          value: row.wallet ? Number(row.wallet.available_balance).toFixed(2) : '--',
+          color: '#409EFF'   // 蓝色
+        },
+        {
+          label: '三方余额',
+          value: row.third_game_total_balance != null ? Number(row.third_game_total_balance).toFixed(2) : '--',
+          color: '#409EFF'   // 蓝色
+        },
+        {
+          label: '冻结金额',
+          value: row.wallet ? Number(row.wallet.frozen_balance) : '--',
+          color: (row.wallet && Number(row.wallet.frozen_balance) > 0) ? '#F3061F' : '#606266'
+        },
+        {
+          label: '余额宝金额',
+          value: row.wallet ? row.wallet.yuebao : '--',
+          color: (row.wallet && Number(row.wallet.yuebao) > 0) ? '#05A58F' : '#606266'
+        },
+        {
+          label: '打码量',
+          value: row.total_consume != null ? Number(row.total_consume) : '--',
+          color: Number(row.total_consume) > 0 ? '#18C80A' : '#606266'
+        },
+        { label: '充值通道', value: this.getChannelName(row.recharge_channel_group_id) },
+        { label: '注册时间', value: row.created_at || '--' },
+        { label: '新增用户', value: this.getNewUserType(row.created_at) },
+        { label: '活跃时间', value: row.last_active_time || '--' },
+        {
+          label: '是否封号',
+          value: row.is_banned === 0 ? '正常' : '封号',
+          color: Number(row.is_banned) === 0 ? '#18C80A' : '#F3061F'
+        },
+        { label: '秘钥', value: row.secret_key || '--' },
+        { label: '访客ID', value: row.visitor_id || '--' },
+        { label: '备注', value: row.admin_note || '--' },
+        { label: '手机号', value: row.phone || '--' },
+        { label: 'IP', value: row.register_ip || '--' },
+      ];
+    }
   },
   },
   data() {
   data() {
     return {
     return {
@@ -359,6 +557,11 @@ export default {
       visibleBasicDrawer: false,
       visibleBasicDrawer: false,
       renderContent: "",
       renderContent: "",
       rowsActions: [
       rowsActions: [
+        {
+          key: "view",
+          label: "查看",
+          method: (row) => this.showDetail(row)
+        },
         {
         {
           key: "upWallet",
           key: "upWallet",
           label: "充值",
           label: "充值",
@@ -584,7 +787,7 @@ export default {
               value: ["username"],
               value: ["username"],
             },
             },
             {
             {
-              label: "异常信息",
+              label: "备注",
               vShow: (row) => (row?.admin_note ? true : false),
               vShow: (row) => (row?.admin_note ? true : false),
               value: ["admin_note"],
               value: ["admin_note"],
             },
             },
@@ -632,7 +835,7 @@ export default {
                 member_id: row.member_id,
                 member_id: row.member_id,
               },
               },
             });
             });
-          },
+          }
         },
         },
         {
         {
           label: "三方余额",
           label: "三方余额",
@@ -760,6 +963,7 @@ export default {
           prop: "register_ip",
           prop: "register_ip",
         },
         },
       ],
       ],
+      detailData: {},
     };
     };
   },
   },
   mounted() {
   mounted() {
@@ -790,6 +994,45 @@ export default {
           this.logLoading = false;
           this.logLoading = false;
         });
         });
     },
     },
+
+    // 转换注册来源文字
+    getFromText(from) {
+      const map = {
+        '-1': 'tg用户',
+        '0': '后台客服账号',
+        '1': '真实用户',
+        '2': '虚拟用户'
+      };
+      return map[from] || '--';
+    },
+
+    // 根据通道组合ID获取名称
+    getChannelName(id) {
+      const group = this.channelGroupList.find(g => g.id === id);
+      return group ? group.name : '--';
+    },
+
+    // 计算新增用户分类(与列表逻辑一致)
+    getNewUserType(created_at) {
+      if (!created_at) return '--';
+      const targetDate = new Date(created_at.replace(/-/g, '/'));
+      const targetTime = targetDate.getTime();
+      const now = new Date();
+      const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
+      const yesterdayStart = todayStart - 24 * 60 * 60 * 1000;
+      const sevenDaysAgoStart = todayStart - 7 * 24 * 60 * 60 * 1000;
+      if (targetTime >= todayStart) return '今天';
+      else if (targetTime >= yesterdayStart && targetTime < todayStart) return '昨天';
+      else if (targetTime >= sevenDaysAgoStart && targetTime < yesterdayStart) return '7天内';
+      else return '7天前';
+    },
+
+    // 打开详情弹窗
+    showDetail(row) {
+      this.detailData = { ...row };
+      this.$refs.dialogDetail.open();
+    },
+
     sfBalanceTransferClick(member_id) {
     sfBalanceTransferClick(member_id) {
       this.logLoading = true;
       this.logLoading = true;
       const params = {
       const params = {

+ 44 - 31
src/views/userReports/index.vue

@@ -1,23 +1,9 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch
-      :loading="loading"
-      :search-form="searchForm"
-      @onValueChange="onValueChange"
-      @submit="onSubmit"
-    />
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="true"
-      :table-options="tableOptions"
-      :columns="columns"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-    />
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="true" :selection="true" :table-options="tableOptions" :columns="columns"
+      :rows-actions="rowsActions" :show-summary="false" :apis="apis"
+      :custom-style="{ height: 'calc(100vh - 150px)' }" />
   </div>
   </div>
 </template>
 </template>
 
 
@@ -42,14 +28,14 @@ export default {
           prop: 'first_name',
           prop: 'first_name',
           clearable: true
           clearable: true
         },
         },
-  // {
-  //         label: '日期范围',
-  //         type: 'daterange',
-  //         prop: 'dateRange',
-  //         valueFormat: 'yyyy-MM-dd',
-  //         startPlaceholder: '开始日期',
-  //         endPlaceholder: '结束日期'
-  //       }
+        // {
+        //         label: '日期范围',
+        //         type: 'daterange',
+        //         prop: 'dateRange',
+        //         valueFormat: 'yyyy-MM-dd',
+        //         startPlaceholder: '开始日期',
+        //         endPlaceholder: '结束日期'
+        //       }
       ],
       ],
 
 
       // 表格右侧操作列 (原 showAction: false,所以留空)
       // 表格右侧操作列 (原 showAction: false,所以留空)
@@ -74,20 +60,47 @@ export default {
 
 
       // 表格列配置 (原 columns)
       // 表格列配置 (原 columns)
       columns: [
       columns: [
-       {
+        {
           label: '会员ID',
           label: '会员ID',
           prop: 'member_id',
           prop: 'member_id',
           width: 120
           width: 120
         },
         },
         {
         {
           label: '会员昵称',
           label: '会员昵称',
-          prop: 'first_name', 
+          prop: 'first_name',
           width: 150
           width: 150
         },
         },
         { prop: 'remarks', label: '用户备注' },
         { prop: 'remarks', label: '用户备注' },
-        { prop: 'recharge', label: '充值' },
-        { prop: 'withdraw', label: '提现' },
-        { prop: 'money', label: '余额' },
+        {
+          label: '充值',
+          prop: 'recharge',
+          html: true,
+          method: (row) => {
+            return row.recharge != null
+              ? `<span style="color: #18C80A;">${row.recharge}</span>`
+              : '--';
+          }
+        },
+        {
+          label: '提现',
+          prop: 'withdraw',
+          html: true,
+          method: (row) => {
+            return row.withdraw != null
+              ? `<span style="color: #F56C6C;">${row.withdraw}</span>`
+              : '--';
+          }
+        },
+        {
+          label: '余额',
+          prop: 'money',
+          html: true,
+          method: (row) => {
+            return row.money != null
+              ? `<span style="color: #0B17FF;">${parseFloat(row.money)}</span>`
+              : '--';
+          }
+        }
       ]
       ]
     }
     }
   },
   },

+ 1 - 1
src/views/wallet/topUp/index.vue

@@ -113,7 +113,7 @@ export default {
               value: ['member.username']
               value: ['member.username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.member.admin_note ? true : false,
               vShow: (row) => row?.member.admin_note ? true : false,
               value: ['member.admin_note']
               value: ['member.admin_note']
             }
             }

+ 148 - 73
src/views/withdraw/ManualTopUp/index.vue

@@ -1,24 +1,19 @@
 <template>
 <template>
   <div class="app-container">
   <div class="app-container">
     <div class="filter-container" style="margin-bottom: 20px;">
     <div class="filter-container" style="margin-bottom: 20px;">
-      <el-select v-model="listQuery.payment_type" placeholder="请选择充值类型" clearable class="filter-item" style="width: 200px; margin-right: 10px;">
+      <el-select v-model="listQuery.payment_type" placeholder="请选择充值类型" clearable class="filter-item"
+        style="width: 200px; margin-right: 10px;">
         <el-option label="微信" value="1" />
         <el-option label="微信" value="1" />
         <el-option label="支付宝" value="2" />
         <el-option label="支付宝" value="2" />
         <el-option label="银行卡" value="3" />
         <el-option label="银行卡" value="3" />
       </el-select>
       </el-select>
       <el-button type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button>
       <el-button type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button>
-      <el-button type="success" icon="el-icon-setting" :disabled="selectedIds.length === 0" @click="handleBatchSetData">批量设置渠道信息</el-button>
+      <el-button type="success" icon="el-icon-setting" :disabled="selectedIds.length === 0"
+        @click="handleBatchSetData">批量设置渠道信息</el-button>
     </div>
     </div>
 
 
-    <el-table
-      v-loading="listLoading"
-      :data="list"
-      border
-      fit
-      highlight-current-row
-      style="width: 100%;height: calc(100% - 120px);"
-      @selection-change="handleSelectionChange"
-    >
+    <el-table v-loading="listLoading" :data="list" border fit highlight-current-row
+      style="width: 100%;height: calc(100% - 120px);" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column prop="id" label="ID" width="80" align="center" />
       <el-table-column prop="id" label="ID" width="80" align="center" />
       <el-table-column prop="order_no" label="订单号" min-width="220" align="center" />
       <el-table-column prop="order_no" label="订单号" min-width="220" align="center" />
@@ -31,16 +26,14 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="payment_type" label="充值渠道" width="150" align="center">
       <el-table-column prop="payment_type" label="充值渠道" width="150" align="center">
         <template slot-scope="{row}">
         <template slot-scope="{row}">
-          {{ patTypeText[row.payment_type] }}
+          <span :style="{ color: paymentTypeColor[row.payment_type] }">
+            {{ patTypeText[row.payment_type] }}
+          </span>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
       <el-table-column prop="payment_type" label="支付凭证" width="150" align="center">
       <el-table-column prop="payment_type" label="支付凭证" width="150" align="center">
         <template slot-scope="{row}">
         <template slot-scope="{row}">
-          <el-image
-            v-if="row.image"
-            style="width: 60px; height: 60px"
-            :src="row.image"
-            :preview-src-list="[row.image]">
+          <el-image v-if="row.image" style="width: 60px; height: 60px" :src="row.image" :preview-src-list="[row.image]">
           </el-image>
           </el-image>
         </template>
         </template>
       </el-table-column>
       </el-table-column>
@@ -53,9 +46,12 @@
       </el-table-column>
       </el-table-column>
       <el-table-column prop="created_at" label="创建时间" width="180" align="center" />
       <el-table-column prop="created_at" label="创建时间" width="180" align="center" />
 
 
-      <el-table-column label="操作" align="center" min-width="220" class-name="small-padding fixed-width">
+      <el-table-column label="操作" align="center" min-width="280" class-name="small-padding fixed-width">
         <template slot-scope="{row}">
         <template slot-scope="{row}">
-          <el-button v-if="row.status === 0" type="primary" size="mini" @click="handleSetSingleData(row)">设置渠道</el-button>
+          <!-- 查看按钮(始终显示) -->
+          <el-button type="primary" size="mini" @click="handleView(row)">查看</el-button>
+          <el-button v-if="row.status === 0" type="primary" size="mini"
+            @click="handleSetSingleData(row)">设置渠道</el-button>
           <el-button v-if="row.status === 5" type="success" size="mini" @click="handlePass(row)">通过</el-button>
           <el-button v-if="row.status === 5" type="success" size="mini" @click="handlePass(row)">通过</el-button>
           <template v-if="row.status === 0 || row.status === 5">
           <template v-if="row.status === 0 || row.status === 5">
             <el-button type="danger" size="mini" @click="handleReject(row)">驳回</el-button>
             <el-button type="danger" size="mini" @click="handleReject(row)">驳回</el-button>
@@ -65,18 +61,12 @@
     </el-table>
     </el-table>
 
 
     <div style="margin-top: 20px; text-align: right;">
     <div style="margin-top: 20px; text-align: right;">
-      <el-pagination
-        background
-        layout="total, prev, pager, next,sizes"
-        :total="total"
-        :current-page.sync="listQuery.page"
-        :page-size="listQuery.limit"
-        :page-sizes="[10, 20, 50, 100]"
-        @current-change="getList"
-        @size-change="handleSizeChange"
-      />
+      <el-pagination background layout="total, prev, pager, next,sizes" :total="total"
+        :current-page.sync="listQuery.page" :page-size="listQuery.limit" :page-sizes="[10, 20, 50, 100]"
+        @current-change="getList" @size-change="handleSizeChange" />
     </div>
     </div>
 
 
+    <!-- 设置渠道配置弹窗(原有 el-dialog) -->
     <el-dialog title="设置人工充值配置" :visible.sync="configDialogVisible" width="500px">
     <el-dialog title="设置人工充值配置" :visible.sync="configDialogVisible" width="500px">
       <el-form ref="configForm" :model="configForm" :rules="configRules" label-width="100px">
       <el-form ref="configForm" :model="configForm" :rules="configRules" label-width="100px">
         <el-form-item label="充值类型" prop="payment_type">
         <el-form-item label="充值类型" prop="payment_type">
@@ -105,31 +95,80 @@
         <el-button type="primary" @click="submitConfigData">确认提交</el-button>
         <el-button type="primary" @click="submitConfigData">确认提交</el-button>
       </div>
       </div>
     </el-dialog>
     </el-dialog>
+
+    <!-- 查看详情弹窗(使用 Dialog 组件) -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '800px',
+      title: '订单详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+
+            <!-- 金额字段:红色加粗 -->
+            <div v-if="field.type === 'amount'" style="color: #F56C6C; font-weight: bold; font-size: 15px;">
+              {{ field.value }}
+            </div>
+
+            <!-- 充值渠道:带颜色 -->
+            <div v-else-if="field.type === 'payment_type'"
+              :style="{ color: paymentTypeColor[field.rawValue] || '#303133', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+
+            <!-- 支付凭证:图片 -->
+            <div v-else-if="field.type === 'image'">
+              <el-image v-if="field.value" style="width: 60px; height: 60px" :src="field.value"
+                :preview-src-list="[field.value]">
+              </el-image>
+              <span v-else style="color: #909399; font-size: 15px;">无</span>
+            </div>
+
+            <!-- 状态:使用 el-tag -->
+            <div v-else-if="field.type === 'status'">
+              <el-tag :type="getTagType(field.rawValue)" size="medium">
+                {{ field.value }}
+              </el-tag>
+            </div>
+
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">
+              {{ field.value }}
+            </div>
+          </div>
+        </div>
+      </template>
+    </Dialog>
   </div>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
-// 引入你提供的 API
-import { getPaymentOrder, paymentOrderSetPayData, paymentOrderManual‌Audit } from '@/api/data'
+// 引入 API 和组件
+import { getPaymentOrder, paymentOrderSetPayData, paymentOrderManualAudit } from '@/api/data'
 import UploadOneImage from '@/components/UploadOneImage'
 import UploadOneImage from '@/components/UploadOneImage'
+import Dialog from "@/components/Dialog/index.vue"
+
 export default {
 export default {
   name: 'ManualRechargeList',
   name: 'ManualRechargeList',
   components: {
   components: {
-    UploadOneImage
+    UploadOneImage,
+    Dialog
   },
   },
   data() {
   data() {
     return {
     return {
-      batchDisabled: true, // 批量设置按钮禁用状态
+      batchDisabled: true,
       list: [],
       list: [],
       total: 0,
       total: 0,
       listLoading: false,
       listLoading: false,
-      selectedIds: [], // 选中的订单ID数组
+      selectedIds: [],
       isDisabledType: false,
       isDisabledType: false,
-      // 列表查询参数
       listQuery: {
       listQuery: {
         page: 1,
         page: 1,
         limit: 20,
         limit: 20,
-        channel: 'rgcz', // 固定传值
+        channel: 'rgcz',
         payment_type: ''
         payment_type: ''
       },
       },
       patTypeText: {
       patTypeText: {
@@ -137,8 +176,11 @@ export default {
         2: '支付宝',
         2: '支付宝',
         3: '银行卡'
         3: '银行卡'
       },
       },
-
-      // 状态映射字典 (根据实际业务情况可自行调整)
+      paymentTypeColor: {
+        1: '#07C160',
+        2: '#1677FF',
+        3: '#F5A623'
+      },
       statusMap: {
       statusMap: {
         0: '待处理',
         0: '待处理',
         1: '处理中',
         1: '处理中',
@@ -147,8 +189,7 @@ export default {
         4: '待用户上传凭证',
         4: '待用户上传凭证',
         5: '待审核',
         5: '待审核',
       },
       },
-
-      // --- 充值配置弹窗数据 ---
+      // 配置弹窗
       configDialogVisible: false,
       configDialogVisible: false,
       configForm: {
       configForm: {
         payment_type: 1,
         payment_type: 1,
@@ -160,18 +201,58 @@ export default {
       configRules: {
       configRules: {
         payment_type: [{ required: true, message: '请选择充值类型', trigger: 'change' }],
         payment_type: [{ required: true, message: '请选择充值类型', trigger: 'change' }],
         payAccount: [{ required: true, message: '请输入收款账号', trigger: 'blur' }]
         payAccount: [{ required: true, message: '请输入收款账号', trigger: 'blur' }]
-      }
+      },
+      // 查看弹窗数据
+      viewRow: null,
+    }
+  },
+  computed: {
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+      return [
+        { label: 'ID', prop: 'id', value: row.id },
+        { label: '订单号', prop: 'order_no', value: row.order_no || '--' },
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '用户名/邮箱', prop: 'first_name', value: row.first_name || '--' },
+        {
+          label: '充值金额',
+          prop: 'amount',
+          value: row.amount,
+          type: 'amount'
+        },
+        {
+          label: '充值渠道',
+          prop: 'payment_type',
+          value: this.patTypeText[row.payment_type] || '--',
+          type: 'payment_type',
+          rawValue: row.payment_type
+        },
+        {
+          label: '支付凭证',
+          prop: 'image',
+          value: row.image,
+          type: 'image'
+        },
+        {
+          label: '状态',
+          prop: 'status',
+          value: this.statusMap[row.status] || '未知状态',
+          type: 'status',
+          rawValue: row.status
+        },
+        { label: '创建时间', prop: 'created_at', value: row.created_at || '--' },
+      ]
     }
     }
   },
   },
   created() {
   created() {
     this.getList()
     this.getList()
   },
   },
   methods: {
   methods: {
-    // 获取列表数据
+    // 获取列表
     getList() {
     getList() {
       this.listLoading = true
       this.listLoading = true
       getPaymentOrder(this.listQuery).then(res => {
       getPaymentOrder(this.listQuery).then(res => {
-        // 根据你提供的接口数据结构解析
         if (res.code === 0 && res.data) {
         if (res.code === 0 && res.data) {
           this.list = res.data.data
           this.list = res.data.data
           this.total = res.data.total
           this.total = res.data.total
@@ -184,26 +265,19 @@ export default {
         this.listLoading = false
         this.listLoading = false
       })
       })
     },
     },
-
-    // 搜索按钮
     handleFilter() {
     handleFilter() {
       this.listQuery.page = 1
       this.listQuery.page = 1
       this.getList()
       this.getList()
     },
     },
-
-    // 表格多选变化事件
     handleSelectionChange(val) {
     handleSelectionChange(val) {
       this.selectedIds = val.map(item => item.id)
       this.selectedIds = val.map(item => item.id)
     },
     },
-
-    // 打开批量设置配置弹窗
     handleBatchSetData() {
     handleBatchSetData() {
-      this.isDisabledType = false;
+      this.isDisabledType = false
       if (this.selectedIds.length === 0) {
       if (this.selectedIds.length === 0) {
         this.$message.warning('请先选择要配置的订单')
         this.$message.warning('请先选择要配置的订单')
         return
         return
       }
       }
-      // 初始化表单
       this.configForm = {
       this.configForm = {
         payment_type: 1,
         payment_type: 1,
         payName: '',
         payName: '',
@@ -216,12 +290,9 @@ export default {
         this.$refs.configForm.clearValidate()
         this.$refs.configForm.clearValidate()
       })
       })
     },
     },
-
-    // 提交配置数据
     submitConfigData() {
     submitConfigData() {
       this.$refs.configForm.validate(valid => {
       this.$refs.configForm.validate(valid => {
         if (valid) {
         if (valid) {
-          // 组装 pay_data 格式为 JSON 字符串
           const payDataObj = {
           const payDataObj = {
             payName: this.configForm.payName,
             payName: this.configForm.payName,
             payAccount: this.configForm.payAccount
             payAccount: this.configForm.payAccount
@@ -243,20 +314,13 @@ export default {
             } else {
             } else {
               this.$message.error(res.msg || '操作失败')
               this.$message.error(res.msg || '操作失败')
             }
             }
-
-            this.getList()
           })
           })
         }
         }
       })
       })
     },
     },
-
-    // 设置单行渠道信息
     handleSetSingleData(row) {
     handleSetSingleData(row) {
-      this.isDisabledType = true;
-      // 将当前行ID设为选中,复用批量设置的逻辑
+      this.isDisabledType = true
       this.selectedIds = [row.id]
       this.selectedIds = [row.id]
-
-      // 初始化表单
       this.configForm = {
       this.configForm = {
         payment_type: row.payment_type,
         payment_type: row.payment_type,
         payName: '',
         payName: '',
@@ -269,15 +333,13 @@ export default {
         this.$refs.configForm.clearValidate()
         this.$refs.configForm.clearValidate()
       })
       })
     },
     },
-
-    // 直接通过操作
     handlePass(row) {
     handlePass(row) {
       this.$confirm('确定要通过该人工充值吗?', '提示', {
       this.$confirm('确定要通过该人工充值吗?', '提示', {
         confirmButtonText: '确定',
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         cancelButtonText: '取消',
         type: 'warning'
         type: 'warning'
       }).then(() => {
       }).then(() => {
-        paymentOrderManualAudit({ id: row.id, status: 2, remark: '' }).then(res => {
+        paymentOrderManualAudit({ id: row.id, status: 2, remark: '' }).then(res => {
           if (res.code === 0) {
           if (res.code === 0) {
             this.$message.success('审核已通过')
             this.$message.success('审核已通过')
             this.getList()
             this.getList()
@@ -286,10 +348,8 @@ export default {
             this.getList()
             this.getList()
           }
           }
         })
         })
-      }).catch(() => {})
+      }).catch(() => { })
     },
     },
-
-    // 驳回操作(带输入原因)
     handleReject(row) {
     handleReject(row) {
       this.$prompt('请输入驳回原因', '提示', {
       this.$prompt('请输入驳回原因', '提示', {
         confirmButtonText: '确定驳回',
         confirmButtonText: '确定驳回',
@@ -297,7 +357,7 @@ export default {
         inputType: 'textarea',
         inputType: 'textarea',
         inputPlaceholder: '请输入审核备注(驳回时建议填写原因)'
         inputPlaceholder: '请输入审核备注(驳回时建议填写原因)'
       }).then(({ value }) => {
       }).then(({ value }) => {
-        paymentOrderManualAudit({ id: row.id, status: 3, remark: value || '' }).then(res => {
+        paymentOrderManualAudit({ id: row.id, status: 3, remark: value || '' }).then(res => {
           if (res.code === 0) {
           if (res.code === 0) {
             this.$message.success('审核已驳回')
             this.$message.success('审核已驳回')
             this.getList()
             this.getList()
@@ -306,20 +366,34 @@ export default {
             this.getList()
             this.getList()
           }
           }
         })
         })
-      }).catch(() => {})
+      }).catch(() => { })
     },
     },
-
     handleSizeChange(e) {
     handleSizeChange(e) {
       this.listQuery.page = 1
       this.listQuery.page = 1
       this.listQuery.limit = e
       this.listQuery.limit = e
       this.getList()
       this.getList()
+    },
+
+    // ---- 查看功能 ----
+    handleView(row) {
+      // 保存当前行数据
+      this.viewRow = { ...row }
+      // 打开 Dialog
+      this.$refs.viewDialog.open()
+    },
+    // 根据状态值返回 el-tag 的 type
+    getTagType(status) {
+      if (status === 1) return 'info'
+      if (status === 2) return 'success'
+      if (status === 5) return 'warning'
+      return 'danger'
     }
     }
   }
   }
 }
 }
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>
-.app-container{
+.app-container {
   padding: 20px;
   padding: 20px;
   margin: 20px;
   margin: 20px;
   background-color: #fff;
   background-color: #fff;
@@ -327,8 +401,9 @@ export default {
   width: calc(100% - 40px);
   width: calc(100% - 40px);
   height: calc(100vh - 86px);
   height: calc(100vh - 86px);
 }
 }
+
 .filter-container {
 .filter-container {
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
 }
 }
-</style>
+</style>

+ 144 - 59
src/views/withdraw/Manualwithdrawal/index.vue

@@ -1,28 +1,86 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit"/>
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="true"
-      :table-options="tableOptions"
-      :edit-form="editForm"
-      :edit-config="editConfig"
-      :columns="columns"
-      :actions-width="120"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :alertTip="alertTip"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-      @onResponse="onResponse"
-    />
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="true" :selection="true" :table-options="tableOptions"
+      :edit-form="editForm" :edit-config="editConfig" :columns="columns" :actions-width="180"
+      :rows-actions="rowsActions" :show-summary="false" :apis="apis" :alertTip="alertTip"
+      :custom-style="{ height: 'calc(100vh - 150px)' }" @onResponse="onResponse">
+      <!-- 提现金额 -->
+      <template #amount="{ row }">
+        <span style="color: #18C80A;">
+          {{ row.amount != null ? Number(row.amount).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 手续费 -->
+      <template #fee="{ row }">
+        <span style="color: #18C80A;">
+          {{ row.fee != null ? Number(row.fee).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 是否加锁 -->
+      <template #is_locked="{ row }">
+        <span :style="{ color: row.is_locked === 1 ? '#F3061F' : '#18C80A' }">
+          {{ row.is_locked === 1 ? '是' : '否' }}
+        </span>
+      </template>
+
+      <!-- 状态 -->
+      <template #status="{ row }">
+        <span :style="{ color: statusColorMap[row.status] || '#606266' }">
+          {{ getStatusLabel(row.status) }}
+        </span>
+      </template>
+    </YMTable>
+
+    <!-- 原有的空 Dialog(保留) -->
     <Dialog ref="dialog">
     <Dialog ref="dialog">
-      <template slot="content"/>
+      <template slot="content" />
+    </Dialog>
+
+    <!-- 查看详情弹窗 -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '800px',
+      title: '提现订单详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+               style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+
+            <!-- 提现金额 / 手续费:绿色 -->
+            <div v-if="field.type === 'amount' || field.type === 'fee'" style="color: #18C80A; font-size: 15px;">
+              {{ field.value }}
+            </div>
+
+            <!-- 是否加锁 -->
+            <div v-else-if="field.type === 'is_locked'" :style="{ color: field.rawValue === 1 ? '#F3061F' : '#18C80A', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+
+            <!-- 状态 -->
+            <div v-else-if="field.type === 'status'" :style="{ color: statusColorMap[field.rawValue] || '#606266', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+
+            <!-- 信息(银行/账户)-- 使用 v-html 支持换行 -->
+            <div v-else-if="field.type === 'info'" style="font-size: 15px; color: #0B17FF; line-height: 1.6;" v-html="field.value">
+            </div>
+
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">
+              {{ field.value }}
+            </div>
+          </div>
+        </div>
+      </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
 </template>
 </template>
+
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
 import { paymentOrderManualRGTXAudit, withdrawssetRmbNote, rmbPaymentOrderSetIsLocked } from '@/api/data'
 import { paymentOrderManualRGTXAudit, withdrawssetRmbNote, rmbPaymentOrderSetIsLocked } from '@/api/data'
@@ -33,38 +91,18 @@ export default {
   },
   },
   data() {
   data() {
     const statusOpt = [
     const statusOpt = [
-      {
-        value: 0,
-        label: '待处理'
-      },
-      {
-        value: 1,
-        label: '处理中'
-      },
-      {
-        value: 2,
-        label: '成功'
-      },
-      {
-        value: 3,
-        label: '失败'
-      },
-      {
-        value: 4,
-        label: '待用户提交凭证'
-      },
-      {
-        value: 5,
-        label: '待人工审核'
-      },
-      {
-        value: 6,
-        label: '已撤回'
-      }
+      { value: 0, label: '待处理' },
+      { value: 1, label: '处理中' },
+      { value: 2, label: '成功' },
+      { value: 3, label: '失败' },
+      { value: 4, label: '待用户提交凭证' },
+      { value: 5, label: '待人工审核' },
+      { value: 6, label: '已撤回' }
     ]
     ]
     return {
     return {
       loading: false,
       loading: false,
-      alertTip:'',
+      alertTip: '',
+      viewRow: null,
       searchForm: [
       searchForm: [
         {
         {
           label: '会员ID',
           label: '会员ID',
@@ -108,7 +146,7 @@ export default {
               value: ['first_name']
               value: ['first_name']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.admin_note ? true : false,
               vShow: (row) => row?.admin_note ? true : false,
               value: ['admin_note']
               value: ['admin_note']
             }
             }
@@ -124,10 +162,10 @@ export default {
           method: (row) => Number(row.amount)?.toFixed(2)
           method: (row) => Number(row.amount)?.toFixed(2)
         },
         },
         {
         {
-          label: '银行卡',
+          label: '信息',
           width: '180px',
           width: '180px',
           html: true,
           html: true,
-          method: (row) => `${row?.account}(${row?.bank_name})<br/>账户:${row?.card_no} `
+          method: (row) => `<span style="color: #0B17FF;">${row?.account}(${row?.bank_name})<br/>账户:${row?.card_no}</span>`
         },
         },
         {
         {
           label: '手续费',
           label: '手续费',
@@ -154,6 +192,7 @@ export default {
         },
         },
         {
         {
           label: '状态',
           label: '状态',
+          prop: 'status',
           method: (row) => {
           method: (row) => {
             return statusOpt.filter(item => item.value === row.status)[0]?.label
             return statusOpt.filter(item => item.value === row.status)[0]?.label
           }
           }
@@ -172,6 +211,14 @@ export default {
         }
         }
       ],
       ],
       rowsActions: [
       rowsActions: [
+        // 查看按钮放在最前面
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.handleView(row)
+          }
+        },
         {
         {
           key: 'lock',
           key: 'lock',
           label: '上锁',
           label: '上锁',
@@ -192,7 +239,7 @@ export default {
                   message: '操作成功'
                   message: '操作成功'
                 })
                 })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -215,7 +262,7 @@ export default {
                   message: '操作成功'
                   message: '操作成功'
                 })
                 })
               })
               })
-            }).catch(() => {})
+            }).catch(() => { })
           }
           }
         },
         },
         {
         {
@@ -291,10 +338,40 @@ export default {
         }
         }
       },
       },
       editForm: [],
       editForm: [],
-      editConfig: {}
+      editConfig: {},
+      statusOpt: statusOpt,
+      statusColorMap: {
+        0: '#E6A23C',
+        1: '#409EFF',
+        2: '#67C23A',
+        3: '#F56C6C',
+        4: '#909399',
+        5: '#E6A23C',
+        6: '#909399'
+      }
     }
     }
   },
   },
-  created() {
+  computed: {
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+      // 构造信息字段,使用 <br/> 换行
+      const infoHtml = `${row.account || ''}(${row.bank_name || ''})<br/>账户:${row.card_no || ''}`
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '订单号', prop: 'order_no', value: row.order_no || '--' },
+        { label: '提现金额', prop: 'amount', value: row.amount != null ? Number(row.amount).toFixed(2) : '--', type: 'amount' },
+        { label: '信息', prop: 'info', value: infoHtml, type: 'info' },
+        { label: '手续费', prop: 'fee', value: row.fee != null ? Number(row.fee).toFixed(2) : '--', type: 'fee' },
+        { label: '类型', prop: 'type', value: { 1: '代收', 2: '代付', 3: '人工充值', 4: '人工提现' }[row.type] || '--' },
+        { label: '是否加锁', prop: 'is_locked', value: row.is_locked === 1 ? '是' : '否', type: 'is_locked', rawValue: row.is_locked },
+        { label: '状态', prop: 'status', value: this.getStatusLabel(row.status), type: 'status', rawValue: row.status },
+        { label: '原因', prop: 'remark', value: row.remark || '--' },
+        { label: '备注', prop: 'admin_note', value: row.admin_note || '--' },
+        { label: '申请时间', prop: 'created_at', value: row.created_at || '--' },
+      ]
+    }
   },
   },
   mounted() {
   mounted() {
     this.onSubmit()
     this.onSubmit()
@@ -303,6 +380,10 @@ export default {
     onResponse(data) {
     onResponse(data) {
       this.alertTip = `总金额:${data.total_amount}(RMB);已处理:${data.total_success}(RMB);失败金额:${data.total_fail}(RMB)`
       this.alertTip = `总金额:${data.total_amount}(RMB);已处理:${data.total_success}(RMB);失败金额:${data.total_fail}(RMB)`
     },
     },
+    getStatusLabel(status) {
+      const found = this.statusOpt.find(item => item.value === status)
+      return found ? found.label : '--'
+    },
     getStatus(row) {
     getStatus(row) {
       if (row.status === 3) {
       if (row.status === 3) {
         this.$prompt('请输入原因', '提示', {
         this.$prompt('请输入原因', '提示', {
@@ -330,7 +411,7 @@ export default {
           cancelButtonText: '取消',
           cancelButtonText: '取消',
           type: 'warning'
           type: 'warning'
         }).then(() => {
         }).then(() => {
-          paymentOrderManualRGTXAudit({...row,  is_rgtx: 1,})
+          paymentOrderManualRGTXAudit({ ...row, is_rgtx: 1 })
             .then(() => {
             .then(() => {
               this.onSubmit()
               this.onSubmit()
               this.$message({
               this.$message({
@@ -342,11 +423,15 @@ export default {
       }
       }
     },
     },
     onValueChange(val) {
     onValueChange(val) {
-
     },
     },
     onSubmit(params) {
     onSubmit(params) {
-      this.$refs.table.getList({...params, type: 4})
+      this.$refs.table.getList({ ...params, type: 4 })
+    },
+    // 查看功能
+    handleView(row) {
+      this.viewRow = { ...row }
+      this.$refs.viewDialog.open()
     }
     }
   }
   }
 }
 }
-</script>
+</script>

+ 103 - 42
src/views/withdraw/MemberBonus/index.vue

@@ -1,28 +1,71 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit"/>
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="false"
-      :table-options="tableOptions"
-      :edit-form="editForm"
-      :edit-config="editConfig"
-      :columns="columns"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :alertTip="alertTip"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-      @onResponse="onResponse"
-    />
-    <!-- 自定义弹窗 -->
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="true" :selection="false" :table-options="tableOptions"
+      :edit-form="editForm" :edit-config="editConfig" :columns="columns" :rows-actions="rowsActions"
+      :show-summary="false" :apis="apis" :alertTip="alertTip" :custom-style="{ height: 'calc(100vh - 150px)' }"
+      :actions-width="120" @onResponse="onResponse">
+      <!-- 变动后余额 -->
+      <template #before_balance="{ row }">
+        <span style="color: #18C80A;">
+          {{ row.before_balance != null ? Number(row.before_balance).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 变动金额 -->
+      <template #amount="{ row }">
+        <span :style="{
+          color: Number(row.amount) > 0 ? '#18C80A' : Number(row.amount) < 0 ? '#F56C6C' : '#909399'
+        }">
+          {{ row.amount != null ? Number(row.amount).toFixed(2) : '--' }}
+        </span>
+      </template>
+
+      <!-- 类型(change_type) -->
+      <template #change_type="{ row }">
+        <span style="color: #0B17FF;">
+          {{ row.change_type || '--' }}
+        </span>
+      </template>
+    </YMTable>
+
+    <!-- 原有的空弹窗(保留) -->
     <Dialog ref="dialog">
     <Dialog ref="dialog">
-      <template slot="content"/>
+      <template slot="content" />
+    </Dialog>
+
+    <!-- ========== 查看详情弹窗(无底部关闭按钮) ========== -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '800px',
+      title: '余额变动详情',
+      confirmButtom: false,
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 变动前余额 / 变动后余额:绿色 -->
+            <div v-if="field.type === 'balance'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <!-- 变动金额:正绿负红 -->
+            <div v-else-if="field.type === 'amount'"
+              :style="{ color: field.rawValue > 0 ? '#18C80A' : field.rawValue < 0 ? '#F56C6C' : '#909399', fontSize: '15px' }">
+              {{ field.value }}</div>
+            <!-- 类型(change_type):蓝色 -->
+            <div v-else-if="field.type === 'change_type'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}
+            </div>
+            <!-- 资金类型:显示“可用余额”/“冻结金额” -->
+            <div v-else-if="field.type === 'fund_type'" style="color: #303133; font-size: 15px;">{{ field.value }}</div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+        <!-- 底部无额外按钮,仅右上角 X 关闭 -->
+      </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
 </template>
 </template>
+
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
 
 
@@ -35,6 +78,8 @@ export default {
       loading: false,
       loading: false,
       visibleBasicDrawer: false,
       visibleBasicDrawer: false,
       alertTip: '',
       alertTip: '',
+      // 新增:存储当前查看的行数据
+      viewRow: null,
       searchForm: [
       searchForm: [
         {
         {
           label: '会员ID',
           label: '会员ID',
@@ -43,7 +88,7 @@ export default {
           default: '',
           default: '',
           clearable: true
           clearable: true
         },
         },
-         {
+        {
           label: '会员昵称',
           label: '会员昵称',
           type: 'input',
           type: 'input',
           prop: 'first_name',
           prop: 'first_name',
@@ -63,10 +108,9 @@ export default {
           default: '',
           default: '',
           clearable: true
           clearable: true
         }
         }
-
       ],
       ],
       columns: [
       columns: [
-          {
+        {
           label: '会员ID',
           label: '会员ID',
           prop: 'member_id',
           prop: 'member_id',
           width: 120
           width: 120
@@ -86,7 +130,7 @@ export default {
               value: ['member.username']
               value: ['member.username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.member.admin_note ? true : false,
               vShow: (row) => row?.member.admin_note ? true : false,
               value: ['member.admin_note']
               value: ['member.admin_note']
             }
             }
@@ -95,27 +139,26 @@ export default {
         {
         {
           label: '变动前余额',
           label: '变动前余额',
           prop: 'after_balance',
           prop: 'after_balance',
-          method: (row) => Number(row.before_balance)?.toFixed(2)
+          method: (row) => Number(row.after_balance)?.toFixed(2)
         },
         },
         {
         {
           label: '变动金额',
           label: '变动金额',
           prop: 'amount',
           prop: 'amount',
           method: (row) => Number(row.amount)?.toFixed(2)
           method: (row) => Number(row.amount)?.toFixed(2)
         },
         },
-
         {
         {
           label: '变动后余额',
           label: '变动后余额',
           prop: 'before_balance',
           prop: 'before_balance',
-          method: (row) => Number(row.after_balance)?.toFixed(2)
+          method: (row) => Number(row.before_balance)?.toFixed(2)
         },
         },
         {
         {
           label: '时间',
           label: '时间',
           prop: 'created_at'
           prop: 'created_at'
         },
         },
-          {
+        {
           label: '资金类型',
           label: '资金类型',
           prop: 'type',
           prop: 'type',
-             method: (row) => Number(row.type) === 1 ? '可用余额' : '冻结金额'
+          method: (row) => Number(row.type) === 1 ? '可用余额' : '冻结金额'
         },
         },
         {
         {
           label: '类型',
           label: '类型',
@@ -130,7 +173,17 @@ export default {
           prop: 'remark'
           prop: 'remark'
         }
         }
       ],
       ],
-      rowsActions: [],
+      rowsActions: [
+        // ---------- 新增查看按钮 ----------
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.viewRow = { ...row };
+            this.$refs.viewDialog.open();
+          }
+        }
+      ],
       apis: {
       apis: {
         list: {
         list: {
           url: 'balance/log',
           url: 'balance/log',
@@ -148,8 +201,27 @@ export default {
       member_id: ''
       member_id: ''
     }
     }
   },
   },
+  computed: {
+    // 新增:详情弹窗字段列表
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+      const fundTypeMap = { 1: '可用余额', 2: '冻结金额' }
+      return [
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        { label: '变动前余额', prop: 'after_balance', value: row.after_balance != null ? Number(row.after_balance).toFixed(2) : '--', type: 'balance' },
+        { label: '变动金额', prop: 'amount', value: row.amount != null ? Number(row.amount).toFixed(2) : '--', type: 'amount', rawValue: Number(row.amount) },
+        { label: '变动后余额', prop: 'before_balance', value: row.before_balance != null ? Number(row.before_balance).toFixed(2) : '--', type: 'balance' },
+        { label: '时间', prop: 'created_at', value: row.created_at || '--' },
+        { label: '资金类型', prop: 'type', value: fundTypeMap[row.type] || '--', type: 'fund_type' },
+        { label: '类型', prop: 'change_type', value: row.change_type || '--', type: 'change_type' },
+        { label: '关联ID', prop: 'related_id', value: row.related_id || '--' },
+        { label: '说明', prop: 'remark', value: row.remark || '--' },
+      ]
+    }
+  },
   created() {
   created() {
-    // 获取参数
     this.member_id = this.$route.query.member_id
     this.member_id = this.$route.query.member_id
     if (this.member_id) {
     if (this.member_id) {
       this.searchForm[0] = Object.assign({}, this.searchForm[0], {
       this.searchForm[0] = Object.assign({}, this.searchForm[0], {
@@ -160,22 +232,13 @@ export default {
   },
   },
   methods: {
   methods: {
     initDateRange() {
     initDateRange() {
-      // const endDate = new Date()
-      // const startDate = new Date()
-      // startDate.setDate(startDate.getDate() - 7)
-      // this.searchForm[2] = Object.assign({}, this.searchForm[2], {
-      //   default: [this.formatDate(startDate), this.formatDate(endDate)]
-      // })
       this.$nextTick(() => {
       this.$nextTick(() => {
         this.$refs.table.getList({
         this.$refs.table.getList({
           member_id: this.member_id,
           member_id: this.member_id,
           is_fancai: 1
           is_fancai: 1
-          // start_time: this.formatDate(startDate),
-          // end_time: this.formatDate(endDate)
         })
         })
       })
       })
     },
     },
-    // 格式化日期
     formatDate(date) {
     formatDate(date) {
       const year = date.getFullYear()
       const year = date.getFullYear()
       const month = String(date.getMonth() + 1).padStart(2, '0')
       const month = String(date.getMonth() + 1).padStart(2, '0')
@@ -184,7 +247,6 @@ export default {
     },
     },
     handleSubmit(formData) {
     handleSubmit(formData) {
       console.log('提交数据:', formData)
       console.log('提交数据:', formData)
-      // 调用API提交数据
     },
     },
     onResponse(data) {
     onResponse(data) {
       console.log(data, 'data')
       console.log(data, 'data')
@@ -198,7 +260,6 @@ export default {
       })
       })
     },
     },
     onValueChange(val) {
     onValueChange(val) {
-
     },
     },
     onSubmit(params = {}) {
     onSubmit(params = {}) {
       const start_time = params?.created_range && params?.created_range.length > 1 ? `${params.created_range[0]}` : null
       const start_time = params?.created_range && params?.created_range.length > 1 ? `${params.created_range[0]}` : null
@@ -208,4 +269,4 @@ export default {
     }
     }
   }
   }
 }
 }
-</script>
+</script>

+ 1 - 1
src/views/withdraw/listRMB/index.vue

@@ -108,7 +108,7 @@ export default {
               value: ['first_name']
               value: ['first_name']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.admin_note ? true : false,
               vShow: (row) => row?.admin_note ? true : false,
               value: ['admin_note']
               value: ['admin_note']
             }
             }

+ 1 - 1
src/views/withdraw/listUSDT/index.vue

@@ -94,7 +94,7 @@ export default {
               value: ['username']
               value: ['username']
             },
             },
             {
             {
-              label: '异常信息',
+              label: '备注',
               vShow: (row) => row?.user_admin_note ? true : false,
               vShow: (row) => row?.user_admin_note ? true : false,
               value: ['user_admin_note']
               value: ['user_admin_note']
             }
             }

+ 99 - 36
src/views/yuebao/index.vue

@@ -1,30 +1,40 @@
 <template>
 <template>
   <div class="new-app-container layout-vertical">
   <div class="new-app-container layout-vertical">
-    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit"/>
-    <YMTable
-      ref="table"
-      :table-key="1"
-      :index="true"
-      :selection="false"
-      :columns="columns"
-      :rows-actions="rowsActions"
-      :show-summary="false"
-      :apis="apis"
-      :custom-style="{ height: 'calc(100vh - 150px)' }"
-    />
+    <YMTableSearch :loading="loading" :search-form="searchForm" @onValueChange="onValueChange" @submit="onSubmit" />
+    <YMTable ref="table" :table-key="1" :index="true" :selection="false" :columns="columns" :rows-actions="rowsActions"
+      :show-summary="false" :apis="apis" :custom-style="{ height: 'calc(100vh - 150px)' }" :actions-width="120">
+      <!-- 状态插槽 -->
+      <template #status="{ row }">
+        <span :style="{
+          color: row.status === 1 ? '#18C80A' : '#F3061F'
+        }">
+          {{ row.status === 1 ? '持仓中' : '已转出' }}
+        </span>
+      </template>
+
+      <!-- 剩余本金插槽 -->
+      <template #surplus_principal="{ row }">
+        <span style="color: #18C80A;">
+          {{ row.surplus_principal != null ? row.surplus_principal : '--' }}
+        </span>
+      </template>
 
 
-    <Dialog
-      ref="dialogLog"
-      :dialog-actions="{
-        width: '800px',
-        title: '余额宝日志',
-        confirmButtom: false // 仅用于查看,隐藏底部的确定按钮
-      }"
-    >
+      <!-- 日利率插槽 -->
+      <template #daily_interest_rate="{ row }">
+        <span style="color: #0B17FF;">
+          {{ row.daily_interest_rate != null ? row.daily_interest_rate : '--' }}
+        </span>
+      </template>
+    </YMTable>
+
+    <!-- 余额宝日志弹窗(原有) -->
+    <Dialog ref="dialogLog" :dialog-actions="{
+      width: '800px',
+      title: '余额宝日志',
+      confirmButtom: false
+    }">
       <template slot="content">
       <template slot="content">
         <el-table :data="logTableData" border stripe height="400px" v-loading="logLoading">
         <el-table :data="logTableData" border stripe height="400px" v-loading="logLoading">
-          <!-- <el-table-column prop="id" label="日志ID" align="center" width="80" />
-          <el-table-column prop="item_id" label="持仓ID" align="center" width="80" /> -->
           <el-table-column prop="type" label="操作类型" align="center" />
           <el-table-column prop="type" label="操作类型" align="center" />
           <el-table-column prop="amount" label="操作金额" align="center" />
           <el-table-column prop="amount" label="操作金额" align="center" />
           <el-table-column prop="hold_hours" label="持有时间(小时)" align="center" />
           <el-table-column prop="hold_hours" label="持有时间(小时)" align="center" />
@@ -37,6 +47,35 @@
         </el-table>
         </el-table>
       </template>
       </template>
     </Dialog>
     </Dialog>
+
+    <!-- ========== 新增:查看详情弹窗 ========== -->
+    <Dialog ref="viewDialog" :dialog-actions="{
+      width: '800px',
+      title: '持仓详情',
+      confirmButtom: false
+    }">
+      <template slot="content">
+        <div style="display: flex; flex-wrap: wrap; gap: 12px; padding: 10px 0; max-height: 500px; overflow-y: auto;">
+          <div v-for="field in viewFields" :key="field.prop"
+            style="flex: 0 0 calc(33.33% - 12px); background: #f5f7fa; border-radius: 6px; padding: 12px 16px; box-sizing: border-box; border: 1px solid #e4e7ed;">
+            <div style="font-size: 13px; color: #909399; margin-bottom: 4px;">{{ field.label }}</div>
+            <!-- 状态:持仓中绿色 / 已转出红色 -->
+            <div v-if="field.type === 'status'"
+              :style="{ color: field.rawValue === 1 ? '#18C80A' : '#F3061F', fontSize: '15px' }">
+              {{ field.value }}
+            </div>
+            <!-- 剩余本金 / 初始本金:绿色 -->
+            <div v-else-if="field.type === 'principal'" style="color: #18C80A; font-size: 15px;">{{ field.value }}</div>
+            <!-- 日利率:蓝色 -->
+            <div v-else-if="field.type === 'rate'" style="color: #0B17FF; font-size: 15px;">{{ field.value }}</div>
+            <!-- 时间字段 -->
+            <div v-else-if="field.type === 'time'" style="color: #606266; font-size: 15px;">{{ field.value }}</div>
+            <!-- 普通字段 -->
+            <div v-else style="color: #303133; font-size: 15px; word-break: break-all;">{{ field.value }}</div>
+          </div>
+        </div>
+      </template>
+    </Dialog>
   </div>
   </div>
 </template>
 </template>
 
 
@@ -52,7 +91,8 @@ export default {
   data() {
   data() {
     return {
     return {
       loading: false,
       loading: false,
-      // 搜索表单配置
+      // 新增:存储当前查看的行数据
+      viewRow: null,
       searchForm: [
       searchForm: [
         {
         {
           label: '会员ID',
           label: '会员ID',
@@ -60,7 +100,7 @@ export default {
           prop: 'member_id',
           prop: 'member_id',
           clearable: true
           clearable: true
         },
         },
-         {
+        {
           label: '会员昵称',
           label: '会员昵称',
           type: 'input',
           type: 'input',
           prop: 'first_name',
           prop: 'first_name',
@@ -73,29 +113,34 @@ export default {
           clearable: true
           clearable: true
         }
         }
       ],
       ],
-      // 列表接口配置
       apis: {
       apis: {
         list: {
         list: {
           url: 'yuebao/item',
           url: 'yuebao/item',
           dataParam: 'data.data',
           dataParam: 'data.data',
           resultParam: 'data',
           resultParam: 'data',
-          init: true // 页面加载时自动请求列表
+          init: true
         }
         }
       },
       },
-      // 列表操作列配置
       rowsActions: [
       rowsActions: [
+        // ========== 新增:查看按钮(放在首位) ==========
+        {
+          key: 'view',
+          label: '查看',
+          method: (row) => {
+            this.viewRow = { ...row }
+            this.$refs.viewDialog.open()
+          }
+        },
         {
         {
           key: 'log',
           key: 'log',
           label: '查看日志',
           label: '查看日志',
           method: (row) => {
           method: (row) => {
             this.logTableData = []
             this.logTableData = []
             this.$refs.dialogLog.open()
             this.$refs.dialogLog.open()
-            // 取当前行的 user_id 查询日志
             this.getLogList(row.user_id)
             this.getLogList(row.user_id)
           }
           }
         }
         }
       ],
       ],
-      // 列表展示字段
       columns: [
       columns: [
         {
         {
           label: '记录ID',
           label: '记录ID',
@@ -105,7 +150,7 @@ export default {
           label: '会员ID',
           label: '会员ID',
           prop: 'member_id'
           prop: 'member_id'
         },
         },
-         {
+        {
           label: '会员昵称',
           label: '会员昵称',
           type: 'input',
           type: 'input',
           prop: 'first_name',
           prop: 'first_name',
@@ -142,30 +187,49 @@ export default {
           width: 160
           width: 160
         }
         }
       ],
       ],
-      // 日志弹窗数据
       logTableData: [],
       logTableData: [],
       logLoading: false,
       logLoading: false,
     }
     }
   },
   },
+  computed: {
+    // 新增:详情弹窗字段列表
+    viewFields() {
+      if (!this.viewRow) return []
+      const row = this.viewRow
+      return [
+        { label: '记录ID', prop: 'id', value: row.id },
+        { label: '会员ID', prop: 'member_id', value: row.member_id },
+        { label: '会员昵称', prop: 'first_name', value: row.first_name || '--' },
+        {
+          label: '状态',
+          prop: 'status',
+          value: row.status === 1 ? '持仓中' : '已转出',
+          type: 'status',
+          rawValue: row.status
+        },
+        { label: '初始本金', prop: 'principal', value: row.principal != null ? row.principal : '--', type: 'principal' },
+        { label: '剩余本金', prop: 'surplus_principal', value: row.surplus_principal != null ? row.surplus_principal : '--', type: 'principal' },
+        { label: '日利率', prop: 'daily_interest_rate', value: row.daily_interest_rate != null ? row.daily_interest_rate : '--', type: 'rate' },
+        { label: '创建时间', prop: 'create_time', value: this.formatDate(row.create_time), type: 'time' },
+        { label: '更新时间', prop: 'update_time', value: this.formatDate(row.update_time), type: 'time' },
+      ]
+    }
+  },
   methods: {
   methods: {
     onValueChange(val) {
     onValueChange(val) {
       // 搜索表单值变动时的回调
       // 搜索表单值变动时的回调
     },
     },
     onSubmit(params = {}) {
     onSubmit(params = {}) {
       const queryParams = { ...params }
       const queryParams = { ...params }
-      
-      // 处理 daterange 日期范围,将其转换为接口需要的 start_time 和 end_time
       if (queryParams.dateRange && queryParams.dateRange.length === 2) {
       if (queryParams.dateRange && queryParams.dateRange.length === 2) {
         queryParams.start_time = queryParams.dateRange[0]
         queryParams.start_time = queryParams.dateRange[0]
         queryParams.end_time = queryParams.dateRange[1]
         queryParams.end_time = queryParams.dateRange[1]
       }
       }
       delete queryParams.dateRange
       delete queryParams.dateRange
-
       this.$refs.table.getList(queryParams)
       this.$refs.table.getList(queryParams)
     },
     },
     getLogList(userId) {
     getLogList(userId) {
       this.logLoading = true
       this.logLoading = true
-      // 调用查看日志接口
       yuebaoLog({ user_id: userId })
       yuebaoLog({ user_id: userId })
         .then(res => {
         .then(res => {
           this.logTableData = res.data?.data || []
           this.logTableData = res.data?.data || []
@@ -175,7 +239,6 @@ export default {
           this.logLoading = false
           this.logLoading = false
         })
         })
     },
     },
-    // 时间戳格式化转换
     formatDate(timestamp) {
     formatDate(timestamp) {
       if (!timestamp) return '--'
       if (!timestamp) return '--'
       const d = new Date(timestamp * 1000)
       const d = new Date(timestamp * 1000)