pxb 13 часов назад
Родитель
Сommit
3925307595

+ 27 - 0
src/router/index.js

@@ -277,6 +277,12 @@ export const constantRoutes = [
         name: "Banner",
         meta: { title: "Banner" },
       },
+      {
+        path: "ShareMoney",
+        component: () => import("@/views/Activity/ShareMoney/index"),
+        name: "ShareMoney",
+        meta: { title: "分享赚钱" },
+      },
     ],
   },
   {
@@ -523,6 +529,27 @@ export const constantRoutes = [
       },
     ],
   },
+  {
+    path: "/operationSetting",
+    name: "operationSetting",
+    component: Layout,
+    redirect: "/operationSetting/paymentConfig",
+    meta: { title: "运营设置", icon: "setting" },
+    children: [
+      {
+        path: "paymentConfig",
+        component: () => import("@/views/operationSetting/paymentConfig/index"),
+        name: "operationPaymentConfig",
+        meta: { title: "支付配置" },
+      },
+      {
+        path: "appConfig",
+        component: () => import("@/views/operationSetting/appConfig/index"),
+        name: "operationAppConfig",
+        meta: { title: "APP配置" },
+      },
+    ],
+  },
   {
     path: "/promoteUsers",
     name: "promoteUsers",

+ 1017 - 0
src/views/Activity/ShareMoney/index.vue

@@ -0,0 +1,1017 @@
+<template>
+  <div class="share-money-page">
+    <div class="share-money-panel">
+      <el-tabs v-model="activeTab" class="promotion-tabs" @tab-click="handleTabChange">
+        <el-tab-pane label="推广会员列表" name="members" />
+        <el-tab-pane label="推广汇总" name="summary" />
+        <el-tab-pane label="推广设定" name="settings" />
+        <el-tab-pane label="禁止推广列表" name="blocked" />
+      </el-tabs>
+      <el-form
+        v-if="activeTab !== 'settings'"
+        ref="queryForm"
+        :model="query"
+        class="share-money-search"
+        inline
+        size="small"
+      >
+        <el-form-item v-if="activeTab !== 'blocked'" label="时间" prop="date_range">
+          <el-date-picker
+            v-model="query.date_range"
+            type="daterange"
+            :default-value="[new Date(new Date().getFullYear(), new Date().getMonth() - 1, 1), new Date()]"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            value-format="yyyy-MM-dd"
+            :picker-options="disableFutureDate"
+          />
+        </el-form-item>
+        <el-form-item v-if="activeTab === 'summary'" label="推广账号" prop="promoter_account">
+          <el-input v-model="query.promoter_account" placeholder="请输入推广账号" clearable />
+        </el-form-item>
+        <template v-if="activeTab === 'blocked'">
+          <el-form-item>
+            <el-button type="primary" @click="handleBlockedCreate">新增</el-button>
+          </el-form-item>
+          <el-form-item prop="blocked_account">
+            <el-input
+              v-model="query.blocked_account"
+              placeholder="搜索禁止推广账号"
+              clearable
+              @input="handleBlockedSearch"
+            />
+          </el-form-item>
+        </template>
+        <el-form-item v-if="activeTab !== 'blocked'" class="search-actions">
+          <el-button type="primary" :loading="loading" @click="onSubmit">查询</el-button>
+          <el-button @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <div v-if="activeTab === 'settings'" class="promotion-settings">
+        <el-form :model="settingsForm" label-width="190px" class="settings-form">
+          <el-form-item label="分享赚钱开关(含前台显示)">
+            <el-switch
+              v-model="settingsForm.share_enabled"
+              :active-value="1"
+              :inactive-value="0"
+              active-color="#13ce66"
+              inactive-color="#f56c6c"
+            />
+          </el-form-item>
+          <el-form-item label="分享赚钱域名">
+            <el-input v-model="settingsForm.share_domain" />
+          </el-form-item>
+          <el-form-item label="有效会员最低存款">
+            <el-input v-model="settingsForm.minimum_deposit" />
+          </el-form-item>
+          <el-form-item label="佣金/手续费减免设置">
+            <el-switch
+              v-model="settingsForm.commission_enabled"
+              :active-value="1"
+              :inactive-value="0"
+              active-color="#13ce66"
+              inactive-color="#f56c6c"
+            />
+          </el-form-item>
+          <div class="commission-settings">
+            <el-form-item label="非卖家单笔阈值 >=">
+              <el-input v-model="settingsForm.non_seller_threshold" :disabled="!settingsForm.commission_enabled">
+                <template slot="append">元</template>
+              </el-input>
+            </el-form-item>
+            <el-form-item label="抽佣阶梯一">
+              <el-input v-model="settingsForm.commission_tier_one" :disabled="!settingsForm.commission_enabled">
+                <template slot="append">%</template>
+              </el-input>
+            </el-form-item>
+            <el-form-item label="抽佣阶梯二">
+              <el-input v-model="settingsForm.commission_tier_two" :disabled="!settingsForm.commission_enabled">
+                <template slot="append">%</template>
+              </el-input>
+            </el-form-item>
+          </div>
+        </el-form>
+        <div class="settings-actions">
+          <el-button type="primary" @click="submitSettings">提交</el-button>
+        </div>
+      </div>
+
+      <div v-if="activeTab !== 'settings'" class="share-money-table">
+        <el-table
+          v-if="activeTab === 'summary'"
+          v-loading="loading"
+          :data="summaryTableData"
+          height="100%"
+          class="share-money-list summary-list"
+        >
+          <el-table-column type="index" label="序号" width="100" align="center" />
+          <el-table-column prop="date" label="日期" min-width="120" align="center" />
+          <el-table-column prop="promoter_account" label="推广账号" min-width="140" align="center" />
+          <el-table-column prop="promoter_name" label="推广昵称" min-width="140" align="center" />
+          <el-table-column prop="deposit" label="存款" min-width="120" align="center" />
+          <el-table-column prop="commission" label="佣金" min-width="120" align="center" />
+          <el-table-column prop="sales_amount" label="销售额" min-width="120" align="center" />
+          <el-table-column prop="fee_reduction" label="手续费减免" min-width="160" align="center" />
+        </el-table>
+        <div v-if="activeTab === 'summary'" class="summary-footer">
+          <span>总佣金:<strong>{{ summaryCommission }}</strong></span>
+          <span>当前最高手续费减免:<strong>{{ summaryMaxFeeReduction }}</strong></span>
+        </div>
+        <el-table
+          v-if="activeTab === 'blocked'"
+          v-loading="loading"
+          :data="blockedTableData"
+          height="100%"
+          class="share-money-list blocked-list"
+        >
+          <el-table-column type="index" label="序号" width="100" align="center" />
+          <el-table-column prop="member_account" label="会员账号" min-width="180" align="center" />
+          <el-table-column prop="prohibited_category" label="不能返佣的类目" min-width="260" align="center" />
+          <el-table-column label="状态" min-width="160" align="center">
+            <template slot-scope="scope">
+              <el-switch
+                :value="scope.row.status === 1"
+                active-color="#13ce66"
+                inactive-color="#f56c6c"
+                @change="handleBlockedToggle(scope.row, $event)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" min-width="220" align="center">
+            <template slot-scope="scope">
+              <el-button type="text" size="small" class="ym-view-btn" @click="handleBlockedEdit(scope.row)">修改</el-button>
+              <el-button type="text" size="small" class="ym-view-btn" @click="handleBlockedDelete(scope.row)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-table
+          v-if="activeTab !== 'summary' && activeTab !== 'settings' && activeTab !== 'blocked'"
+          v-loading="loading"
+          :data="tableData"
+          height="100%"
+          class="share-money-list"
+        >
+          <el-table-column type="index" label="序号" width="100" align="center" />
+          <el-table-column prop="date" label="日期" min-width="130" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.date }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="promoter_count" label="推广人数" min-width="110" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.promoter_count }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="registered_members" label="注册会员" min-width="110" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.registered_members }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="h5_register" label="H5注册" min-width="110" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.h5_register }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="ios_register" label="ios注册" min-width="110" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.ios_register }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="android_register" label="安卓注册" min-width="110" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.android_register }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="deposit_total" label="存款总额" min-width="120" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.deposit_total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="consumption_total" label="消费金额" min-width="120" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.consumption_total }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column prop="company_profit" label="公司盈利" min-width="120" align="center">
+            <template slot-scope="scope">
+              <span>{{ scope.row.company_profit }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" min-width="220" align="center" fixed="right">
+            <template slot-scope="scope">
+              <el-button type="text" size="small" class="ym-view-btn" @click="handleView(scope.row)">推广详情</el-button>
+              <el-button type="text" size="small" class="ym-view-btn" @click="handleRegisterView(scope.row)">注册详情</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <el-pagination
+        v-if="activeTab !== 'settings'"
+        background
+        class="share-money-pagination"
+        layout="total, sizes, prev, pager, next, jumper"
+        :current-page="page"
+        :page-size="limit"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="activeTab === 'summary' ? summaryTotal : activeTab === 'blocked' ? blockedTotal : total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+
+      <Dialog
+        ref="viewDialog"
+        :dialog-actions="{
+          width: '960px',
+          title: '推广会员详情',
+          confirmButtom: false,
+        }"
+      >
+        <template slot="content">
+          <el-form :model="detailQuery" class="detail-search" inline size="small">
+            <el-form-item label="会员ID">
+              <el-input v-model="detailQuery.member_id" placeholder="请输入会员ID" clearable />
+            </el-form-item>
+            <el-form-item label="会员账号">
+              <el-input v-model="detailQuery.member_account" placeholder="请输入会员账号" clearable />
+            </el-form-item>
+            <el-form-item class="detail-search-actions">
+              <el-button type="primary" @click="handleDetailSearch">查询</el-button>
+              <el-button @click="resetDetailQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+          <div class="detail-table">
+            <el-table :data="detailTableData" height="360" style="width: 100%;">
+              <el-table-column prop="date" label="日期" width="120" align="center" />
+              <el-table-column prop="member_account" label="会员账号" width="120" align="center" />
+              <el-table-column prop="member_name" label="会员昵称" width="120" align="center" />
+              <el-table-column prop="deposit_total" label="存款总额" width="110" align="center" />
+              <el-table-column prop="register_count" label="注册人数" width="110" align="center" />
+              <el-table-column prop="commission" label="佣金" width="100" align="center">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.commission }}</span>
+                </template>
+              </el-table-column>
+              <el-table-column prop="current_fee" label="当前手续费" min-width="120" align="center">
+                <template slot-scope="scope">
+                  <span>{{ scope.row.current_fee }}</span>
+                </template>
+              </el-table-column>
+            </el-table>
+            <el-pagination
+              background
+              class="detail-pagination"
+              layout="total, sizes, prev, pager, next, jumper"
+              :current-page="detailPage"
+              :page-size="detailLimit"
+              :page-sizes="[10, 20, 50]"
+              :total="detailTotal"
+              @size-change="handleDetailSizeChange"
+              @current-change="handleDetailCurrentChange"
+            />
+            <div class="detail-total">总人数:{{ detailTotal }}</div>
+          </div>
+          <div class="promotion-description">
+            <p>佣金来源:</p>
+            <p>被邀请人单笔下注>={{ promotionRule.highBetAmount }}元,推广人可以抽取购买单价的{{ promotionRule.highCommissionRate }}%佣金。</p>
+            <p>被邀请人单笔下注{{ promotionRule.lessThan }}{{ promotionRule.lowBetAmount }}元,推广人可以抽取购买单价的{{ promotionRule.lowCommissionRate }}%佣金。</p>
+          </div>
+        </template>
+      </Dialog>
+      <Dialog
+        ref="registerDialog"
+        :dialog-actions="{
+          width: '960px',
+          title: '注册会员详情',
+          confirmButtom: false,
+        }"
+      >
+        <template slot="content">
+          <el-form :model="registerDetailQuery" class="detail-search" inline size="small">
+            <el-form-item label="会员ID">
+              <el-input v-model="registerDetailQuery.member_id" placeholder="请输入会员ID" clearable />
+            </el-form-item>
+            <el-form-item label="会员账号">
+              <el-input v-model="registerDetailQuery.member_account" placeholder="请输入会员账号" clearable />
+            </el-form-item>
+            <el-form-item class="detail-search-actions">
+              <el-button type="primary" @click="handleRegisterDetailSearch">查询</el-button>
+              <el-button @click="resetRegisterDetailQuery">重置</el-button>
+            </el-form-item>
+          </el-form>
+          <div class="register-detail-table">
+            <el-table :data="registerDetailTableData" height="440" style="width: 100%;">
+              <el-table-column prop="date" label="日期" min-width="120" align="center" />
+              <el-table-column prop="member_account" label="会员账号" min-width="130" align="center" />
+              <el-table-column prop="member_name" label="会员昵称" min-width="130" align="center" />
+              <el-table-column prop="deposit_total" label="存款总额" min-width="130" align="center" />
+              <el-table-column prop="consumption_total" label="下注总额" min-width="130" align="center" />
+              <el-table-column prop="withdrawal_total" label="提款总额" min-width="130" align="center" />
+            </el-table>
+            <div class="detail-total">总人数:{{ registerDetailTotal }}</div>
+          </div>
+        </template>
+      </Dialog>
+      <Dialog
+        ref="blockedDialog"
+        :dialog-actions="{
+          width: '560px',
+          title: blockedDialogTitle,
+          buttom: false,
+          confirmButtom: false,
+        }"
+      >
+        <template slot="content">
+          <el-form :model="blockedForm" label-width="120px" class="blocked-form">
+            <el-form-item label="禁止推广账号">
+              <el-input v-model="blockedForm.member_account" />
+            </el-form-item>
+            <el-form-item label="不能返佣的类目">
+              <el-checkbox v-model="blockedForm.selectAll" @change="toggleBlockedCategories">全选</el-checkbox>
+              <div
+                v-for="(categoryGroup, groupIndex) in blockedCategoryGroups"
+                :key="groupIndex"
+                class="blocked-category-row"
+              >
+                <el-checkbox
+                  v-for="category in categoryGroup"
+                  :key="category"
+                  v-model="blockedForm.categories"
+                  :label="category"
+                  @change="syncBlockedSelectAll"
+                />
+              </div>
+            </el-form-item>
+            <div class="blocked-dialog-actions">
+              <el-button type="primary" @click="submitBlocked">提交</el-button>
+            </div>
+          </el-form>
+        </template>
+      </Dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/components/Dialog/index.vue'
+import { disableFutureDate } from '@/utils/index'
+
+export default {
+  name: 'ShareMoney',
+  components: {
+    Dialog
+  },
+  data() {
+    return {
+      loading: false,
+      activeTab: 'members',
+      page: 1,
+      limit: 10,
+      total: 0,
+      summaryTotal: 0,
+      blockedTotal: 0,
+      summaryCommission: '534.9',
+      summaryMaxFeeReduction: '-4%',
+      settingsForm: {
+        share_enabled: 1,
+        share_domain: 'show888.com',
+        minimum_deposit: 20,
+        commission_enabled: 0,
+        non_seller_threshold: 200,
+        commission_tier_one: 4,
+        commission_tier_two: 6
+      },
+      viewRow: null,
+      detailPage: 1,
+      detailLimit: 10,
+      detailTableData: [],
+      detailTotal: 0,
+      detailQuery: {
+        member_id: '',
+        member_account: ''
+      },
+      registerDetailTableData: [],
+      registerDetailTotal: 223,
+      registerDetailAllTableData: [],
+      registerDetailViewDate: '',
+      registerDetailQuery: {
+        member_id: '',
+        member_account: ''
+      },
+      promotionRule: {
+        highBetAmount: 200,
+        lowBetAmount: 200,
+        highCommissionRate: 4,
+        lowCommissionRate: 6,
+        lessThan: '<'
+      },
+      detailMockData: [
+        { member_id: 10001, member_account: 'Monu2000', member_name: '原味小娥', deposit_total: 20, register_count: 3, is_seller: '否', commission: 8, current_fee: '-' },
+        { member_id: 10002, member_account: 'Kiwq1200', member_name: '奶酪', deposit_total: 23, register_count: 23, is_seller: '是', commission: '-', current_fee: '-4%' },
+        { member_id: 10003, member_account: 'Kiwq1200', member_name: '奶酪', deposit_total: 23, register_count: 6, is_seller: '是', commission: '-', current_fee: '-4%' },
+        { member_id: 10004, member_account: 'Kiwq1200', member_name: '奶酪', deposit_total: 23, register_count: 6, is_seller: '是', commission: '-', current_fee: '-4%' },
+        { member_id: 10005, member_account: 'Kiwq1200', member_name: '奶酪', deposit_total: 23, register_count: 6, is_seller: '是', commission: '-', current_fee: '-4%' },
+        { member_id: 10006, member_account: 'Kiwq1200', member_name: '奶酪', deposit_total: 23, register_count: 6, is_seller: '是', commission: '-', current_fee: '-4%' }
+      ],
+      detailAllTableData: [],
+      allTableData: [],
+      summaryAllTableData: [],
+      summaryTableData: [],
+      blockedAllTableData: [],
+      blockedTableData: [],
+      blockedCategoryGroups: [
+        ['体育', '彩票', '第三方游戏']
+      ],
+      blockedForm: {
+        member_account: '',
+        categories: [],
+        selectAll: false
+      },
+      blockedEditingRow: null,
+      blockedDialogTitle: '新增禁止推广账号',
+      query: {
+        date_range: [],
+        promoter_account: '',
+        blocked_account: ''
+      },
+      disableFutureDate,
+      tableData: []
+    }
+  },
+  created() {
+    this.allTableData = this.getMockRows()
+    this.detailAllTableData = this.getDetailMockData()
+    this.registerDetailAllTableData = this.getRegisterDetailMockData()
+    this.summaryAllTableData = this.getSummaryMockData()
+    this.blockedAllTableData = this.getBlockedMockData()
+    this.getList()
+  },
+  methods: {
+    getMockRows() {
+      const firstRows = [
+        {
+          date: '2025-03-10',
+          promoter_count: 20,
+          registered_members: 223,
+          h5_register: 23,
+          ios_register: 150,
+          android_register: 50,
+          deposit_total: 1200,
+          consumption_total: 1000,
+          company_profit: 150
+        },
+        {
+          date: '2025-03-10',
+          promoter_count: 150,
+          registered_members: 180,
+          h5_register: 30,
+          ios_register: 120,
+          android_register: 50,
+          deposit_total: 880,
+          consumption_total: 500,
+          company_profit: 75
+        }
+      ]
+      const extraRows = Array.from({ length: 23 }, (_, index) => ({
+        date: `2025-03-${String(9 - (index % 9)).padStart(2, '0')}`,
+        promoter_count: 30 + index * 5,
+        registered_members: 100 + index * 8,
+        h5_register: 15 + index,
+        ios_register: 60 + index * 3,
+        android_register: 25 + index * 2,
+        deposit_total: 400 + index * 35,
+        consumption_total: 280 + index * 24,
+        company_profit: 35 + index * 5
+      }))
+      return firstRows.concat(extraRows)
+    },
+    getSummaryMockData() {
+      const firstRows = [
+        { date: '2025-03-11', promoter_account: 'qq900', promoter_name: '原味大哥', deposit: 20, commission: 12, sales_amount: '--', fee_reduction: '--' },
+        { date: '2025-03-10', promoter_account: 'tsa123', promoter_name: '七月玫瑰', deposit: '--', commission: '--', sales_amount: 100, fee_reduction: '-4%' },
+        { date: '2025-03-09', promoter_account: 'qq900', promoter_name: '原味大哥', deposit: 30, commission: 1.2, sales_amount: '--', fee_reduction: '--' },
+        { date: '2025-03-08', promoter_account: 'tsa123', promoter_name: '七月玫瑰', deposit: '--', commission: '--', sales_amount: 100, fee_reduction: '-2%' }
+      ]
+      const extraRows = Array.from({ length: 21 }, (_, index) => ({
+        date: `2025-03-${String(7 - (index % 7)).padStart(2, '0')}`,
+        promoter_account: index % 2 === 0 ? 'qq900' : 'tsa123',
+        promoter_name: index % 2 === 0 ? '原味大哥' : '七月玫瑰',
+        deposit: index % 2 === 0 ? 20 + index : '--',
+        commission: index % 2 === 0 ? 10 + index : '--',
+        sales_amount: index % 2 === 0 ? '--' : 100 + index,
+        fee_reduction: index % 2 === 0 ? '--' : index % 3 === 0 ? '-4%' : '-2%'
+      }))
+      return firstRows.concat(extraRows)
+    },
+    getDetailMockData() {
+      const extraRows = Array.from({ length: 19 }, (_, index) => ({
+        member_id: 10007 + index,
+        member_account: `Member${String(index + 3).padStart(4, '0')}`,
+        member_name: `推广会员${index + 3}`,
+        deposit_total: 25 + index * 3,
+        register_count: 2 + index,
+        is_seller: index % 2 === 0 ? '是' : '否',
+        commission: index % 3 === 0 ? 6 + index : '-',
+        current_fee: index % 2 === 0 ? '-4%' : '-'
+      }))
+      return this.detailMockData.concat(extraRows)
+    },
+    getRegisterDetailMockData() {
+      const firstRows = [
+        { member_id: 20001, member_account: 'Mo120', member_name: '原味大虾', deposit_total: 330, consumption_total: 134, is_seller: '否', sales_total: '--', withdrawal_total: '--' },
+        { member_id: 20002, member_account: 'saa120', member_name: '七月玫瑰', deposit_total: '--', consumption_total: '--', is_seller: '是', sales_total: 500, withdrawal_total: 50 },
+        { member_id: 20003, member_account: 'pe122', member_name: '原味小段', deposit_total: '--', consumption_total: '--', is_seller: '否', sales_total: '--', withdrawal_total: '--' },
+        { member_id: 20004, member_account: 'tt232', member_name: '牙鸟', deposit_total: 300, consumption_total: 344, is_seller: '否', sales_total: '--', withdrawal_total: '--' },
+        { member_id: 20005, member_account: 'ead3434', member_name: '卖原味', deposit_total: '--', consumption_total: '--', is_seller: '是', sales_total: '--', withdrawal_total: '--' }
+      ]
+      const extraRows = Array.from({ length: 10 }, (_, index) => ({
+        member_id: 20006 + index,
+        member_account: `register${String(index + 1).padStart(3, '0')}`,
+        member_name: index % 2 === 0 ? '原味会员' : '推广会员',
+        deposit_total: index % 2 === 0 ? 100 + index * 10 : '--',
+        consumption_total: index % 3 === 0 ? 80 + index * 4 : '--',
+        is_seller: index % 2 === 0 ? '否' : '是',
+        sales_total: index % 2 === 0 ? '--' : 200 + index * 10,
+        withdrawal_total: index % 4 === 0 ? 50 : '--'
+      }))
+      return firstRows.concat(extraRows)
+    },
+    getBlockedMockData() {
+      const firstRow = {
+        member_account: 'yad123',
+        prohibited_category: '体育',
+        status: 0
+      }
+      const categories = ['体育', '彩票', '第三方游戏']
+      const extraRows = Array.from({ length: 11 }, (_, index) => ({
+        member_account: `blocked${String(index + 1).padStart(3, '0')}`,
+        prohibited_category: categories[index % categories.length],
+        status: index % 3 === 0 ? 1 : 0
+      }))
+      return [firstRow].concat(extraRows)
+    },
+    getList() {
+      if (this.activeTab === 'summary') {
+        this.getSummaryList()
+        return
+      }
+      if (this.activeTab === 'blocked') {
+        this.getBlockedList()
+        return
+      }
+      const [startDate, endDate] = this.query.date_range || []
+      const filteredRows = this.allTableData.filter(row => {
+        return (!startDate || row.date >= startDate) && (!endDate || row.date <= endDate)
+      })
+      this.total = filteredRows.length
+      this.tableData = filteredRows.slice((this.page - 1) * this.limit, this.page * this.limit)
+    },
+    getSummaryList() {
+      const [startDate, endDate] = this.query.date_range || []
+      const account = this.query.promoter_account || ''
+      const filteredRows = this.summaryAllTableData.filter(row => {
+        const dateMatched = (!startDate || row.date >= startDate) && (!endDate || row.date <= endDate)
+        const accountMatched = !account || row.promoter_account.indexOf(account) > -1
+        return dateMatched && accountMatched
+      })
+      this.summaryTotal = filteredRows.length
+      this.summaryTableData = filteredRows.slice((this.page - 1) * this.limit, this.page * this.limit)
+    },
+    getBlockedList() {
+      const keyword = this.query.blocked_account || ''
+      const filteredRows = this.blockedAllTableData.filter(row => {
+        return !keyword || row.member_account.indexOf(keyword) > -1
+      })
+      this.blockedTotal = filteredRows.length
+      this.blockedTableData = filteredRows.slice((this.page - 1) * this.limit, this.page * this.limit)
+    },
+    onSubmit() {
+      this.page = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.$refs.queryForm.resetFields()
+      this.onSubmit()
+    },
+    handleTabChange() {
+      this.page = 1
+      this.getList()
+    },
+    handleBlockedSearch() {
+      this.page = 1
+      this.getBlockedList()
+    },
+    handleBlockedCreate() {
+      this.resetBlockedForm()
+      this.$refs.blockedDialog.open()
+    },
+    resetBlockedForm() {
+      this.blockedForm = {
+        member_account: '',
+        categories: [],
+        selectAll: false
+      }
+      this.blockedEditingRow = null
+      this.blockedDialogTitle = '新增禁止推广账号'
+    },
+    toggleBlockedCategories(value) {
+      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
+      this.blockedForm.categories = value ? categories : []
+    },
+    syncBlockedSelectAll() {
+      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
+      this.blockedForm.selectAll = this.blockedForm.categories.length === categories.length
+    },
+    submitBlocked() {
+      if (!this.blockedForm.member_account.trim()) {
+        this.$message.warning('请输入禁止推广账号')
+        return
+      }
+      if (!this.blockedForm.categories.length) {
+        this.$message.warning('请选择不能返佣的类目')
+        return
+      }
+      const blockedData = {
+        member_account: this.blockedForm.member_account,
+        prohibited_category: this.blockedForm.categories.join('、')
+      }
+      if (this.blockedEditingRow) {
+        Object.assign(this.blockedEditingRow, blockedData)
+      } else {
+        this.blockedAllTableData.unshift({
+          ...blockedData,
+          status: 0
+        })
+      }
+      this.$refs.blockedDialog.close()
+      this.getBlockedList()
+      this.resetBlockedForm()
+      this.$message.success('提交成功')
+    },
+    handleBlockedEdit(row) {
+      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
+      const selectedCategories = row.prohibited_category
+        .split('、')
+        .filter(category => categories.includes(category))
+      this.blockedEditingRow = row
+      this.blockedDialogTitle = '修改禁止推广账号'
+      this.blockedForm = {
+        member_account: row.member_account,
+        categories: selectedCategories,
+        selectAll: selectedCategories.length === categories.length
+      }
+      this.$refs.blockedDialog.open()
+    },
+    handleBlockedToggle(row, value) {
+      row.status = value ? 1 : 0
+    },
+    handleBlockedDelete(row) {
+      this.$confirm(`确定删除会员账号“${row.member_account}”吗?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        const rowIndex = this.blockedAllTableData.indexOf(row)
+        if (rowIndex > -1) {
+          this.blockedAllTableData.splice(rowIndex, 1)
+          this.getBlockedList()
+        }
+      })
+    },
+    submitSettings() {
+      this.$message.success('提交成功')
+    },
+    handleSizeChange(value) {
+      this.limit = value
+      this.page = 1
+      this.getList()
+    },
+    handleCurrentChange(value) {
+      this.page = value
+      this.getList()
+    },
+    handleView(row) {
+      this.viewRow = { ...row }
+      this.detailPage = 1
+      this.detailQuery = {
+        member_id: '',
+        member_account: ''
+      }
+      this.getDetailList()
+      this.$refs.viewDialog.open()
+    },
+    handleDetailSearch() {
+      this.detailPage = 1
+      this.getDetailList()
+    },
+    resetDetailQuery() {
+      this.detailQuery = {
+        member_id: '',
+        member_account: ''
+      }
+      this.detailPage = 1
+      this.getDetailList()
+    },
+    handleRegisterView(row) {
+      this.registerDetailViewDate = row.date
+      this.registerDetailQuery = {
+        member_id: '',
+        member_account: ''
+      }
+      this.getRegisterDetailList()
+      this.$refs.registerDialog.open()
+    },
+    handleRegisterDetailSearch() {
+      this.getRegisterDetailList()
+    },
+    resetRegisterDetailQuery() {
+      this.registerDetailQuery = {
+        member_id: '',
+        member_account: ''
+      }
+      this.getRegisterDetailList()
+    },
+    getDetailList() {
+      const memberId = this.detailQuery.member_id.trim()
+      const memberAccount = this.detailQuery.member_account.trim()
+      const filteredRows = this.detailAllTableData.filter(item => {
+        const idMatched = !memberId || String(item.member_id).indexOf(memberId) > -1
+        const accountMatched = !memberAccount || item.member_account.indexOf(memberAccount) > -1
+        return idMatched && accountMatched
+      })
+      const detailRows = filteredRows.slice(
+        (this.detailPage - 1) * this.detailLimit,
+        this.detailPage * this.detailLimit
+      )
+      this.detailTotal = filteredRows.length
+      this.detailTableData = detailRows.map(item => ({
+        ...item,
+        date: this.viewRow.date
+      }))
+    },
+    getRegisterDetailList() {
+      const memberId = this.registerDetailQuery.member_id.trim()
+      const memberAccount = this.registerDetailQuery.member_account.trim()
+      const filteredRows = this.registerDetailAllTableData.filter(item => {
+        const idMatched = !memberId || String(item.member_id).indexOf(memberId) > -1
+        const accountMatched = !memberAccount || item.member_account.indexOf(memberAccount) > -1
+        return idMatched && accountMatched
+      })
+      this.registerDetailTableData = filteredRows.map(item => ({
+        ...item,
+        date: this.registerDetailViewDate
+      }))
+    },
+    handleDetailSizeChange(value) {
+      this.detailLimit = value
+      this.detailPage = 1
+      this.getDetailList()
+    },
+    handleDetailCurrentChange(value) {
+      this.detailPage = value
+      this.getDetailList()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.share-money-page {
+  display: flex;
+  height: 100%;
+  padding: 16px;
+  background: #f5f7fa;
+}
+
+.share-money-panel {
+  display: flex;
+  flex: 1;
+  flex-direction: column;
+  min-width: 0;
+  min-height: 0;
+  padding: 0 20px 12px;
+  overflow: hidden;
+  background: #fff;
+  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08);
+}
+
+.promotion-tabs {
+  flex-shrink: 0;
+
+  ::v-deep .el-tabs__header {
+    margin: 0;
+  }
+
+  ::v-deep .el-tabs__item {
+    height: 52px;
+    line-height: 52px;
+    font-weight: 500;
+  }
+}
+
+.share-money-search {
+  flex-shrink: 0;
+  padding: 16px 0 0;
+
+  ::v-deep .el-form-item {
+    margin-right: 22px;
+    margin-bottom: 14px;
+  }
+
+  ::v-deep .el-form-item__label {
+    color: #303133;
+    font-weight: 500;
+  }
+
+  ::v-deep .el-date-editor--daterange.el-input__inner {
+    width: 400px;
+  }
+
+  ::v-deep .el-input {
+    width: 236px;
+  }
+
+  .search-actions {
+    margin-right: 0;
+  }
+}
+
+.promotion-settings {
+  flex: 1;
+  min-height: 0;
+  overflow: auto;
+  padding-top: 16px;
+}
+
+.settings-actions {
+  margin-top: 8px;
+}
+
+.settings-form {
+  ::v-deep .el-form-item {
+    margin-bottom: 16px;
+  }
+
+  ::v-deep .el-form-item__label {
+    color: #303133;
+    font-weight: 500;
+    white-space: nowrap;
+  }
+
+  ::v-deep .el-input {
+    width: 236px;
+  }
+}
+
+.commission-settings {
+  ::v-deep .el-form-item {
+    margin-bottom: 8px;
+  }
+
+  ::v-deep .el-form-item__label {
+    color: #909399;
+    font-size: 14px;
+  }
+
+  ::v-deep .el-input {
+    width: 150px;
+  }
+}
+
+.share-money-table {
+  display: flex;
+  flex: 1;
+  flex-direction: column;
+  min-height: 0;
+
+  .el-table {
+    flex: 1;
+    border-radius: 4px;
+    overflow: hidden;
+  }
+
+  ::v-deep .el-table__fixed-right {
+    height: 100% !important;
+  }
+
+  ::v-deep .el-table th {
+    height: 44px;
+    background: #f5f7fa;
+  }
+
+  ::v-deep .el-table th .cell {
+    color: #606266 !important;
+    font-weight: 500;
+  }
+
+  ::v-deep .el-table td {
+    height: 49px;
+  }
+
+  ::v-deep .el-table td .cell {
+    overflow: hidden;
+    color: #606266;
+    font-size: 14px;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+}
+
+.share-money-pagination {
+  flex-shrink: 0;
+  padding-top: 12px;
+  text-align: right;
+}
+
+.summary-footer {
+  flex-shrink: 0;
+  padding: 12px 16px 0;
+  color: #606266;
+  text-align: right;
+}
+
+.summary-footer span + span {
+  margin-left: 56px;
+}
+
+.summary-footer strong {
+  color: #606266;
+  font-weight: 600;
+}
+
+.blocked-form {
+  ::v-deep .el-form-item {
+    margin-bottom: 16px;
+  }
+
+  ::v-deep .el-form-item__label {
+    color: #303133;
+  }
+
+  ::v-deep .el-input {
+    width: 236px;
+  }
+}
+
+.blocked-category-row {
+  display: flex;
+  margin-top: 12px;
+
+  ::v-deep .el-checkbox {
+    margin-right: 24px;
+  }
+}
+
+.blocked-dialog-actions {
+  margin-top: 20px;
+  text-align: right;
+}
+
+.detail-search {
+  margin-bottom: 12px;
+
+  ::v-deep .el-form-item {
+    margin-right: 18px;
+    margin-bottom: 8px;
+  }
+
+  ::v-deep .el-input {
+    width: 150px;
+  }
+
+  .detail-search-actions {
+    margin-right: 0;
+  }
+}
+
+.detail-table {
+  padding: 10px 0 0;
+}
+
+.detail-total {
+  padding: 12px 16px;
+  color: #303133;
+}
+
+.detail-pagination {
+  padding-top: 12px;
+  text-align: right;
+}
+
+.promotion-description {
+  padding: 12px 16px 0;
+  color: #303133;
+  font-size: 14px;
+}
+
+.description-title {
+  margin-bottom: 8px;
+  font-weight: 600;
+}
+
+.promotion-description p {
+  margin: 6px 0;
+}
+</style>

+ 2 - 3
src/views/fund/manualAudit/index.vue

@@ -53,7 +53,7 @@
           height="calc(100vh - 340px)" style="width: 100%; border-radius: 12px; overflow: hidden;"
           empty-text="暂无数据">
           <el-table-column type="index" label="序号" width="80" align="center" />
-          <el-table-column prop="member_account" label="会员ID" width="140" align="center" />
+          <el-table-column prop="member_id" label="会员ID" width="140" align="center" />
           <el-table-column prop="member_name" label="会员昵称" width="140" align="center" />
           <el-table-column prop="pay_type" label="类型" width="100" align="center">
             <template slot-scope="{ row }">
@@ -261,7 +261,7 @@ export default {
       const statusColor = row.status === '成功' ? '#18C80A' : row.status === '失败' ? '#F56C6C' : '#909399'
       const payTypeColor = row.pay_type === '人工上分' ? '#18C80A' : row.pay_type === '人工下分' ? '#F56C6C' : '#606266'
       return [
-        { label: '会员ID', prop: 'member_account', value: row.member_account || '--' },
+        { label: '会员ID', prop: 'member_id', value: row.member_id || '--' },
         { label: '会员昵称', prop: 'member_name', value: row.member_name || '--' },
         { label: '类型', prop: 'pay_type', value: row.pay_type || '--', color: payTypeColor },
         { label: '上分类型', prop: 'change_type', value: row.change_type || '--' },
@@ -295,7 +295,6 @@ export default {
         id: row.id,
         request_id: row.request_id || '--',
         admin_id: row.admin_id != null ? row.admin_id : '--',
-        member_account: row.username || row.member_id || '--',
         member_name: row.first_name || '--',
         member_id: row.member_id,
         pay_type: row.transaction_type_text || (row.transaction_type === 'credit' ? '人工上分' : '人工下分'),

+ 378 - 0
src/views/operationSetting/appConfig/index.vue

@@ -0,0 +1,378 @@
+<template>
+  <div class="new-app-container layout-vertical operation-setting-page">
+    <div class="operation-setting-panel">
+      <el-tabs v-model="activeTab" class="operation-tabs" @tab-click="handleTabChange">
+        <el-tab-pane label="安装包设置" name="package" />
+        <el-tab-pane label="下载统计" name="download" />
+        <el-tab-pane label="IOS上架设置" name="ios" />
+      </el-tabs>
+
+      <el-form v-if="activeTab !== 'package'" ref="queryForm" :model="query" class="operation-search" inline size="small" @submit.native.prevent="handleSearch">
+        <el-form-item label="时间">
+          <el-date-picker v-model="query.date_range" type="daterange" value-format="yyyy-MM-dd" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="disableFutureDate" />
+        </el-form-item>
+        <el-form-item class="search-actions">
+          <el-button type="primary" :loading="loading" @click="handleSearch">查询</el-button>
+          <el-button @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <template v-if="activeTab === 'package'">
+        <div class="display-settings">
+          <div class="display-settings-title">前台显示</div>
+          <div class="display-setting-item"><span>IOS前端显示</span><el-switch v-model="displaySettings.ios" active-color="#13ce66" inactive-color="#c0c4cc" @change="saveDisplaySettings" /></div>
+          <div class="display-setting-item"><span>安卓前端显示</span><el-switch v-model="displaySettings.android" active-color="#13ce66" inactive-color="#c0c4cc" @change="saveDisplaySettings" /></div>
+        </div>
+        <div class="operation-toolbar">
+          <span class="operation-toolbar-title">安装包列表</span>
+          <el-button type="primary" size="small" @click="handleCreatePackage">创建安装包</el-button>
+        </div>
+        <div class="operation-table-wrap">
+          <el-table key="package-table" v-loading="loading" :data="pagedPackageRows" height="100%" class="operation-table">
+            <el-table-column type="index" label="序号" width="70" align="center" />
+            <el-table-column prop="platform" label="平台" width="90" align="center" />
+            <el-table-column prop="package_link" label="安装包链接" min-width="220" align="center" show-overflow-tooltip />
+            <el-table-column prop="version" label="版号" width="90" align="center" />
+            <el-table-column label="强制更新" width="100" align="center"><template slot-scope="scope">{{ scope.row.force_update ? '开' : '关' }}</template></el-table-column>
+            <el-table-column label="状态" width="90" align="center"><template slot-scope="scope"><el-switch :value="scope.row.status === 1" active-color="#13ce66" inactive-color="#c0c4cc" @change="toggleStatus(scope.row)" /></template></el-table-column>
+            <el-table-column prop="created_at" label="创建时间" min-width="160" align="center" />
+            <el-table-column prop="updated_at" label="修改时间" min-width="160" align="center" />
+            <el-table-column prop="operator" label="操作者" width="110" align="center" />
+            <el-table-column label="操作" min-width="150" align="center" fixed="right"><template slot-scope="scope"><el-button type="text" size="small" class="operation-link" @click="handleEditPackage(scope.row)">编辑</el-button><el-button type="text" size="small" class="operation-link danger-link" @click="handleDeletePackage(scope.row)">删除</el-button></template></el-table-column>
+          </el-table>
+        </div>
+        <el-pagination background class="operation-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="limit" :page-sizes="[10, 20, 50, 100]" :total="packageRows.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </template>
+
+      <template v-else-if="activeTab === 'download'">
+        <div class="operation-toolbar"><span class="operation-toolbar-title">下载点击统计</span></div>
+        <div class="operation-table-wrap download-table-wrap">
+          <el-table key="download-click-table" v-loading="loading" :data="pagedDownloadRows" height="50%" class="operation-table compact-table">
+            <el-table-column type="index" label="序号" width="70" align="center" />
+            <el-table-column prop="platform" label="平台" width="100" align="center" />
+            <el-table-column prop="source" label="来源" min-width="130" align="center" />
+            <el-table-column prop="download_link" label="App下载链接" min-width="260" align="center" show-overflow-tooltip />
+            <el-table-column prop="click_count" label="点击链接次数" min-width="130" align="center" />
+          </el-table>
+          <el-table key="download-app-table" class="operation-table compact-table" :data="pagedDownloadAppRows" height="50%">
+            <el-table-column type="index" label="序号" width="70" align="center" />
+            <el-table-column prop="platform" label="平台" width="100" align="center" />
+            <el-table-column prop="package_type" label="安装包类型" min-width="180" align="center" />
+            <el-table-column prop="download_count" label="下载且开启App次数" min-width="180" align="center" />
+          </el-table>
+        </div>
+        <el-pagination background class="operation-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="limit" :page-sizes="[10, 20, 50, 100]" :total="downloadRows.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </template>
+
+      <template v-else>
+        <div class="operation-toolbar"><span class="operation-toolbar-title">IOS上架设置</span><el-button type="primary" size="small" @click="handleCreateIos">新增</el-button></div>
+        <div class="operation-table-wrap">
+          <el-table key="ios-table" v-loading="loading" :data="pagedIosRows" height="100%" class="operation-table">
+            <el-table-column type="index" label="序号" width="70" align="center" />
+            <el-table-column prop="platform" label="平台" width="90" align="center" />
+            <el-table-column prop="publish_version" label="上架版本" min-width="110" align="center" />
+            <el-table-column prop="operation_version" label="运营版本" min-width="110" align="center" />
+            <el-table-column prop="review_user_ids" label="提供审查用户ID" min-width="180" align="center" />
+            <el-table-column prop="created_at" label="创建时间" min-width="160" align="center" />
+            <el-table-column prop="updated_at" label="修改时间" min-width="160" align="center" />
+            <el-table-column prop="operator" label="操作者" width="110" align="center" />
+            <el-table-column label="操作" min-width="230" align="center" fixed="right"><template slot-scope="scope"><el-button type="text" size="small" class="operation-link" @click="handleEditIos(scope.row)">编辑</el-button><el-button type="text" size="small" class="operation-link danger-link" @click="handleDeleteIos(scope.row)">删除</el-button><el-button type="text" size="small" class="operation-link" @click="handleIosOperationRecord">操作记录</el-button></template></el-table-column>
+          </el-table>
+        </div>
+        <el-pagination background class="operation-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="page" :page-size="limit" :page-sizes="[10, 20, 50, 100]" :total="iosRows.length" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
+      </template>
+    </div>
+
+    <Dialog ref="packageDialog" :dialog-actions="packageDialogActions">
+      <template slot="content">
+        <el-form :model="packageForm" label-width="110px" class="app-dialog-form">
+          <el-form-item label="平台"><el-select v-model="packageForm.platform"><el-option label="安卓" value="安卓" /><el-option label="ios" value="ios" /></el-select></el-form-item>
+          <el-form-item label="版号"><el-input v-model="packageForm.version" placeholder="请输入版号" /></el-form-item>
+          <el-form-item label="安装包名"><el-input v-model="packageForm.package_name" placeholder="请输入安装包名" /></el-form-item>
+          <el-form-item label="强制更新"><el-switch v-model="packageForm.force_update" active-color="#13ce66" inactive-color="#c0c4cc" /></el-form-item>
+          <el-form-item label="安装包类型"><el-select v-model="packageForm.package_type"><el-option label="安卓Apk" value="安卓Apk" /><el-option label="Testflight" value="Testflight" /></el-select></el-form-item>
+          <el-form-item label="安装包链接"><el-input v-model="packageForm.package_link" placeholder="请输入安装包链接" /></el-form-item>
+          <el-form-item label="更新内容"><el-input v-model="packageForm.update_content" type="textarea" :rows="4" placeholder="请输入更新内容" /></el-form-item>
+          <div class="dialog-actions"><el-button type="primary" @click="submitPackage">提交</el-button></div>
+        </el-form>
+      </template>
+    </Dialog>
+
+    <Dialog ref="iosDialog" :dialog-actions="iosDialogActions">
+      <template slot="content">
+        <el-form :model="iosForm" label-width="130px" class="app-dialog-form">
+          <el-form-item label="平台"><el-input v-model="iosForm.platform" disabled /></el-form-item>
+          <el-form-item label="上架版本"><el-input v-model="iosForm.publish_version" /></el-form-item>
+          <el-form-item label="运营版本"><el-input v-model="iosForm.operation_version" /></el-form-item>
+          <el-form-item label="提供审查用户ID"><el-input v-model="iosForm.review_user_ids" type="textarea" :rows="3" /></el-form-item>
+          <div class="dialog-actions"><el-button type="primary" @click="submitIos">提交</el-button></div>
+        </el-form>
+      </template>
+    </Dialog>
+
+    <Dialog ref="iosOperationDialog" :dialog-actions="{ width: '900px', title: '操作记录', confirmButtom: false }">
+      <template slot="content">
+        <el-form :model="operationQuery" class="operation-record-search" inline size="small">
+          <el-form-item label="时间"><el-date-picker v-model="operationQuery.date_range" type="daterange" value-format="yyyy-MM-dd" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="disableFutureDate" /></el-form-item>
+          <el-form-item label="操作员账号"><el-input v-model="operationQuery.operator" placeholder="请输入操作员账号" clearable /></el-form-item>
+          <el-form-item class="search-actions"><el-button type="primary" @click="searchOperationRecords">查询</el-button><el-button @click="resetOperationQuery">重置</el-button></el-form-item>
+        </el-form>
+        <el-table :data="pagedOperationRows" height="360" class="operation-record-table">
+          <el-table-column type="index" label="序号" width="70" align="center" />
+          <el-table-column prop="date" label="日期" min-width="160" align="center" />
+          <el-table-column prop="operator" label="操作员账号" min-width="130" align="center" />
+          <el-table-column prop="item" label="操作项目" min-width="120" align="center" />
+          <el-table-column prop="attribute" label="属性" min-width="120" align="center" />
+          <el-table-column prop="old_value" label="旧值" min-width="110" align="center" />
+          <el-table-column prop="new_value" label="新值" min-width="110" align="center" />
+        </el-table>
+        <el-pagination background class="operation-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="operationPage" :page-size="operationLimit" :page-sizes="[10, 20, 50]" :total="filteredOperationRows.length" @size-change="handleOperationSizeChange" @current-change="handleOperationCurrentChange" />
+      </template>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/components/Dialog/index.vue'
+import { disableFutureDate } from '@/utils/index'
+
+const createAppRow = (row) => ({
+  status: 1,
+  operator: 'admin',
+  created_at: '2025-03-10 11:25:23',
+  updated_at: '2025-04-10 11:25:23',
+  ...row
+})
+
+export default {
+  name: 'OperationAppConfig',
+  components: { Dialog },
+  data() {
+    return {
+      disableFutureDate,
+      loading: false,
+      activeTab: 'package',
+      page: 1,
+      limit: 10,
+      query: { date_range: [] },
+      displaySettings: { ios: false, android: false },
+      packageForm: {},
+      iosForm: {},
+      packageDialogMode: 'create',
+      packageEditRow: null,
+      iosEditRow: null,
+      iosDialogMode: 'edit',
+      operationPage: 1,
+      operationLimit: 10,
+      operationQuery: { date_range: [], operator: '' },
+      operationRows: [
+        { date: '2025-03-07 22:16:43', operator: 'hope123', item: '更新', attribute: '运营版本', old_value: '122', new_value: '123' },
+        { date: '2025-03-06 18:20:11', operator: 'admin', item: '更新', attribute: '提供审查用户ID', old_value: '66801,66802', new_value: '66811,66812,66813' }
+      ],
+      packageRows: [
+        createAppRow({ platform: '安卓', package_link: 'https://show2.cc/ywx.apk', version: '123', force_update: true, package_name: 'ywx.apk', package_type: '安卓Apk', update_content: '1. 更新了首页,更高用户体验' }),
+        createAppRow({ platform: 'ios', package_link: 'https://testflight.apple.com/join/Swqj981X', version: '123', force_update: true, package_name: 'ywx.ipa', package_type: 'Testflight', update_content: '1. 更新了首页,更高用户体验' }),
+        createAppRow({ platform: '安卓', package_link: 'https://show2.cc/ywx-122.apk', version: '122', force_update: false, package_name: 'ywx-122.apk', package_type: '安卓Apk', update_content: '优化登录体验' })
+      ],
+      downloadRows: [
+        { platform: '安卓', source: '百度统计', download_link: 'https://show2.cc/ywx.apk', click_count: 19 },
+        { platform: 'ios', source: '百度统计', download_link: 'https://testflight.apple.com/join/Swqj981X', click_count: 33 }
+      ],
+      downloadAppRows: [
+        { platform: '安卓', package_type: '安卓Apk', download_count: 213 },
+        { platform: 'ios', package_type: 'Testflight', download_count: 456 }
+      ],
+      iosRows: [
+        createAppRow({ platform: 'ios', publish_version: '20.0', operation_version: '123', review_user_ids: '66811,66812,66813' }),
+        createAppRow({ platform: 'ios', publish_version: '19.8', operation_version: '122', review_user_ids: '66821,66822' }),
+        createAppRow({ platform: 'ios', publish_version: '19.5', operation_version: '121', review_user_ids: '66831,66832' })
+      ]
+    }
+  },
+  computed: {
+    pagedPackageRows() { return this.getPagedRows(this.packageRows) },
+    pagedDownloadRows() { return this.getPagedRows(this.downloadRows) },
+    pagedDownloadAppRows() { return this.getPagedRows(this.downloadAppRows) },
+    pagedIosRows() { return this.getPagedRows(this.iosRows) },
+    packageDialogActions() {
+      return { width: '700px', title: `${this.packageDialogMode === 'edit' ? '编辑' : '创建'}安装包`, buttom: false, confirmButtom: false }
+    },
+    iosDialogActions() {
+      return { width: '620px', title: `${this.iosDialogMode === 'edit' ? '编辑' : '新增'}IOS上架设置`, buttom: false, confirmButtom: false }
+    },
+    filteredOperationRows() {
+      const operator = (this.operationQuery.operator || '').trim().toLowerCase()
+      return this.operationRows.filter(row => !operator || row.operator.toLowerCase().includes(operator))
+    },
+    pagedOperationRows() {
+      const start = (this.operationPage - 1) * this.operationLimit
+      return this.filteredOperationRows.slice(start, start + this.operationLimit)
+    }
+  },
+  mounted() {
+    this.packageForm = this.getPackageForm()
+    this.iosForm = this.getIosForm()
+  },
+  methods: {
+    getPagedRows(rows) {
+      const start = (this.page - 1) * this.limit
+      return rows.slice(start, start + this.limit)
+    },
+    getPackageForm(row = {}) {
+      return { platform: '安卓', version: '', package_name: '', force_update: false, package_type: '安卓Apk', package_link: '', update_content: '', ...row }
+    },
+    getIosForm(row = {}) {
+      return { platform: 'ios', publish_version: '', operation_version: '', review_user_ids: '', ...row }
+    },
+    handleSearch() {
+      this.page = 1
+    },
+    resetQuery() {
+      this.query = { date_range: [] }
+      this.page = 1
+    },
+    handleTabChange() {
+      this.query = { date_range: [] }
+      this.page = 1
+    },
+    handleSizeChange(value) {
+      this.limit = value
+      this.page = 1
+    },
+    handleCurrentChange(value) {
+      this.page = value
+    },
+    saveDisplaySettings() {
+      this.$message.success('设置已更新')
+    },
+    toggleStatus(row) {
+      row.status = row.status === 1 ? 0 : 1
+    },
+    handleCreatePackage() {
+      this.packageDialogMode = 'create'
+      this.packageEditRow = null
+      this.packageForm = this.getPackageForm()
+      this.$refs.packageDialog.open()
+    },
+    handleEditPackage(row) {
+      this.packageDialogMode = 'edit'
+      this.packageEditRow = row
+      this.packageForm = this.getPackageForm(row)
+      this.$refs.packageDialog.open()
+    },
+    submitPackage() {
+      if (this.packageDialogMode === 'edit') {
+        const targetIndex = this.packageRows.indexOf(this.packageEditRow)
+        if (targetIndex !== -1) this.$set(this.packageRows, targetIndex, { ...this.packageRows[targetIndex], ...this.packageForm })
+      } else {
+        this.packageRows.unshift(createAppRow({ ...this.packageForm }))
+      }
+      this.$refs.packageDialog.close()
+      this.$message.success('提交成功')
+    },
+    handleDeletePackage(row) {
+      this.$confirm('确定删除这个安装包吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
+        const index = this.packageRows.indexOf(row)
+        if (index !== -1) this.packageRows.splice(index, 1)
+        this.$message.success('删除成功')
+      }).catch(() => {})
+    },
+    handleEditIos(row) {
+      this.iosDialogMode = 'edit'
+      this.iosEditRow = row
+      this.iosForm = this.getIosForm(row)
+      this.$refs.iosDialog.open()
+    },
+    handleCreateIos() {
+      this.iosDialogMode = 'create'
+      this.iosEditRow = null
+      this.iosForm = this.getIosForm()
+      this.$refs.iosDialog.open()
+    },
+    submitIos() {
+      if (this.iosDialogMode === 'edit') {
+        const targetIndex = this.iosRows.indexOf(this.iosEditRow)
+        if (targetIndex !== -1) {
+          const oldRow = { ...this.iosRows[targetIndex] }
+          const updatedRow = { ...this.iosRows[targetIndex], ...this.iosForm }
+          this.$set(this.iosRows, targetIndex, updatedRow)
+          this.addIosOperationRecord('更新', oldRow, updatedRow)
+        }
+      } else {
+        const createdRow = createAppRow({ ...this.iosForm })
+        this.iosRows.unshift(createdRow)
+        this.addIosOperationRecord('新增', null, createdRow)
+      }
+      this.$refs.iosDialog.close()
+      this.$message.success('提交成功')
+    },
+    handleDeleteIos(row) {
+      this.$confirm('确定删除这条上架配置吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
+        const index = this.iosRows.indexOf(row)
+        if (index !== -1) this.iosRows.splice(index, 1)
+        this.$message.success('删除成功')
+      }).catch(() => {})
+    },
+    handleIosOperationRecord() {
+      this.operationPage = 1
+      this.operationQuery = { date_range: [], operator: '' }
+      this.$refs.iosOperationDialog.open()
+    },
+    searchOperationRecords() {
+      this.operationPage = 1
+    },
+    resetOperationQuery() {
+      this.operationQuery = { date_range: [], operator: '' }
+      this.operationPage = 1
+    },
+    handleOperationSizeChange(value) {
+      this.operationLimit = value
+      this.operationPage = 1
+    },
+    handleOperationCurrentChange(value) {
+      this.operationPage = value
+    },
+    addIosOperationRecord(item, oldRow, newRow) {
+      const fields = [
+        { key: 'platform', label: '平台' },
+        { key: 'publish_version', label: '上架版本' },
+        { key: 'operation_version', label: '运营版本' },
+        { key: 'review_user_ids', label: '提供审查用户ID' }
+      ]
+      const now = new Date()
+      const date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
+      const records = fields.filter(field => item === '新增' || String((newRow || {})[field.key]) !== String((oldRow || {})[field.key])).map(field => ({
+        date,
+        operator: 'admin',
+        item,
+        attribute: field.label,
+        old_value: item === '新增' ? '--' : (oldRow || {})[field.key],
+        new_value: (newRow || {})[field.key]
+      }))
+      this.operationRows.unshift(...records)
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.operation-setting-page { height: 100%; padding: 16px; background: #f5f7fa; box-sizing: border-box; }
+.operation-setting-panel { display: flex; flex: 1; flex-direction: column; min-width: 0; min-height: 0; padding: 0 20px 12px; overflow: hidden; background: #fff; box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08); }
+.operation-tabs { flex-shrink: 0; ::v-deep .el-tabs__header { margin: 0; } ::v-deep .el-tabs__item { height: 52px; line-height: 52px; font-weight: 500; } }
+.operation-search { flex-shrink: 0; padding-top: 16px; ::v-deep .el-form-item { margin-right: 38px; margin-bottom: 14px; } ::v-deep .el-form-item__label { color: #303133; font-weight: 500; } ::v-deep .el-date-editor--daterange.el-input__inner { width: 320px; } .search-actions { margin-right: 0; } }
+.display-settings { flex-shrink: 0; padding: 14px 18px 10px; border: 1px solid #ebeef5; background: #fff; }
+.display-settings-title { margin-bottom: 8px; color: #303133; font-size: 14px; font-weight: 500; }
+.display-setting-item { display: inline-flex; align-items: center; width: 220px; color: #606266; font-size: 14px; }
+.display-setting-item span { width: 130px; }
+.operation-toolbar { display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; min-height: 42px; padding-bottom: 10px; }
+.operation-toolbar-title { color: #303133; font-size: 15px; font-weight: 500; }
+.operation-table-wrap { display: flex; flex: 1; min-height: 0; flex-direction: column; }
+.download-table-wrap { gap: 12px; }
+.operation-table { flex: 1; ::v-deep th { height: 44px; background: #f5f7fa; } ::v-deep th .cell { color: #606266 !important; font-weight: 500; } ::v-deep td { height: 49px; } ::v-deep td .cell { color: #606266; font-size: 14px; } ::v-deep .el-table__fixed-right { height: 100% !important; } }
+.compact-table { flex: 1 1 50%; min-height: 160px; }
+.operation-link { margin: 0 4px; color: #3e7bfa; }
+.danger-link { color: #f56c6c; }
+.operation-pagination { flex-shrink: 0; padding-top: 12px; text-align: right; }
+.app-dialog-form { max-height: 560px; overflow-y: auto; padding: 12px 28px 0; ::v-deep .el-form-item { margin-bottom: 14px; } ::v-deep .el-input, ::v-deep .el-select { width: 360px; } }
+.dialog-actions { padding: 12px 0 4px; text-align: center; }
+</style>

+ 577 - 0
src/views/operationSetting/paymentConfig/index.vue

@@ -0,0 +1,577 @@
+<template>
+  <div class="new-app-container layout-vertical operation-setting-page">
+    <div class="operation-setting-panel">
+      <el-tabs v-model="activeTab" class="operation-tabs" @tab-click="handleTabChange">
+        <el-tab-pane label="扫描直充" name="direct" />
+        <el-tab-pane label="网关支付" name="gateway" />
+        <el-tab-pane label="代收代付" name="third" />
+      </el-tabs>
+
+      <el-form ref="queryForm" :model="query" class="operation-search" inline size="small" @submit.native.prevent="handleSearch">
+        <template v-if="activeTab === 'direct'">
+          <el-form-item label="时间">
+            <el-date-picker
+              v-model="query.date_range"
+              type="daterange"
+              value-format="yyyy-MM-dd"
+              range-separator="-"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :picker-options="disableFutureDate"
+            />
+          </el-form-item>
+          <el-form-item label="充值名称">
+            <el-input v-model="query.keyword" placeholder="请输入充值名称" clearable />
+          </el-form-item>
+        </template>
+        <template v-else>
+          <el-form-item label="网关类型">
+            <el-radio-group v-model="gatewayType" size="small" @change="handleGatewayTypeChange">
+              <el-radio-button label="deposit">{{ activeTab === 'gateway' ? '存款网关' : '代收扫描' }}</el-radio-button>
+              <el-radio-button label="withdraw">{{ activeTab === 'gateway' ? '出款网关' : '代收三方' }}</el-radio-button>
+            </el-radio-group>
+          </el-form-item>
+          <el-form-item v-if="activeTab === 'gateway'" label="支付公司">
+            <el-select v-model="query.payment_company" placeholder="请选择支付公司" clearable>
+              <el-option label="188pay" value="188pay" />
+              <el-option label="wepay" value="wepay" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-else label="代收三方">
+            <el-select v-model="query.third_party" placeholder="请选择代收三方" clearable>
+              <el-option label="富基代收" value="富基代收" />
+              <el-option label="AA支付" value="AA支付" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="gatewayType === 'deposit'" label="支付方式">
+            <el-select v-model="query.payment_method" placeholder="请选择支付方式" clearable>
+              <el-option label="UPI" value="UPI" />
+              <el-option label="微信" value="微信" />
+              <el-option label="支付宝" value="支付宝" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="gatewayType === 'withdraw'" label="状态">
+            <el-select v-model="query.status" placeholder="请选择状态" clearable>
+              <el-option label="启用" :value="1" />
+              <el-option label="禁用" :value="0" />
+            </el-select>
+          </el-form-item>
+          <el-form-item v-if="gatewayType === 'deposit'" label="层级">
+            <el-select v-model="query.level" placeholder="请选择层级" clearable>
+              <el-option label="全部" value="全部" />
+              <el-option label="未分层" value="未分层" />
+            </el-select>
+          </el-form-item>
+        </template>
+        <el-form-item class="search-actions">
+          <el-button type="primary" :loading="loading" @click="handleSearch">查询</el-button>
+          <el-button @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <div class="operation-toolbar">
+        <span class="operation-toolbar-title">{{ tableTitle }}</span>
+        <el-button type="primary" size="small" @click="handleCreate">新增{{ addLabel }}</el-button>
+      </div>
+
+      <div class="operation-table-wrap">
+        <el-table v-loading="loading" :data="pagedRows" height="100%" class="operation-table">
+          <el-table-column type="index" label="序号" width="70" align="center" />
+          <template v-if="activeTab === 'direct'">
+            <el-table-column prop="id" label="充值ID" min-width="110" align="center" />
+            <el-table-column prop="amount" label="充值金额" min-width="110" align="center" />
+            <el-table-column prop="name" label="充值名称" min-width="180" align="center" />
+            <el-table-column label="手续费" min-width="100" align="center">
+              <template slot-scope="scope">{{ formatFee(scope.row.fee) }}</template>
+            </el-table-column>
+            <el-table-column label="实际到账" min-width="110" align="center">
+              <template slot-scope="scope">{{ getFeeAmount(scope.row) }}</template>
+            </el-table-column>
+            <el-table-column prop="created_at" label="创建时间" min-width="160" align="center" />
+            <el-table-column prop="updated_at" label="修改时间" min-width="160" align="center" />
+          </template>
+          <template v-else-if="activeTab === 'gateway' && gatewayType === 'deposit'">
+            <el-table-column prop="payment_company" label="支付公司" min-width="120" align="center" />
+            <el-table-column prop="merchant_no" label="商户号" min-width="150" align="center" />
+            <el-table-column prop="payment_method" label="支付方式" min-width="110" align="center" />
+            <el-table-column prop="channel_no" label="通道编号" min-width="100" align="center" />
+            <el-table-column prop="channel_name" label="通道名称" min-width="110" align="center" />
+            <el-table-column prop="sort" label="排序" width="80" align="center" />
+            <el-table-column prop="fee" label="金流手续费" min-width="110" align="center" />
+            <el-table-column prop="min_amount" label="最低额度" min-width="100" align="center" />
+            <el-table-column prop="max_amount" label="最高额度" min-width="100" align="center" />
+            <el-table-column prop="level" label="层级" min-width="100" align="center" />
+          </template>
+          <template v-else-if="activeTab === 'gateway'">
+            <el-table-column prop="payment_company" label="支付公司" min-width="120" align="center" />
+            <el-table-column prop="merchant_no" label="商户号" min-width="150" align="center" />
+            <el-table-column prop="fee" label="金流手续费" min-width="110" align="center" />
+            <el-table-column prop="level" label="层级" min-width="100" align="center" />
+          </template>
+          <template v-else>
+            <el-table-column prop="third_party" label="代收三方" min-width="120" align="center" />
+            <el-table-column prop="group_name" label="群名称" min-width="120" align="center" />
+            <el-table-column prop="payment_method" label="收款方式" min-width="110" align="center" />
+            <el-table-column prop="channel_no" label="通道编号" min-width="100" align="center" />
+            <el-table-column prop="channel_name" label="通道名称" min-width="110" align="center" />
+            <el-table-column prop="sort" label="排序" width="80" align="center" />
+            <el-table-column prop="fee" label="金流手续费" min-width="110" align="center" />
+            <el-table-column prop="min_amount" label="最低额度" min-width="100" align="center" />
+            <el-table-column prop="max_amount" label="最高额度" min-width="100" align="center" />
+            <el-table-column prop="level" label="层级" min-width="100" align="center" />
+          </template>
+          <el-table-column label="状态" width="100" align="center">
+            <template slot-scope="scope">
+              <el-switch
+                :value="scope.row.status === 1"
+                active-color="#13ce66"
+                inactive-color="#c0c4cc"
+                @change="toggleStatus(scope.row)"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column prop="operator" label="操作者" width="110" align="center" />
+          <el-table-column label="操作" min-width="210" align="center" fixed="right">
+            <template slot-scope="scope">
+              <el-button type="text" size="small" class="operation-link" @click="handleEdit(scope.row)">编辑</el-button>
+              <el-button type="text" size="small" class="operation-link danger-link" @click="handleDelete(scope.row)">删除</el-button>
+              <el-button type="text" size="small" class="operation-link" @click="handleOperationRecord(scope.row)">操作记录</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <el-pagination
+        background
+        class="operation-pagination"
+        layout="total, sizes, prev, pager, next, jumper"
+        :current-page="page"
+        :page-size="limit"
+        :page-sizes="[10, 20, 50, 100]"
+        :total="filteredRows.length"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+
+    <Dialog ref="paymentDialog" :dialog-actions="paymentDialogActions">
+      <template slot="content">
+        <el-form :model="paymentForm" label-width="120px" class="payment-dialog-form">
+          <template v-if="paymentDialogType === 'direct'">
+            <el-form-item label="充值名称"><el-input v-model="paymentForm.name" placeholder="请输入充值名称" /></el-form-item>
+            <el-form-item label="充值ID"><el-input v-model="paymentForm.id" placeholder="请输入充值ID" /></el-form-item>
+            <el-form-item label="充值金额"><el-input v-model="paymentForm.amount" placeholder="请输入充值金额" /></el-form-item>
+            <el-form-item label="手续费"><el-input :value="getFeePercentInput(paymentForm.fee)" type="number" min="0" max="100" @input="setFeePercent"><template slot="append">%</template></el-input></el-form-item>
+            <el-form-item label="实际到账"><span class="calculated-value">{{ getFeeAmount(paymentForm) }}</span></el-form-item>
+          </template>
+          <template v-else-if="paymentDialogType === 'deposit'">
+            <el-form-item label="币种"><el-input v-model="paymentForm.currency" disabled /></el-form-item>
+            <el-form-item label="支付公司"><el-select v-model="paymentForm.payment_company"><el-option label="188pay" value="188pay" /><el-option label="wepay" value="wepay" /></el-select></el-form-item>
+            <el-form-item label="商户号"><el-input v-model="paymentForm.merchant_no" placeholder="请输入商户号" /></el-form-item>
+            <el-form-item label="MD5密钥"><el-input v-model="paymentForm.md5_key" placeholder="请输入MD5密钥" /></el-form-item>
+            <el-form-item label="支付方式"><el-input v-model="paymentForm.payment_method" disabled /></el-form-item>
+            <el-form-item label="通道编号"><el-input v-model="paymentForm.channel_no" placeholder="请输入通道编号" /></el-form-item>
+            <el-form-item label="通道名称"><el-input v-model="paymentForm.channel_name" placeholder="请输入通道名称" /></el-form-item>
+            <el-form-item label="金流手续费"><el-input v-model="paymentForm.fee"><template slot="append">%</template></el-input></el-form-item>
+            <el-form-item label="额度限制"><el-select v-model="paymentForm.limit_type"><el-option label="存款金额范围" value="存款金额范围" /><el-option label="自定义" value="自定义" /></el-select></el-form-item>
+            <el-form-item label="最低额度"><el-input v-model="paymentForm.min_amount" /></el-form-item>
+            <el-form-item label="最高额度"><el-input v-model="paymentForm.max_amount" /></el-form-item>
+            <el-form-item label="排序"><el-input v-model="paymentForm.sort" /></el-form-item>
+            <el-form-item label="层级"><el-select v-model="paymentForm.level"><el-option label="全部" value="全部" /><el-option label="未分层" value="未分层" /></el-select></el-form-item>
+          </template>
+          <template v-else-if="paymentDialogType === 'withdraw'">
+            <el-form-item label="币种"><el-input v-model="paymentForm.currency" disabled /></el-form-item>
+            <el-form-item label="支付公司"><el-select v-model="paymentForm.payment_company"><el-option label="wepay" value="wepay" /><el-option label="188pay" value="188pay" /></el-select></el-form-item>
+            <el-form-item label="商户号"><el-input v-model="paymentForm.merchant_no" placeholder="请输入商户号" /></el-form-item>
+            <el-form-item label="金流手续费"><el-input v-model="paymentForm.fee"><template slot="append">%</template></el-input></el-form-item>
+            <el-form-item label="出款密钥"><el-input v-model="paymentForm.withdraw_key" type="textarea" :rows="3" placeholder="请输入出款密钥" /></el-form-item>
+            <el-form-item label="最低额度"><el-input v-model="paymentForm.min_amount" /></el-form-item>
+            <el-form-item label="最高额度"><el-input v-model="paymentForm.max_amount" /></el-form-item>
+            <el-form-item label="出款层级"><el-select v-model="paymentForm.level"><el-option label="全部" value="全部" /><el-option label="未分层" value="未分层" /></el-select></el-form-item>
+          </template>
+          <template v-else>
+            <el-form-item label="币种"><el-input v-model="paymentForm.currency" disabled /></el-form-item>
+            <el-form-item label="代收三方"><el-input v-model="paymentForm.third_party" placeholder="请输入代收三方" /></el-form-item>
+            <el-form-item label="群名称"><el-input v-model="paymentForm.group_name" placeholder="请输入群名称" /></el-form-item>
+            <el-form-item label="收款方式"><el-input v-model="paymentForm.payment_method" placeholder="请输入收款方式" /></el-form-item>
+            <el-form-item label="通道编号"><el-input v-model="paymentForm.channel_no" placeholder="请输入通道编号" /></el-form-item>
+            <el-form-item label="通道名称"><el-input v-model="paymentForm.channel_name" placeholder="请输入通道名称" /></el-form-item>
+            <el-form-item label="金流手续费"><el-input v-model="paymentForm.fee"><template slot="append">%</template></el-input></el-form-item>
+            <el-form-item label="最低金额"><el-input v-model="paymentForm.min_amount" /></el-form-item>
+            <el-form-item label="最高金额"><el-input v-model="paymentForm.max_amount" /></el-form-item>
+            <el-form-item label="层级"><el-select v-model="paymentForm.level"><el-option label="全部" value="全部" /><el-option label="未分层" value="未分层" /></el-select></el-form-item>
+          </template>
+          <div class="dialog-actions"><el-button type="primary" @click="submitPayment">提交</el-button></div>
+        </el-form>
+      </template>
+    </Dialog>
+
+    <Dialog ref="operationDialog" :dialog-actions="{ width: '900px', title: '操作记录', confirmButtom: false }">
+      <template slot="content">
+        <el-form :model="operationQuery" class="operation-record-search" inline size="small">
+          <el-form-item label="时间">
+            <el-date-picker v-model="operationQuery.date_range" type="daterange" value-format="yyyy-MM-dd" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="disableFutureDate" />
+          </el-form-item>
+          <el-form-item label="操作员账号"><el-input v-model="operationQuery.operator" placeholder="请输入操作员账号" clearable /></el-form-item>
+          <el-form-item class="search-actions"><el-button type="primary" @click="searchOperationRecords">查询</el-button><el-button @click="resetOperationQuery">重置</el-button></el-form-item>
+        </el-form>
+        <el-table :data="pagedOperationRows" height="360" class="operation-record-table">
+          <el-table-column type="index" label="序号" width="70" align="center" />
+          <el-table-column prop="date" label="日期" min-width="160" align="center" />
+          <el-table-column prop="operator" label="操作员账号" min-width="130" align="center" />
+          <el-table-column prop="item" label="操作项目" min-width="120" align="center" />
+          <el-table-column prop="attribute" label="属性" min-width="100" align="center" />
+          <el-table-column prop="old_value" label="旧值" min-width="100" align="center" />
+          <el-table-column prop="new_value" label="新值" min-width="100" align="center" />
+        </el-table>
+        <el-pagination background class="operation-record-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="operationPage" :page-size="operationLimit" :page-sizes="[10, 20, 50]" :total="filteredOperationRows.length" @size-change="handleOperationSizeChange" @current-change="handleOperationCurrentChange" />
+      </template>
+    </Dialog>
+  </div>
+</template>
+
+<script>
+import Dialog from '@/components/Dialog/index.vue'
+import { disableFutureDate } from '@/utils/index'
+
+const createPaymentRow = (row) => ({
+  status: 1,
+  operator: 'admin',
+  created_at: '2025-03-10 11:25:23',
+  updated_at: '2025-04-10 11:25:23',
+  ...row
+})
+
+const getFeeNumber = (fee) => Number(String(fee == null ? 0 : fee).replace('%', '')) || 0
+const getFeeAmountValue = (row = {}) => ((Number(row.amount) || 0) - (Number(row.amount) || 0) * getFeeNumber(row.fee))
+const getDirectDisplayNameValue = (row = {}) => `到账金额${getFeeAmountValue(row).toFixed(2)}`
+const createDirectRow = (row) => {
+  const directRow = createPaymentRow({ fee: Math.floor(Math.random() * 101) / 100, ...row })
+  return {
+    ...directRow,
+    name: directRow.name || getDirectDisplayNameValue(directRow),
+    actual_amount: getFeeAmountValue(directRow).toFixed(2)
+  }
+}
+
+export default {
+  name: 'OperationPaymentConfig',
+  components: { Dialog },
+  data() {
+    return {
+      disableFutureDate,
+      loading: false,
+      activeTab: 'direct',
+      gatewayType: 'deposit',
+      page: 1,
+      limit: 10,
+      query: this.getDefaultQuery(),
+      operationPage: 1,
+      operationLimit: 10,
+      operationQuery: { date_range: [], operator: '' },
+      paymentDialogType: 'direct',
+      paymentDialogMode: 'create',
+      paymentEditRow: null,
+      paymentForm: {},
+      directRows: [
+        createDirectRow({ id: '2025698', amount: '698.00' }),
+        createDirectRow({ id: '2025699', amount: '100.00' }),
+        createDirectRow({ id: '2025700', amount: '50.00' })
+      ],
+      depositRows: [
+        createPaymentRow({ payment_company: '188pay', merchant_no: 'f6f087b56a', payment_method: 'UPI', channel_no: '90', channel_name: '支付1', sort: 1, fee: '3%', min_amount: 50, max_amount: 50000, level: '全部' }),
+        createPaymentRow({ payment_company: 'wepay', merchant_no: 'wp202503', payment_method: '微信', channel_no: '91', channel_name: '支付2', sort: 2, fee: '2%', min_amount: 20, max_amount: 30000, level: '未分层' })
+      ],
+      withdrawRows: [
+        createPaymentRow({ payment_company: '188pay', merchant_no: 'f6f087b56a', fee: '3%', level: '全部', min_amount: 50, max_amount: 50000 })
+      ],
+      thirdRows: [
+        createPaymentRow({ third_party: '富基代收', group_name: 'AA支付', payment_method: '微信', channel_no: '90', channel_name: '支付1', sort: 1, fee: '3%', min_amount: 50, max_amount: 50000, level: '全部' }),
+        createPaymentRow({ third_party: '富基代收', group_name: 'BB支付', payment_method: '支付宝', channel_no: '91', channel_name: '支付2', sort: 2, fee: '2%', min_amount: 20, max_amount: 30000, level: '未分层' })
+      ],
+      operationRows: [
+        { date: '2025-03-07 22:16:43', operator: 'hope123', item: '更新', attribute: '状态', old_value: '停用', new_value: '启用' },
+        { date: '2025-03-07 22:16:43', operator: 'hope123', item: '更新', attribute: '状态', old_value: '启用', new_value: '停用' },
+        { date: '2025-03-06 18:20:11', operator: 'admin', item: '更新', attribute: '手续费', old_value: '2%', new_value: '3%' }
+      ]
+    }
+  },
+  computed: {
+    tableTitle() {
+      if (this.activeTab === 'direct') return '直充配置'
+      if (this.activeTab === 'gateway') return this.gatewayType === 'deposit' ? '存款网关' : '出款网关'
+      return '代收三方'
+    },
+    addLabel() {
+      if (this.activeTab === 'direct') return '直充'
+      if (this.activeTab === 'gateway') return this.gatewayType === 'deposit' ? '存款网关' : '出款网关'
+      return '代收三方'
+    },
+    currentRows() {
+      if (this.activeTab === 'direct') return this.directRows
+      if (this.activeTab === 'gateway') return this.gatewayType === 'deposit' ? this.depositRows : this.withdrawRows
+      return this.thirdRows
+    },
+    filteredRows() {
+      const keyword = (this.query.keyword || '').trim().toLowerCase()
+      return this.currentRows.filter(row => {
+        if (keyword && !String(row.name || '').toLowerCase().includes(keyword)) return false
+        if (this.query.payment_company && row.payment_company !== this.query.payment_company) return false
+        if (this.query.third_party && row.third_party !== this.query.third_party) return false
+        if (this.query.payment_method && row.payment_method !== this.query.payment_method) return false
+        if (this.query.level && row.level !== this.query.level) return false
+        if (this.query.status !== '' && this.query.status != null && row.status !== this.query.status) return false
+        return true
+      })
+    },
+    pagedRows() {
+      const start = (this.page - 1) * this.limit
+      return this.filteredRows.slice(start, start + this.limit)
+    },
+    filteredOperationRows() {
+      const operator = (this.operationQuery.operator || '').trim().toLowerCase()
+      return this.operationRows.filter(row => !operator || row.operator.toLowerCase().includes(operator))
+    },
+    pagedOperationRows() {
+      const start = (this.operationPage - 1) * this.operationLimit
+      return this.filteredOperationRows.slice(start, start + this.operationLimit)
+    },
+    paymentDialogActions() {
+      const label = this.paymentDialogMode === 'edit' ? '编辑' : '新增'
+      return { width: '620px', title: `${label}${this.addLabel}`, buttom: false, confirmButtom: false }
+    }
+  },
+  mounted() {
+    this.paymentForm = this.getPaymentForm()
+  },
+  methods: {
+    getDefaultQuery() {
+      return { date_range: [], keyword: '', payment_company: '', third_party: '', payment_method: '', level: '', status: '' }
+    },
+    getPaymentForm(row = {}) {
+      return {
+        currency: 'RMB', name: '', id: '', amount: '', payment_company: '188pay', merchant_no: '', md5_key: '', payment_method: 'UPI', channel_no: '', channel_name: '', fee: 0, limit_type: '存款金额范围', min_amount: '', max_amount: '', sort: '', level: '全部', withdraw_key: '', third_party: '', group_name: '',
+        ...row
+      }
+    },
+    getFeeAmount(row) {
+      return getFeeAmountValue(row).toFixed(2)
+    },
+    getFeePercentInput(fee) {
+      return (getFeeNumber(fee) * 100).toFixed(2).replace(/\.00$/, '')
+    },
+    setFeePercent(value) {
+      const percent = Math.min(100, Math.max(0, Number(value) || 0))
+      this.paymentForm.fee = percent / 100
+    },
+    formatFee(fee) {
+      return `${getFeeNumber(fee) * 100}%`
+    },
+    handleSearch() {
+      this.page = 1
+    },
+    resetQuery() {
+      this.query = this.getDefaultQuery()
+      this.page = 1
+    },
+    handleTabChange() {
+      this.query = this.getDefaultQuery()
+      this.page = 1
+    },
+    handleGatewayTypeChange() {
+      this.query = this.getDefaultQuery()
+      this.page = 1
+    },
+    handleSizeChange(value) {
+      this.limit = value
+      this.page = 1
+    },
+    handleCurrentChange(value) {
+      this.page = value
+    },
+    handleCreate() {
+      this.paymentDialogMode = 'create'
+      this.paymentEditRow = null
+      this.paymentDialogType = this.activeTab === 'direct' ? 'direct' : this.activeTab === 'gateway' ? this.gatewayType : 'third'
+      this.paymentForm = this.getPaymentForm()
+      this.$refs.paymentDialog.open()
+    },
+    handleEdit(row) {
+      this.paymentDialogMode = 'edit'
+      this.paymentEditRow = row
+      this.paymentDialogType = this.activeTab === 'direct' ? 'direct' : this.activeTab === 'gateway' ? this.gatewayType : 'third'
+      this.paymentForm = this.getPaymentForm(row)
+      if (this.paymentDialogType === 'direct' && !this.paymentForm.name) this.paymentForm.name = getDirectDisplayNameValue(this.paymentForm)
+      this.$refs.paymentDialog.open()
+    },
+    submitPayment() {
+      const rows = this.currentRows
+      const oldRow = this.paymentEditRow ? { ...this.paymentEditRow } : null
+      const payload = { ...this.paymentForm }
+      if (this.paymentDialogType === 'direct') {
+        payload.fee = Math.min(1, Math.max(0, getFeeNumber(payload.fee)))
+        payload.name = payload.name || getDirectDisplayNameValue(payload)
+        payload.actual_amount = getFeeAmountValue(payload).toFixed(2)
+      }
+      if (this.paymentDialogMode === 'edit') {
+        const index = rows.indexOf(this.paymentEditRow)
+        if (index !== -1) {
+          const updatedRow = { ...rows[index], ...payload }
+          this.$set(rows, index, updatedRow)
+          this.recordPaymentOperation('更新', oldRow, updatedRow, this.paymentDialogType)
+        }
+      } else {
+        const createdRow = this.paymentDialogType === 'direct' ? createDirectRow(payload) : createPaymentRow(payload)
+        rows.unshift(createdRow)
+        this.recordPaymentOperation('新增', null, createdRow, this.paymentDialogType)
+      }
+      this.$refs.paymentDialog.close()
+      this.$message.success('提交成功')
+    },
+    handleDelete(row) {
+      this.$confirm('确定删除这条配置吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
+        const index = this.currentRows.indexOf(row)
+        if (index !== -1) this.currentRows.splice(index, 1)
+        this.$message.success('删除成功')
+      }).catch(() => {})
+    },
+    toggleStatus(row) {
+      const oldRow = { ...row }
+      row.status = row.status === 1 ? 0 : 1
+      this.recordPaymentOperation('更新', oldRow, row, this.activeTab === 'direct' ? 'direct' : 'other')
+    },
+    recordPaymentOperation(item, oldRow, newRow, type) {
+      const fields = type === 'direct'
+        ? [
+          { key: 'id', label: '充值ID' },
+          { key: 'amount', label: '充值金额' },
+          { key: 'name', label: '充值名称' },
+          { key: 'fee', label: '手续费', value: value => this.formatFee(value.fee) },
+          { key: 'actual_amount', label: '实际到账', value: this.getFeeAmount },
+          { key: 'status', label: '状态', value: value => value.status === 1 ? '启用' : '关闭' }
+        ]
+        : [
+          { key: 'payment_company', label: '支付公司' },
+          { key: 'merchant_no', label: '商户号' },
+          { key: 'fee', label: '手续费' },
+          { key: 'status', label: '状态', value: value => value.status === 1 ? '启用' : '关闭' }
+        ]
+      const now = new Date()
+      const date = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`
+      const records = fields.filter(field => item === '新增' || String(field.value ? field.value(newRow) : newRow[field.key]) !== String(field.value ? field.value(oldRow || {}) : (oldRow || {})[field.key])).map(field => ({
+        date,
+        operator: 'admin',
+        item,
+        attribute: field.label,
+        old_value: item === '新增' ? '--' : (field.value ? field.value(oldRow || {}) : (oldRow || {})[field.key]),
+        new_value: field.value ? field.value(newRow) : newRow[field.key]
+      }))
+      this.operationRows.unshift(...records)
+    },
+    handleOperationRecord() {
+      this.operationPage = 1
+      this.operationQuery = { date_range: [], operator: '' }
+      this.$refs.operationDialog.open()
+    },
+    searchOperationRecords() {
+      this.operationPage = 1
+    },
+    resetOperationQuery() {
+      this.operationQuery = { date_range: [], operator: '' }
+      this.operationPage = 1
+    },
+    handleOperationSizeChange(value) {
+      this.operationLimit = value
+      this.operationPage = 1
+    },
+    handleOperationCurrentChange(value) {
+      this.operationPage = value
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.operation-setting-page {
+  height: 100%;
+  padding: 16px;
+  background: #f5f7fa;
+  box-sizing: border-box;
+}
+
+.operation-setting-panel {
+  display: flex;
+  flex: 1;
+  flex-direction: column;
+  min-width: 0;
+  min-height: 0;
+  padding: 0 20px 12px;
+  overflow: hidden;
+  background: #fff;
+  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08);
+}
+
+.operation-tabs {
+  flex-shrink: 0;
+  ::v-deep .el-tabs__header { margin: 0; }
+  ::v-deep .el-tabs__item { height: 52px; line-height: 52px; font-weight: 500; }
+}
+
+.operation-search {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  flex-shrink: 0;
+  padding-top: 16px;
+  ::v-deep .el-form-item { display: flex; flex: 0 0 auto; align-items: center; margin-right: 18px; margin-bottom: 14px; white-space: nowrap; }
+  ::v-deep .el-form-item__label { float: none; width: auto !important; padding: 0 8px 0 0; color: #303133; font-weight: 500; line-height: 32px; }
+  ::v-deep .el-form-item__content { display: flex; align-items: center; margin-left: 0 !important; line-height: 32px; }
+  ::v-deep .el-input { width: 180px; }
+  ::v-deep .el-select { width: 150px; }
+  ::v-deep .el-date-editor--daterange.el-input__inner { width: 320px; }
+  .search-actions { margin-right: 0; }
+}
+
+.operation-toolbar {
+  display: flex;
+  flex-shrink: 0;
+  align-items: center;
+  justify-content: space-between;
+  min-height: 42px;
+  padding-bottom: 10px;
+}
+
+.operation-toolbar-title { color: #303133; font-size: 15px; font-weight: 500; }
+
+.operation-table-wrap { display: flex; flex: 1; min-height: 0; flex-direction: column; }
+
+.operation-table {
+  flex: 1;
+  ::v-deep th { height: 44px; background: #f5f7fa; }
+  ::v-deep th .cell { color: #606266 !important; font-weight: 500; }
+  ::v-deep td { height: 49px; }
+  ::v-deep td .cell { color: #606266; font-size: 14px; }
+  ::v-deep .el-table__fixed-right { height: 100% !important; }
+}
+
+.operation-link { margin: 0 4px; color: #3e7bfa; }
+.danger-link { color: #f56c6c; }
+
+.operation-pagination, .operation-record-pagination { flex-shrink: 0; padding-top: 12px; text-align: right; }
+
+.payment-dialog-form {
+  max-height: 560px;
+  overflow-y: auto;
+  padding: 12px 28px 0;
+  ::v-deep .el-form-item { margin-bottom: 14px; }
+  ::v-deep .el-input, ::v-deep .el-select { width: 300px; }
+}
+
+.dialog-actions { padding: 12px 0 4px; text-align: center; }
+.calculated-value { display: inline-block; min-width: 300px; color: #606266; line-height: 32px; }
+.operation-record-search { margin-bottom: 12px; }
+.operation-record-search ::v-deep .el-form-item { margin-right: 16px; margin-bottom: 8px; }
+.operation-record-search ::v-deep .el-date-editor--daterange.el-input__inner { width: 300px; }
+.operation-record-search ::v-deep .el-input { width: 160px; }
+.operation-record-table ::v-deep th { background: #f5f7fa; }
+</style>