pxb 1 неделя назад
Родитель
Сommit
561aeeb0a0

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/index.html


+ 328 - 0
src/api/data.js

@@ -575,6 +575,22 @@ export function updateRechargeChannel(params) {
   });
   });
 }
 }
 
 
+export function getRechargeChannelOptions(params) {
+  return request({
+    url: "rechargeChannel/options",
+    method: "get",
+    params: params,
+  });
+}
+
+export function deleteRechargeChannel(data) {
+  return request({
+    url: "rechargeChannel/delete",
+    method: "post",
+    data: data,
+  });
+}
+
 // 3.【财务】充值通道组合列表
 // 3.【财务】充值通道组合列表
 export function getRechargeChannelGroupList(params) {
 export function getRechargeChannelGroupList(params) {
   return request({
   return request({
@@ -593,6 +609,14 @@ export function updateRechargeChannelGroup(params) {
   });
   });
 }
 }
 
 
+export function deleteRechargeChannelGroup(data) {
+  return request({
+    url: "rechargeChannel/deleteGroup",
+    method: "post",
+    data: data,
+  });
+}
+
 // 5.【会员列表】设置用户的充值通道
 // 5.【会员列表】设置用户的充值通道
 export function setUserRechargeChannelGroup(params) {
 export function setUserRechargeChannelGroup(params) {
   return request({
   return request({
@@ -610,6 +634,310 @@ export function getRechargeChannelGetChannel(params) {
   });
   });
 }
 }
 
 
+export function getPaymentCompanyList(params) {
+  return request({
+    url: "paymentCompany/list",
+    method: "get",
+    params: params,
+  });
+}
+
+export function setPaymentCompanyStatus(data) {
+  return request({
+    url: "paymentCompany/status",
+    method: "post",
+    data: data,
+  });
+}
+
+export function getShareMembers(params) {
+  return request({
+    url: "shareEarning/members",
+    method: "get",
+    params,
+  });
+}
+
+export function getSharePromoters(params) {
+  return request({
+    url: "shareEarning/members/promoters",
+    method: "get",
+    params,
+  });
+}
+
+export function getShareRegistrations(params) {
+  return request({
+    url: "shareEarning/members/registrations",
+    method: "get",
+    params,
+  });
+}
+
+export function getShareSummary(params) {
+  return request({
+    url: "shareEarning/summary",
+    method: "get",
+    params,
+  });
+}
+
+export function getShareSettings(params) {
+  return request({
+    url: "shareEarning/settings",
+    method: "get",
+    params,
+  });
+}
+
+export function saveShareSettings(data) {
+  return request({
+    url: "shareEarning/settings/save",
+    method: "post",
+    data,
+  });
+}
+
+export function getShareBlacklists(params) {
+  return request({
+    url: "shareEarning/blacklists",
+    method: "get",
+    params,
+  });
+}
+
+export function saveShareBlacklist(data) {
+  return request({
+    url: "shareEarning/blacklists/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setShareBlacklistStatus(data) {
+  return request({
+    url: "shareEarning/blacklists/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deleteShareBlacklist(data) {
+  return request({
+    url: "shareEarning/blacklists/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getAppDisplaySettings(params) {
+  return request({
+    url: "appConfig/display",
+    method: "get",
+    params,
+  });
+}
+
+export function saveAppDisplaySettings(data) {
+  return request({
+    url: "appConfig/display/save",
+    method: "post",
+    data,
+  });
+}
+
+export function getAppPackages(params) {
+  return request({
+    url: "appConfig/packages",
+    method: "get",
+    params,
+  });
+}
+
+export function saveAppPackage(data) {
+  return request({
+    url: "appConfig/packages/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setAppPackageStatus(data) {
+  return request({
+    url: "appConfig/packages/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deleteAppPackage(data) {
+  return request({
+    url: "appConfig/packages/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getAppDownloadStats(params) {
+  return request({
+    url: "appConfig/downloadStats",
+    method: "get",
+    params,
+  });
+}
+
+export function getIosReviews(params) {
+  return request({
+    url: "appConfig/iosReviews",
+    method: "get",
+    params,
+  });
+}
+
+export function saveIosReview(data) {
+  return request({
+    url: "appConfig/iosReviews/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setIosReviewStatus(data) {
+  return request({
+    url: "appConfig/iosReviews/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deleteIosReview(data) {
+  return request({
+    url: "appConfig/iosReviews/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getAppConfigLogs(params) {
+  return request({
+    url: "appConfig/logs",
+    method: "get",
+    params,
+  });
+}
+
+export function getPaymentConfigOptions(params) {
+  return request({
+    url: "paymentConfig/options",
+    method: "get",
+    params,
+  });
+}
+
+export function getPaymentDirectList(params) {
+  return request({
+    url: "paymentConfig/direct",
+    method: "get",
+    params,
+  });
+}
+
+export function savePaymentDirect(data) {
+  return request({
+    url: "paymentConfig/direct/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setPaymentDirectStatus(data) {
+  return request({
+    url: "paymentConfig/direct/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deletePaymentDirect(data) {
+  return request({
+    url: "paymentConfig/direct/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getPaymentGatewayList(params) {
+  return request({
+    url: "paymentConfig/gateways",
+    method: "get",
+    params,
+  });
+}
+
+export function savePaymentGateway(data) {
+  return request({
+    url: "paymentConfig/gateways/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setPaymentGatewayStatus(data) {
+  return request({
+    url: "paymentConfig/gateways/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deletePaymentGateway(data) {
+  return request({
+    url: "paymentConfig/gateways/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getPaymentCollectionList(params) {
+  return request({
+    url: "paymentConfig/collections",
+    method: "get",
+    params,
+  });
+}
+
+export function savePaymentCollection(data) {
+  return request({
+    url: "paymentConfig/collections/save",
+    method: "post",
+    data,
+  });
+}
+
+export function setPaymentCollectionStatus(data) {
+  return request({
+    url: "paymentConfig/collections/status",
+    method: "post",
+    data,
+  });
+}
+
+export function deletePaymentCollection(data) {
+  return request({
+    url: "paymentConfig/collections/delete",
+    method: "post",
+    data,
+  });
+}
+
+export function getPaymentConfigLogs(params) {
+  return request({
+    url: "paymentConfig/logs",
+    method: "get",
+    params,
+  });
+}
+
 export function getLotteryList(params) {
 export function getLotteryList(params) {
   return request({
   return request({
     url: "lhcLottery/list",
     url: "lhcLottery/list",

+ 191 - 300
src/views/Activity/ShareMoney/index.vue

@@ -31,17 +31,20 @@
           <el-input v-model="query.promoter_account" placeholder="请输入推广账号" clearable />
           <el-input v-model="query.promoter_account" placeholder="请输入推广账号" clearable />
         </el-form-item>
         </el-form-item>
         <template v-if="activeTab === 'blocked'">
         <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-form-item label="会员账号" prop="account">
             <el-input
             <el-input
-              v-model="query.blocked_account"
+              v-model="query.account"
               placeholder="搜索禁止推广账号"
               placeholder="搜索禁止推广账号"
               clearable
               clearable
-              @input="handleBlockedSearch"
             />
             />
           </el-form-item>
           </el-form-item>
+          <el-form-item class="search-actions">
+            <el-button type="primary" :loading="loading" @click="onSubmit">查询</el-button>
+            <el-button @click="resetQuery">重置</el-button>
+          </el-form-item>
+          <el-form-item>
+            <el-button type="primary" @click="handleBlockedCreate">新增</el-button>
+          </el-form-item>
         </template>
         </template>
         <el-form-item v-if="activeTab !== 'blocked'" class="search-actions">
         <el-form-item v-if="activeTab !== 'blocked'" class="search-actions">
           <el-button type="primary" :loading="loading" @click="onSubmit">查询</el-button>
           <el-button type="primary" :loading="loading" @click="onSubmit">查询</el-button>
@@ -53,7 +56,7 @@
         <el-form :model="settingsForm" label-width="190px" class="settings-form">
         <el-form :model="settingsForm" label-width="190px" class="settings-form">
           <el-form-item label="分享赚钱开关(含前台显示)">
           <el-form-item label="分享赚钱开关(含前台显示)">
             <el-switch
             <el-switch
-              v-model="settingsForm.share_enabled"
+              v-model="settingsForm.enabled"
               :active-value="1"
               :active-value="1"
               :inactive-value="0"
               :inactive-value="0"
               active-color="#13ce66"
               active-color="#13ce66"
@@ -64,11 +67,11 @@
             <el-input v-model="settingsForm.share_domain" />
             <el-input v-model="settingsForm.share_domain" />
           </el-form-item>
           </el-form-item>
           <el-form-item label="有效会员最低存款">
           <el-form-item label="有效会员最低存款">
-            <el-input v-model="settingsForm.minimum_deposit" />
+            <el-input v-model="settingsForm.valid_member_min_deposit" />
           </el-form-item>
           </el-form-item>
           <el-form-item label="佣金/手续费减免设置">
           <el-form-item label="佣金/手续费减免设置">
             <el-switch
             <el-switch
-              v-model="settingsForm.commission_enabled"
+              v-model="settingsForm.benefit_enabled"
               :active-value="1"
               :active-value="1"
               :inactive-value="0"
               :inactive-value="0"
               active-color="#13ce66"
               active-color="#13ce66"
@@ -77,17 +80,17 @@
           </el-form-item>
           </el-form-item>
           <div class="commission-settings">
           <div class="commission-settings">
             <el-form-item label="非卖家单笔阈值 >=">
             <el-form-item label="非卖家单笔阈值 >=">
-              <el-input v-model="settingsForm.non_seller_threshold" :disabled="!settingsForm.commission_enabled">
+              <el-input v-model="settingsForm.non_seller_threshold" :disabled="!settingsForm.benefit_enabled">
                 <template slot="append">元</template>
                 <template slot="append">元</template>
               </el-input>
               </el-input>
             </el-form-item>
             </el-form-item>
             <el-form-item label="抽佣阶梯一">
             <el-form-item label="抽佣阶梯一">
-              <el-input v-model="settingsForm.commission_tier_one" :disabled="!settingsForm.commission_enabled">
+              <el-input v-model="settingsForm.tier_one_rate" :disabled="!settingsForm.benefit_enabled">
                 <template slot="append">%</template>
                 <template slot="append">%</template>
               </el-input>
               </el-input>
             </el-form-item>
             </el-form-item>
             <el-form-item label="抽佣阶梯二">
             <el-form-item label="抽佣阶梯二">
-              <el-input v-model="settingsForm.commission_tier_two" :disabled="!settingsForm.commission_enabled">
+              <el-input v-model="settingsForm.tier_two_rate" :disabled="!settingsForm.benefit_enabled">
                 <template slot="append">%</template>
                 <template slot="append">%</template>
               </el-input>
               </el-input>
             </el-form-item>
             </el-form-item>
@@ -109,11 +112,11 @@
           <el-table-column type="index" label="序号" width="100" align="center" />
           <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="date" label="日期" min-width="120" align="center" />
           <el-table-column prop="promoter_account" label="推广账号" min-width="140" 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="promoter_nickname" label="推广昵称" min-width="140" align="center" />
           <el-table-column prop="deposit" label="存款" min-width="120" 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="commission" label="佣金" min-width="120" align="center" />
           <el-table-column prop="sales_amount" 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-column prop="fee_waiver_rate" label="手续费减免" min-width="160" align="center" />
         </el-table>
         </el-table>
         <div v-if="activeTab === 'summary'" class="summary-footer">
         <div v-if="activeTab === 'summary'" class="summary-footer">
           <span>总佣金:<strong>{{ summaryCommission }}</strong></span>
           <span>总佣金:<strong>{{ summaryCommission }}</strong></span>
@@ -127,8 +130,10 @@
           class="share-money-list blocked-list"
           class="share-money-list blocked-list"
         >
         >
           <el-table-column type="index" label="序号" width="100" align="center" />
           <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 prop="account" label="会员账号" min-width="180" align="center" />
+          <el-table-column label="不能返佣的类目" min-width="260" align="center">
+            <template slot-scope="scope">{{ formatBlockedCategories(scope.row.blocked_categories) }}</template>
+          </el-table-column>
           <el-table-column label="状态" min-width="160" align="center">
           <el-table-column label="状态" min-width="160" align="center">
             <template slot-scope="scope">
             <template slot-scope="scope">
               <el-switch
               <el-switch
@@ -169,19 +174,19 @@
               <span>{{ scope.row.registered_members }}</span>
               <span>{{ scope.row.registered_members }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column prop="h5_register" label="H5注册" min-width="110" align="center">
+          <el-table-column prop="h5_registered" label="H5注册" min-width="110" align="center">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              <span>{{ scope.row.h5_register }}</span>
+              <span>{{ scope.row.h5_registered }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column prop="ios_register" label="ios注册" min-width="110" align="center">
+          <el-table-column prop="ios_registered" label="ios注册" min-width="110" align="center">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              <span>{{ scope.row.ios_register }}</span>
+              <span>{{ scope.row.ios_registered }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column prop="android_register" label="安卓注册" min-width="110" align="center">
+          <el-table-column prop="android_registered" label="安卓注册" min-width="110" align="center">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              <span>{{ scope.row.android_register }}</span>
+              <span>{{ scope.row.android_registered }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
           <el-table-column prop="deposit_total" label="存款总额" min-width="120" align="center">
           <el-table-column prop="deposit_total" label="存款总额" min-width="120" align="center">
@@ -189,9 +194,9 @@
               <span>{{ scope.row.deposit_total }}</span>
               <span>{{ scope.row.deposit_total }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column prop="consumption_total" label="消费金额" min-width="120" align="center">
+          <el-table-column prop="consume_total" label="投注扣款" min-width="120" align="center">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              <span>{{ scope.row.consumption_total }}</span>
+              <span>{{ scope.row.consume_total }}</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
           <el-table-column prop="company_profit" label="公司盈利" min-width="120" align="center">
           <el-table-column prop="company_profit" label="公司盈利" min-width="120" align="center">
@@ -235,7 +240,7 @@
               <el-input v-model="detailQuery.member_id" placeholder="请输入会员ID" clearable />
               <el-input v-model="detailQuery.member_id" placeholder="请输入会员ID" clearable />
             </el-form-item>
             </el-form-item>
             <el-form-item label="会员账号">
             <el-form-item label="会员账号">
-              <el-input v-model="detailQuery.member_account" placeholder="请输入会员账号" clearable />
+              <el-input v-model="detailQuery.account" placeholder="请输入会员账号" clearable />
             </el-form-item>
             </el-form-item>
             <el-form-item class="detail-search-actions">
             <el-form-item class="detail-search-actions">
               <el-button type="primary" @click="handleDetailSearch">查询</el-button>
               <el-button type="primary" @click="handleDetailSearch">查询</el-button>
@@ -244,19 +249,20 @@
           </el-form>
           </el-form>
           <div class="detail-table">
           <div class="detail-table">
             <el-table :data="detailTableData" height="360" style="width: 100%;">
             <el-table :data="detailTableData" height="360" style="width: 100%;">
+              <el-table-column type="index" label="序号" width="70" align="center" />
               <el-table-column prop="date" label="日期" width="120" align="center" />
               <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="account" label="会员账号" width="120" align="center" />
+              <el-table-column prop="nickname" label="会员昵称" width="120" align="center" />
               <el-table-column prop="deposit_total" label="存款总额" width="110" 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="registered_count" label="注册人数" width="110" align="center" />
               <el-table-column prop="commission" label="佣金" width="100" align="center">
               <el-table-column prop="commission" label="佣金" width="100" align="center">
                 <template slot-scope="scope">
                 <template slot-scope="scope">
                   <span>{{ scope.row.commission }}</span>
                   <span>{{ scope.row.commission }}</span>
                 </template>
                 </template>
               </el-table-column>
               </el-table-column>
-              <el-table-column prop="current_fee" label="当前手续费" min-width="120" align="center">
+              <el-table-column prop="current_fee_rate" label="当前一级比例" min-width="120" align="center">
                 <template slot-scope="scope">
                 <template slot-scope="scope">
-                  <span>{{ scope.row.current_fee }}</span>
+                  <span>{{ scope.row.current_fee_rate }}</span>
                 </template>
                 </template>
               </el-table-column>
               </el-table-column>
             </el-table>
             </el-table>
@@ -275,8 +281,8 @@
           </div>
           </div>
           <div class="promotion-description">
           <div class="promotion-description">
             <p>佣金来源:</p>
             <p>佣金来源:</p>
-            <p>被邀请人单笔下注>={{ promotionRule.highBetAmount }}元,推广人可以抽取购买单价的{{ promotionRule.highCommissionRate }}%佣金。</p>
-            <p>被邀请人单笔下注{{ promotionRule.lessThan }}{{ promotionRule.lowBetAmount }}元,推广人可以抽取购买单价的{{ promotionRule.lowCommissionRate }}%佣金。</p>
+            <p>被邀请人单笔下注{{ greaterThanOrEqualSymbol }}{{ settingsForm.non_seller_threshold }}元,推广人可以抽取购买单价的{{ settingsForm.tier_one_rate }}%佣金。</p>
+            <p>被邀请人单笔下注{{ lessThanSymbol }}{{ settingsForm.non_seller_threshold }}元,推广人可以抽取购买单价的{{ settingsForm.tier_two_rate }}%佣金。</p>
           </div>
           </div>
         </template>
         </template>
       </Dialog>
       </Dialog>
@@ -294,7 +300,7 @@
               <el-input v-model="registerDetailQuery.member_id" placeholder="请输入会员ID" clearable />
               <el-input v-model="registerDetailQuery.member_id" placeholder="请输入会员ID" clearable />
             </el-form-item>
             </el-form-item>
             <el-form-item label="会员账号">
             <el-form-item label="会员账号">
-              <el-input v-model="registerDetailQuery.member_account" placeholder="请输入会员账号" clearable />
+              <el-input v-model="registerDetailQuery.account" placeholder="请输入会员账号" clearable />
             </el-form-item>
             </el-form-item>
             <el-form-item class="detail-search-actions">
             <el-form-item class="detail-search-actions">
               <el-button type="primary" @click="handleRegisterDetailSearch">查询</el-button>
               <el-button type="primary" @click="handleRegisterDetailSearch">查询</el-button>
@@ -303,13 +309,25 @@
           </el-form>
           </el-form>
           <div class="register-detail-table">
           <div class="register-detail-table">
             <el-table :data="registerDetailTableData" height="440" style="width: 100%;">
             <el-table :data="registerDetailTableData" height="440" style="width: 100%;">
+              <el-table-column type="index" label="序号" width="70" align="center" />
               <el-table-column prop="date" label="日期" min-width="120" align="center" />
               <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="account" label="会员账号" min-width="130" align="center" />
+              <el-table-column prop="nickname" label="会员昵称" min-width="130" align="center" />
               <el-table-column prop="deposit_total" 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-column prop="bet_total" label="下注总额" min-width="130" align="center" />
+              <el-table-column prop="withdraw_total" label="提款总额" min-width="130" align="center" />
             </el-table>
             </el-table>
+            <el-pagination
+              background
+              class="detail-pagination"
+              layout="total, sizes, prev, pager, next, jumper"
+              :current-page="registerDetailPage"
+              :page-size="registerDetailLimit"
+              :page-sizes="[10, 20, 50]"
+              :total="registerDetailTotal"
+              @size-change="handleRegisterDetailSizeChange"
+              @current-change="handleRegisterDetailCurrentChange"
+            />
             <div class="detail-total">总人数:{{ registerDetailTotal }}</div>
             <div class="detail-total">总人数:{{ registerDetailTotal }}</div>
           </div>
           </div>
         </template>
         </template>
@@ -326,7 +344,7 @@
         <template slot="content">
         <template slot="content">
           <el-form :model="blockedForm" label-width="120px" class="blocked-form">
           <el-form :model="blockedForm" label-width="120px" class="blocked-form">
             <el-form-item label="禁止推广账号">
             <el-form-item label="禁止推广账号">
-              <el-input v-model="blockedForm.member_account" />
+              <el-input v-model="blockedForm.account" />
             </el-form-item>
             </el-form-item>
             <el-form-item label="不能返佣的类目">
             <el-form-item label="不能返佣的类目">
               <el-checkbox v-model="blockedForm.selectAll" @change="toggleBlockedCategories">全选</el-checkbox>
               <el-checkbox v-model="blockedForm.selectAll" @change="toggleBlockedCategories">全选</el-checkbox>
@@ -337,11 +355,11 @@
               >
               >
                 <el-checkbox
                 <el-checkbox
                   v-for="category in categoryGroup"
                   v-for="category in categoryGroup"
-                  :key="category"
+                  :key="category.value"
                   v-model="blockedForm.categories"
                   v-model="blockedForm.categories"
-                  :label="category"
+                  :label="category.value"
                   @change="syncBlockedSelectAll"
                   @change="syncBlockedSelectAll"
-                />
+                >{{ category.label }}</el-checkbox>
               </div>
               </div>
             </el-form-item>
             </el-form-item>
             <div class="blocked-dialog-actions">
             <div class="blocked-dialog-actions">
@@ -357,6 +375,18 @@
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
 import { disableFutureDate } from '@/utils/index'
 import { disableFutureDate } from '@/utils/index'
+import {
+  getShareMembers,
+  getSharePromoters,
+  getShareRegistrations,
+  getShareSummary,
+  getShareSettings,
+  saveShareSettings,
+  getShareBlacklists,
+  saveShareBlacklist,
+  setShareBlacklistStatus,
+  deleteShareBlacklist
+} from '@/api/data'
 
 
 export default {
 export default {
   name: 'ShareMoney',
   name: 'ShareMoney',
@@ -372,16 +402,18 @@ export default {
       total: 0,
       total: 0,
       summaryTotal: 0,
       summaryTotal: 0,
       blockedTotal: 0,
       blockedTotal: 0,
-      summaryCommission: '534.9',
-      summaryMaxFeeReduction: '-4%',
+      summaryCommission: 0,
+      summaryMaxFeeReduction: 0,
+      greaterThanOrEqualSymbol: '>=',
+      lessThanSymbol: '<',
       settingsForm: {
       settingsForm: {
-        share_enabled: 1,
-        share_domain: 'show888.com',
-        minimum_deposit: 20,
-        commission_enabled: 0,
+        enabled: 0,
+        share_domain: '',
+        valid_member_min_deposit: 0,
+        benefit_enabled: 0,
         non_seller_threshold: 200,
         non_seller_threshold: 200,
-        commission_tier_one: 4,
-        commission_tier_two: 6
+        tier_one_rate: 0,
+        tier_two_rate: 0
       },
       },
       viewRow: null,
       viewRow: null,
       detailPage: 1,
       detailPage: 1,
@@ -390,42 +422,28 @@ export default {
       detailTotal: 0,
       detailTotal: 0,
       detailQuery: {
       detailQuery: {
         member_id: '',
         member_id: '',
-        member_account: ''
+        account: ''
       },
       },
+      registerDetailPage: 1,
+      registerDetailLimit: 10,
       registerDetailTableData: [],
       registerDetailTableData: [],
-      registerDetailTotal: 223,
-      registerDetailAllTableData: [],
       registerDetailViewDate: '',
       registerDetailViewDate: '',
+      registerDetailTotal: 0,
       registerDetailQuery: {
       registerDetailQuery: {
         member_id: '',
         member_id: '',
-        member_account: ''
-      },
-      promotionRule: {
-        highBetAmount: 200,
-        lowBetAmount: 200,
-        highCommissionRate: 4,
-        lowCommissionRate: 6,
-        lessThan: '<'
+        account: ''
       },
       },
-      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: [],
       summaryTableData: [],
-      blockedAllTableData: [],
       blockedTableData: [],
       blockedTableData: [],
       blockedCategoryGroups: [
       blockedCategoryGroups: [
-        ['体育', '彩票', '第三方游戏']
+        [
+          { label: '体育', value: 'sports' },
+          { label: '彩票', value: 'lottery' },
+          { label: '第三方游戏', value: 'third_party_game' }
+        ]
       ],
       ],
       blockedForm: {
       blockedForm: {
-        member_account: '',
+        account: '',
         categories: [],
         categories: [],
         selectAll: false
         selectAll: false
       },
       },
@@ -434,198 +452,95 @@ export default {
       query: {
       query: {
         date_range: [],
         date_range: [],
         promoter_account: '',
         promoter_account: '',
-        blocked_account: ''
+        account: ''
       },
       },
       disableFutureDate,
       disableFutureDate,
       tableData: []
       tableData: []
     }
     }
   },
   },
   created() {
   created() {
-    this.allTableData = this.getMockRows()
-    this.detailAllTableData = this.getDetailMockData()
-    this.registerDetailAllTableData = this.getRegisterDetailMockData()
-    this.summaryAllTableData = this.getSummaryMockData()
-    this.blockedAllTableData = this.getBlockedMockData()
+    this.loadSettings()
     this.getList()
     this.getList()
   },
   },
   methods: {
   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
+    getPageResult(response) {
+      const data = response && response.data ? response.data : {}
+      return { total: Number(data.total) || 0, rows: Array.isArray(data.data) ? data.data : [] }
+    },
+    getDateParams() {
+      const [start_date, end_date] = this.query.date_range || []
+      return { start_date, end_date }
+    },
+    async getList() {
+      this.loading = true
+      try {
+        if (this.activeTab === 'members') {
+          const result = this.getPageResult(await getShareMembers({ ...this.getDateParams(), page: this.page, limit: this.limit }))
+          this.total = result.total
+          this.tableData = result.rows
+        } else if (this.activeTab === 'summary') {
+          const response = await getShareSummary({ ...this.getDateParams(), account: this.query.promoter_account, page: this.page, limit: this.limit })
+          const result = this.getPageResult(response)
+          this.summaryTotal = result.total
+          this.summaryTableData = result.rows
+          const data = response.data || {}
+          this.summaryCommission = data.summary && data.summary.total_commission != null ? data.summary.total_commission : 0
+          this.summaryMaxFeeReduction = data.summary && data.summary.highest_fee_waiver_rate != null ? data.summary.highest_fee_waiver_rate : 0
+        } else {
+          const result = this.getPageResult(await getShareBlacklists({ account: this.query.account, page: this.page, limit: this.limit }))
+          this.blockedTotal = result.total
+          this.blockedTableData = result.rows
         }
         }
-      ]
-      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
+      } finally {
+        this.loading = false
       }
       }
-      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
+    async loadSettings() {
+      this.loading = true
+      try {
+        const response = await getShareSettings()
+        this.settingsForm = { ...this.settingsForm, ...(response.data || {}) }
+      } finally {
+        this.loading = false
       }
       }
-      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() {
     onSubmit() {
       this.page = 1
       this.page = 1
       this.getList()
       this.getList()
     },
     },
     resetQuery() {
     resetQuery() {
-      this.$refs.queryForm.resetFields()
+      this.query = { date_range: [], promoter_account: '', account: '' }
       this.onSubmit()
       this.onSubmit()
     },
     },
     handleTabChange() {
     handleTabChange() {
       this.page = 1
       this.page = 1
-      this.getList()
+      if (this.activeTab === 'settings') this.loadSettings()
+      else this.getList()
     },
     },
-    handleBlockedSearch() {
-      this.page = 1
-      this.getBlockedList()
+    formatBlockedCategories(categories) {
+      const values = Array.isArray(categories) ? categories : []
+      const labels = { sports: '体育', lottery: '彩票', third_party_game: '第三方游戏' }
+      return values.map(category => labels[category] || category).join('、') || '--'
     },
     },
     handleBlockedCreate() {
     handleBlockedCreate() {
       this.resetBlockedForm()
       this.resetBlockedForm()
       this.$refs.blockedDialog.open()
       this.$refs.blockedDialog.open()
     },
     },
     resetBlockedForm() {
     resetBlockedForm() {
-      this.blockedForm = {
-        member_account: '',
-        categories: [],
-        selectAll: false
-      }
+      this.blockedForm = { account: '', categories: [], selectAll: false }
       this.blockedEditingRow = null
       this.blockedEditingRow = null
       this.blockedDialogTitle = '新增禁止推广账号'
       this.blockedDialogTitle = '新增禁止推广账号'
     },
     },
     toggleBlockedCategories(value) {
     toggleBlockedCategories(value) {
-      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
+      const categories = this.blockedCategoryGroups[0].map(category => category.value)
       this.blockedForm.categories = value ? categories : []
       this.blockedForm.categories = value ? categories : []
     },
     },
     syncBlockedSelectAll() {
     syncBlockedSelectAll() {
-      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
+      const categories = this.blockedCategoryGroups[0].map(category => category.value)
       this.blockedForm.selectAll = this.blockedForm.categories.length === categories.length
       this.blockedForm.selectAll = this.blockedForm.categories.length === categories.length
     },
     },
-    submitBlocked() {
-      if (!this.blockedForm.member_account.trim()) {
+    async submitBlocked() {
+      if (!this.blockedForm.account.trim()) {
         this.$message.warning('请输入禁止推广账号')
         this.$message.warning('请输入禁止推广账号')
         return
         return
       }
       }
@@ -633,54 +548,44 @@ export default {
         this.$message.warning('请选择不能返佣的类目')
         this.$message.warning('请选择不能返佣的类目')
         return
         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
-        })
-      }
+      const payload = this.blockedEditingRow
+        ? { id: this.blockedEditingRow.id, blocked_categories: this.blockedForm.categories, status: this.blockedEditingRow.status }
+        : { account: this.blockedForm.account.trim(), blocked_categories: this.blockedForm.categories, status: 1 }
+      await saveShareBlacklist(payload)
       this.$refs.blockedDialog.close()
       this.$refs.blockedDialog.close()
-      this.getBlockedList()
       this.resetBlockedForm()
       this.resetBlockedForm()
+      this.getList()
       this.$message.success('提交成功')
       this.$message.success('提交成功')
     },
     },
     handleBlockedEdit(row) {
     handleBlockedEdit(row) {
-      const categories = this.blockedCategoryGroups.reduce((result, group) => result.concat(group), [])
-      const selectedCategories = row.prohibited_category
-        .split('、')
-        .filter(category => categories.includes(category))
+      const categories = Array.isArray(row.blocked_categories) ? row.blocked_categories : []
       this.blockedEditingRow = row
       this.blockedEditingRow = row
       this.blockedDialogTitle = '修改禁止推广账号'
       this.blockedDialogTitle = '修改禁止推广账号'
-      this.blockedForm = {
-        member_account: row.member_account,
-        categories: selectedCategories,
-        selectAll: selectedCategories.length === categories.length
-      }
+      this.blockedForm = { account: row.account, categories: categories.slice(), selectAll: categories.length === 3 }
       this.$refs.blockedDialog.open()
       this.$refs.blockedDialog.open()
     },
     },
-    handleBlockedToggle(row, value) {
-      row.status = value ? 1 : 0
+    async handleBlockedToggle(row, value) {
+      const status = value ? 1 : 0
+      try {
+        await setShareBlacklistStatus({ id: row.id, status })
+        await this.getList()
+      } catch (error) {
+        this.$message.error('状态更新失败')
+      }
     },
     },
     handleBlockedDelete(row) {
     handleBlockedDelete(row) {
-      this.$confirm(`确定删除会员账号“${row.member_account}”吗?`, '提示', {
+      this.$confirm(`确定删除会员账号“${row.account}”吗?`, '提示', {
         confirmButtonText: '确定',
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         cancelButtonText: '取消',
         type: 'warning'
         type: 'warning'
-      }).then(() => {
-        const rowIndex = this.blockedAllTableData.indexOf(row)
-        if (rowIndex > -1) {
-          this.blockedAllTableData.splice(rowIndex, 1)
-          this.getBlockedList()
-        }
-      })
-    },
-    submitSettings() {
+      }).then(async() => {
+        await deleteShareBlacklist({ id: row.id })
+        this.getList()
+        this.$message.success('删除成功')
+      }).catch(() => {})
+    },
+    async submitSettings() {
+      await saveShareSettings({ ...this.settingsForm })
       this.$message.success('提交成功')
       this.$message.success('提交成功')
     },
     },
     handleSizeChange(value) {
     handleSizeChange(value) {
@@ -695,10 +600,7 @@ export default {
     handleView(row) {
     handleView(row) {
       this.viewRow = { ...row }
       this.viewRow = { ...row }
       this.detailPage = 1
       this.detailPage = 1
-      this.detailQuery = {
-        member_id: '',
-        member_account: ''
-      }
+      this.detailQuery = { member_id: '', account: '' }
       this.getDetailList()
       this.getDetailList()
       this.$refs.viewDialog.open()
       this.$refs.viewDialog.open()
     },
     },
@@ -709,17 +611,15 @@ export default {
     resetDetailQuery() {
     resetDetailQuery() {
       this.detailQuery = {
       this.detailQuery = {
         member_id: '',
         member_id: '',
-        member_account: ''
+        account: ''
       }
       }
       this.detailPage = 1
       this.detailPage = 1
       this.getDetailList()
       this.getDetailList()
     },
     },
     handleRegisterView(row) {
     handleRegisterView(row) {
       this.registerDetailViewDate = row.date
       this.registerDetailViewDate = row.date
-      this.registerDetailQuery = {
-        member_id: '',
-        member_account: ''
-      }
+      this.registerDetailPage = 1
+      this.registerDetailQuery = { member_id: '', account: '' }
       this.getRegisterDetailList()
       this.getRegisterDetailList()
       this.$refs.registerDialog.open()
       this.$refs.registerDialog.open()
     },
     },
@@ -729,40 +629,22 @@ export default {
     resetRegisterDetailQuery() {
     resetRegisterDetailQuery() {
       this.registerDetailQuery = {
       this.registerDetailQuery = {
         member_id: '',
         member_id: '',
-        member_account: ''
+        account: ''
       }
       }
+      this.registerDetailPage = 1
       this.getRegisterDetailList()
       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
-      }))
+    async getDetailList() {
+      const response = await getSharePromoters({ date: this.viewRow.date, page: this.detailPage, limit: this.detailLimit, member_id: this.detailQuery.member_id, account: this.detailQuery.account })
+      const result = this.getPageResult(response)
+      this.detailTotal = result.total
+      this.detailTableData = result.rows
     },
     },
-    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
-      }))
+    async getRegisterDetailList() {
+      const response = await getShareRegistrations({ date: this.registerDetailViewDate, page: this.registerDetailPage, limit: this.registerDetailLimit, member_id: this.registerDetailQuery.member_id, account: this.registerDetailQuery.account })
+      const result = this.getPageResult(response)
+      this.registerDetailTotal = result.total
+      this.registerDetailTableData = result.rows
     },
     },
     handleDetailSizeChange(value) {
     handleDetailSizeChange(value) {
       this.detailLimit = value
       this.detailLimit = value
@@ -772,6 +654,15 @@ export default {
     handleDetailCurrentChange(value) {
     handleDetailCurrentChange(value) {
       this.detailPage = value
       this.detailPage = value
       this.getDetailList()
       this.getDetailList()
+    },
+    handleRegisterDetailSizeChange(value) {
+      this.registerDetailLimit = value
+      this.registerDetailPage = 1
+      this.getRegisterDetailList()
+    },
+    handleRegisterDetailCurrentChange(value) {
+      this.registerDetailPage = value
+      this.getRegisterDetailList()
     }
     }
   }
   }
 }
 }

+ 186 - 117
src/views/operationSetting/appConfig/index.vue

@@ -20,8 +20,8 @@
       <template v-if="activeTab === 'package'">
       <template v-if="activeTab === 'package'">
         <div class="display-settings">
         <div class="display-settings">
           <div class="display-settings-title">前台显示</div>
           <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 class="display-setting-item"><span>IOS前端显示</span><el-switch v-model="displaySettings.ios_frontend_visible" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#c0c4cc" @change="saveDisplaySettings" /></div>
+          <div class="display-setting-item"><span>安卓前端显示</span><el-switch v-model="displaySettings.android_frontend_visible" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#c0c4cc" @change="saveDisplaySettings" /></div>
         </div>
         </div>
         <div class="operation-toolbar">
         <div class="operation-toolbar">
           <span class="operation-toolbar-title">安装包列表</span>
           <span class="operation-toolbar-title">安装包列表</span>
@@ -31,17 +31,17 @@
           <el-table key="package-table" v-loading="loading" :data="pagedPackageRows" height="100%" class="operation-table">
           <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 type="index" label="序号" width="70" align="center" />
             <el-table-column prop="platform" label="平台" width="90" 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="download_url" label="安装包链接" min-width="220" align="center" show-overflow-tooltip />
             <el-table-column prop="version" label="版号" width="90" align="center" />
             <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="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 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="created_at" label="创建时间" min-width="160" align="center" />
             <el-table-column prop="updated_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 prop="operator_name" 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-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>
           </el-table>
         </div>
         </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" />
+        <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="packageTotal" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
       </template>
       </template>
 
 
       <template v-else-if="activeTab === 'download'">
       <template v-else-if="activeTab === 'download'">
@@ -51,17 +51,17 @@
             <el-table-column type="index" label="序号" width="70" align="center" />
             <el-table-column type="index" label="序号" width="70" align="center" />
             <el-table-column prop="platform" label="平台" width="100" 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="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="download_url" label="App下载链接" min-width="260" align="center" show-overflow-tooltip />
             <el-table-column prop="click_count" label="点击链接次数" min-width="130" align="center" />
             <el-table-column prop="click_count" label="点击链接次数" min-width="130" align="center" />
           </el-table>
           </el-table>
           <el-table key="download-app-table" class="operation-table compact-table" :data="pagedDownloadAppRows" height="50%">
           <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 type="index" label="序号" width="70" align="center" />
             <el-table-column prop="platform" label="平台" width="100" 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="package_type" label="安装包类型" min-width="180" align="center" />
-            <el-table-column prop="download_count" label="下载且开启App次数" min-width="180" align="center" />
+            <el-table-column prop="open_count" label="下载且开启App次数" min-width="180" align="center" />
           </el-table>
           </el-table>
         </div>
         </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" />
+        <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="downloadTotal" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
       </template>
       </template>
 
 
       <template v-else>
       <template v-else>
@@ -70,28 +70,29 @@
           <el-table key="ios-table" v-loading="loading" :data="pagedIosRows" height="100%" class="operation-table">
           <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 type="index" label="序号" width="70" align="center" />
             <el-table-column prop="platform" label="平台" width="90" 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="store_version" label="上架版本" min-width="110" align="center" />
+            <el-table-column prop="operating_version" label="运营版本" min-width="110" align="center" />
+            <el-table-column prop="review_user_ids" label="提供审查用户ID" min-width="180" align="center"><template slot-scope="scope">{{ (scope.row.review_user_ids || []).join(',') }}</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="created_at" label="创建时间" min-width="160" align="center" />
             <el-table-column prop="updated_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-column prop="operator_name" 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(scope.row)">操作记录</el-button></template></el-table-column>
           </el-table>
           </el-table>
         </div>
         </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" />
+        <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="iosTotal" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
       </template>
       </template>
     </div>
     </div>
 
 
     <Dialog ref="packageDialog" :dialog-actions="packageDialogActions">
     <Dialog ref="packageDialog" :dialog-actions="packageDialogActions">
       <template slot="content">
       <template slot="content">
         <el-form :model="packageForm" label-width="110px" class="app-dialog-form">
         <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-select v-model="packageForm.platform"><el-option label="安卓" value="android" /><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.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-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-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-select v-model="packageForm.package_type"><el-option label="安卓 APK" value="android_apk" /><el-option label="TestFlight" value="testflight" /><el-option label="App Store" value="app_store" /><el-option label="企业签名" value="enterprise" /><el-option label="网页" value="web" /></el-select></el-form-item>
+          <el-form-item label="安装包链接"><el-input v-model="packageForm.download_url" placeholder="请输入安装包链接" /></el-form-item>
           <el-form-item label="更新内容"><el-input v-model="packageForm.update_content" type="textarea" :rows="4" 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>
           <div class="dialog-actions"><el-button type="primary" @click="submitPackage">提交</el-button></div>
         </el-form>
         </el-form>
@@ -102,9 +103,10 @@
       <template slot="content">
       <template slot="content">
         <el-form :model="iosForm" label-width="130px" class="app-dialog-form">
         <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.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="上架版本"><el-input v-model="iosForm.store_version" /></el-form-item>
+          <el-form-item label="运营版本"><el-input v-model="iosForm.operating_version" /></el-form-item>
           <el-form-item label="提供审查用户ID"><el-input v-model="iosForm.review_user_ids" type="textarea" :rows="3" /></el-form-item>
           <el-form-item label="提供审查用户ID"><el-input v-model="iosForm.review_user_ids" type="textarea" :rows="3" /></el-form-item>
+          <el-form-item label="状态"><el-radio-group v-model="iosForm.status"><el-radio :label="1">启用</el-radio><el-radio :label="0">停用</el-radio></el-radio-group></el-form-item>
           <div class="dialog-actions"><el-button type="primary" @click="submitIos">提交</el-button></div>
           <div class="dialog-actions"><el-button type="primary" @click="submitIos">提交</el-button></div>
         </el-form>
         </el-form>
       </template>
       </template>
@@ -126,7 +128,7 @@
           <el-table-column prop="old_value" label="旧值" min-width="110" 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-column prop="new_value" label="新值" min-width="110" align="center" />
         </el-table>
         </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" />
+        <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="operationTotal" @size-change="handleOperationSizeChange" @current-change="handleOperationCurrentChange" />
       </template>
       </template>
     </Dialog>
     </Dialog>
   </div>
   </div>
@@ -135,14 +137,20 @@
 <script>
 <script>
 import Dialog from '@/components/Dialog/index.vue'
 import Dialog from '@/components/Dialog/index.vue'
 import { disableFutureDate } from '@/utils/index'
 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
-})
+import {
+  getAppDisplaySettings,
+  saveAppDisplaySettings,
+  getAppPackages,
+  saveAppPackage,
+  setAppPackageStatus,
+  deleteAppPackage,
+  getAppDownloadStats,
+  getIosReviews,
+  saveIosReview,
+  setIosReviewStatus,
+  deleteIosReview,
+  getAppConfigLogs
+} from '@/api/data'
 
 
 export default {
 export default {
   name: 'OperationAppConfig',
   name: 'OperationAppConfig',
@@ -154,8 +162,11 @@ export default {
       activeTab: 'package',
       activeTab: 'package',
       page: 1,
       page: 1,
       limit: 10,
       limit: 10,
+      packageTotal: 0,
+      downloadTotal: 0,
+      iosTotal: 0,
       query: { date_range: [] },
       query: { date_range: [] },
-      displaySettings: { ios: false, android: false },
+      displaySettings: { ios_frontend_visible: 0, android_frontend_visible: 0 },
       packageForm: {},
       packageForm: {},
       iosForm: {},
       iosForm: {},
       packageDialogMode: 'create',
       packageDialogMode: 'create',
@@ -164,36 +175,21 @@ export default {
       iosDialogMode: 'edit',
       iosDialogMode: 'edit',
       operationPage: 1,
       operationPage: 1,
       operationLimit: 10,
       operationLimit: 10,
+      operationTotal: 0,
       operationQuery: { date_range: [], operator: '' },
       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' })
-      ]
+      operationRows: [],
+      operationResourceId: null,
+      packageRows: [],
+      downloadRows: [],
+      downloadAppRows: [],
+      iosRows: []
     }
     }
   },
   },
   computed: {
   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) },
+    pagedPackageRows() { return this.packageRows },
+    pagedDownloadRows() { return this.downloadRows },
+    pagedDownloadAppRows() { return this.downloadAppRows },
+    pagedIosRows() { return this.iosRows },
     packageDialogActions() {
     packageDialogActions() {
       return { width: '700px', title: `${this.packageDialogMode === 'edit' ? '编辑' : '创建'}安装包`, buttom: false, confirmButtom: false }
       return { width: '700px', title: `${this.packageDialogMode === 'edit' ? '编辑' : '创建'}安装包`, buttom: false, confirmButtom: false }
     },
     },
@@ -202,51 +198,111 @@ export default {
     },
     },
     filteredOperationRows() {
     filteredOperationRows() {
       const operator = (this.operationQuery.operator || '').trim().toLowerCase()
       const operator = (this.operationQuery.operator || '').trim().toLowerCase()
-      return this.operationRows.filter(row => !operator || row.operator.toLowerCase().includes(operator))
+      return this.operationRows.filter(row => !operator || String(row.operator || '').toLowerCase().includes(operator))
     },
     },
-    pagedOperationRows() {
-      const start = (this.operationPage - 1) * this.operationLimit
-      return this.filteredOperationRows.slice(start, start + this.operationLimit)
-    }
+    pagedOperationRows() { return this.filteredOperationRows }
   },
   },
-  mounted() {
+  created() {
     this.packageForm = this.getPackageForm()
     this.packageForm = this.getPackageForm()
     this.iosForm = this.getIosForm()
     this.iosForm = this.getIosForm()
+    this.loadCurrentTab()
   },
   },
   methods: {
   methods: {
-    getPagedRows(rows) {
-      const start = (this.page - 1) * this.limit
-      return rows.slice(start, start + this.limit)
+    getPageResult(response) {
+      const data = response && response.data ? response.data : {}
+      return { total: Number(data.total) || 0, rows: Array.isArray(data.data) ? data.data : [] }
     },
     },
-    getPackageForm(row = {}) {
-      return { platform: '安卓', version: '', package_name: '', force_update: false, package_type: '安卓Apk', package_link: '', update_content: '', ...row }
+    getDateParams() {
+      const [start_date, end_date] = this.query.date_range || []
+      return { start_date, end_date }
     },
     },
-    getIosForm(row = {}) {
-      return { platform: 'ios', publish_version: '', operation_version: '', review_user_ids: '', ...row }
+    async loadCurrentTab() {
+      if (this.activeTab === 'package') {
+        await Promise.all([this.loadDisplaySettings(), this.loadPackages()])
+      } else if (this.activeTab === 'download') {
+        await this.loadDownloads()
+      } else {
+        await this.loadIosReviews()
+      }
+    },
+    async loadDisplaySettings() {
+      const response = await getAppDisplaySettings()
+      this.displaySettings = { ...this.displaySettings, ...(response.data || {}) }
+    },
+    async loadPackages() {
+      this.loading = true
+      try {
+        const response = await getAppPackages({ page: this.page, limit: this.limit })
+        const result = this.getPageResult(response)
+        this.packageRows = result.rows
+        this.packageTotal = result.total
+      } finally {
+        this.loading = false
+      }
+    },
+    async loadDownloads() {
+      this.loading = true
+      try {
+        const response = await getAppDownloadStats({ ...this.getDateParams(), page: this.page, limit: this.limit })
+        const data = response.data || {}
+        this.downloadRows = data.clicks && Array.isArray(data.clicks.data) ? data.clicks.data : []
+        this.downloadAppRows = data.opens && Array.isArray(data.opens.data) ? data.opens.data : []
+        this.downloadTotal = Math.max(Number(data.clicks && data.clicks.total) || 0, Number(data.opens && data.opens.total) || 0)
+      } finally {
+        this.loading = false
+      }
+    },
+    async loadIosReviews() {
+      this.loading = true
+      try {
+        const response = await getIosReviews({ ...this.getDateParams(), page: this.page, limit: this.limit })
+        const result = this.getPageResult(response)
+        this.iosRows = result.rows
+        this.iosTotal = result.total
+      } finally {
+        this.loading = false
+      }
     },
     },
     handleSearch() {
     handleSearch() {
       this.page = 1
       this.page = 1
+      this.loadCurrentTab()
     },
     },
     resetQuery() {
     resetQuery() {
       this.query = { date_range: [] }
       this.query = { date_range: [] }
-      this.page = 1
+      this.handleSearch()
     },
     },
     handleTabChange() {
     handleTabChange() {
       this.query = { date_range: [] }
       this.query = { date_range: [] }
       this.page = 1
       this.page = 1
+      this.loadCurrentTab()
     },
     },
     handleSizeChange(value) {
     handleSizeChange(value) {
       this.limit = value
       this.limit = value
       this.page = 1
       this.page = 1
+      this.loadCurrentTab()
     },
     },
     handleCurrentChange(value) {
     handleCurrentChange(value) {
       this.page = value
       this.page = value
+      this.loadCurrentTab()
     },
     },
-    saveDisplaySettings() {
+    async saveDisplaySettings() {
+      await saveAppDisplaySettings(this.displaySettings)
       this.$message.success('设置已更新')
       this.$message.success('设置已更新')
     },
     },
-    toggleStatus(row) {
-      row.status = row.status === 1 ? 0 : 1
+    async toggleStatus(row) {
+      const status = row.status === 1 ? 0 : 1
+      const payload = { id: row.id, status }
+      if (this.activeTab === 'package') await setAppPackageStatus(payload)
+      else await setIosReviewStatus(payload)
+      if (this.activeTab === 'package') await this.loadPackages()
+      else await this.loadIosReviews()
+    },
+    getPackageForm(row = {}) {
+      return { platform: 'android', version: '', package_name: '', force_update: 0, package_type: 'android_apk', download_url: '', update_content: '', status: 1, ...row }
+    },
+    getIosForm(row = {}) {
+      const reviewUserIds = Array.isArray(row.review_user_ids) ? row.review_user_ids.join(',') : (row.review_user_ids || '')
+      return { platform: 'ios', store_version: '', operating_version: '', status: 1, ...row, review_user_ids: reviewUserIds }
     },
     },
     handleCreatePackage() {
     handleCreatePackage() {
       this.packageDialogMode = 'create'
       this.packageDialogMode = 'create'
@@ -260,20 +316,28 @@ export default {
       this.packageForm = this.getPackageForm(row)
       this.packageForm = this.getPackageForm(row)
       this.$refs.packageDialog.open()
       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 }))
+    async submitPackage() {
+      const payload = {
+        platform: this.packageForm.platform,
+        version: this.packageForm.version,
+        package_name: this.packageForm.package_name,
+        force_update: this.packageForm.force_update ? 1 : 0,
+        package_type: this.packageForm.package_type,
+        download_url: this.packageForm.download_url,
+        update_content: this.packageForm.update_content,
+        status: this.packageForm.status
       }
       }
+      if (this.packageForm.id) payload.id = this.packageForm.id
+      await saveAppPackage(payload)
       this.$refs.packageDialog.close()
       this.$refs.packageDialog.close()
+      this.page = 1
+      await this.loadPackages()
       this.$message.success('提交成功')
       this.$message.success('提交成功')
     },
     },
     handleDeletePackage(row) {
     handleDeletePackage(row) {
-      this.$confirm('确定删除这个安装包吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
-        const index = this.packageRows.indexOf(row)
-        if (index !== -1) this.packageRows.splice(index, 1)
+      this.$confirm('确定删除这个安装包吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(async() => {
+        await deleteAppPackage({ id: row.id })
+        await this.loadPackages()
         this.$message.success('删除成功')
         this.$message.success('删除成功')
       }).catch(() => {})
       }).catch(() => {})
     },
     },
@@ -289,67 +353,72 @@ export default {
       this.iosForm = this.getIosForm()
       this.iosForm = this.getIosForm()
       this.$refs.iosDialog.open()
       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)
+    async submitIos() {
+      const payload = {
+        store_version: this.iosForm.store_version,
+        operating_version: this.iosForm.operating_version,
+        review_user_ids: String(this.iosForm.review_user_ids || '').split(/[\s,,]+/).filter(Boolean),
+        status: this.iosForm.status
       }
       }
+      if (this.iosForm.id) payload.id = this.iosForm.id
+      await saveIosReview(payload)
       this.$refs.iosDialog.close()
       this.$refs.iosDialog.close()
+      this.page = 1
+      await this.loadIosReviews()
       this.$message.success('提交成功')
       this.$message.success('提交成功')
     },
     },
     handleDeleteIos(row) {
     handleDeleteIos(row) {
-      this.$confirm('确定删除这条上架配置吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
-        const index = this.iosRows.indexOf(row)
-        if (index !== -1) this.iosRows.splice(index, 1)
+      this.$confirm('确定删除这条上架配置吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(async() => {
+        await deleteIosReview({ id: row.id })
+        await this.loadIosReviews()
         this.$message.success('删除成功')
         this.$message.success('删除成功')
       }).catch(() => {})
       }).catch(() => {})
     },
     },
-    handleIosOperationRecord() {
+    async handleIosOperationRecord(row) {
       this.operationPage = 1
       this.operationPage = 1
       this.operationQuery = { date_range: [], operator: '' }
       this.operationQuery = { date_range: [], operator: '' }
+      this.operationResourceId = row.id
+      await this.loadOperationRecords()
       this.$refs.iosOperationDialog.open()
       this.$refs.iosOperationDialog.open()
     },
     },
+    async loadOperationRecords() {
+      const [start_date, end_date] = this.operationQuery.date_range || []
+      const response = await getAppConfigLogs({ resource_type: 'app_ios_review_setting', resource_id: this.operationResourceId, start_date, end_date, operator_name: this.operationQuery.operator, page: this.operationPage, limit: this.operationLimit })
+      const data = response.data || {}
+      this.operationTotal = Number(data.total) || 0
+      this.operationRows = this.normalizeOperationRows(Array.isArray(data.data) ? data.data : [])
+    },
+    normalizeOperationRows(rows) {
+      const actionLabels = { create: '新增', update: '更新', status: '更新', delete: '删除' }
+      return rows.reduce((result, row) => {
+        if (row.attribute != null) {
+          result.push({ ...row, date: row.date || row.created_at, operator: row.operator || row.operator_name, item: actionLabels[row.action] || row.item })
+          return result
+        }
+        const before = row.changes && row.changes.before ? row.changes.before : {}
+        const after = row.changes && row.changes.after ? row.changes.after : {}
+        const keys = Array.from(new Set(Object.keys(before).concat(Object.keys(after))))
+        keys.forEach(key => result.push({ date: row.date || row.created_at, operator: row.operator || row.operator_name, item: actionLabels[row.action] || row.action, attribute: key, old_value: before[key], new_value: after[key] }))
+        return result
+      }, [])
+    },
     searchOperationRecords() {
     searchOperationRecords() {
       this.operationPage = 1
       this.operationPage = 1
+      this.loadOperationRecords()
     },
     },
     resetOperationQuery() {
     resetOperationQuery() {
       this.operationQuery = { date_range: [], operator: '' }
       this.operationQuery = { date_range: [], operator: '' }
       this.operationPage = 1
       this.operationPage = 1
+      this.loadOperationRecords()
     },
     },
     handleOperationSizeChange(value) {
     handleOperationSizeChange(value) {
       this.operationLimit = value
       this.operationLimit = value
       this.operationPage = 1
       this.operationPage = 1
+      this.loadOperationRecords()
     },
     },
     handleOperationCurrentChange(value) {
     handleOperationCurrentChange(value) {
       this.operationPage = 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)
+      this.loadOperationRecords()
     }
     }
   }
   }
 }
 }

Разница между файлами не показана из-за своего большого размера
+ 39 - 146
src/views/operationSetting/paymentConfig/index.vue


+ 464 - 73
src/views/wallet/topUpChannel/index.vue

@@ -3,36 +3,59 @@
     <el-tabs v-model="activeTab" type="border-card" @tab-click="handleTabClick">
     <el-tabs v-model="activeTab" type="border-card" @tab-click="handleTabClick">
 
 
       <el-tab-pane label="通道管理" name="channels">
       <el-tab-pane label="通道管理" name="channels">
-        <el-tabs v-model="channelQuery.data_type" style="margin-bottom: 15px;" @tab-click="getChannels">
+        <el-tabs v-model="channelQuery.data_type" style="margin-bottom: 15px;" @tab-click="handleChannelTabClick">
           <el-tab-pane label="充值" name="1"></el-tab-pane>
           <el-tab-pane label="充值" name="1"></el-tab-pane>
           <el-tab-pane label="提现" name="2"></el-tab-pane>
           <el-tab-pane label="提现" name="2"></el-tab-pane>
           <el-tab-pane label="活动" name="3"></el-tab-pane>
           <el-tab-pane label="活动" name="3"></el-tab-pane>
         </el-tabs>
         </el-tabs>
 
 
-        <el-form :inline="true" :model="channelQuery" class="filter-form">
+        <el-form :inline="true" :model="channelQuery" class="filter-form" @submit.native.prevent="getChannels">
           <el-form-item label="名称">
           <el-form-item label="名称">
             <el-input v-model="channelQuery.name" clearable placeholder="通道名称"></el-input>
             <el-input v-model="channelQuery.name" clearable placeholder="通道名称"></el-input>
           </el-form-item>
           </el-form-item>
           <el-form-item label="标识(Key)">
           <el-form-item label="标识(Key)">
             <el-input v-model="channelQuery.key" clearable placeholder="如: USDT"></el-input>
             <el-input v-model="channelQuery.key" clearable placeholder="如: USDT"></el-input>
           </el-form-item>
           </el-form-item>
+          <el-form-item v-if="channelQuery.data_type === '1' || channelQuery.data_type === '2'" label="支付公司">
+            <el-select v-model="channelQuery.payment_company" clearable placeholder="请选择支付公司">
+              <el-option v-for="item in channelPaymentCompanies" :key="optionValue(item)" :label="optionLabel(item)" :value="optionValue(item)"></el-option>
+            </el-select>
+          </el-form-item>
           <el-form-item>
           <el-form-item>
             <el-button icon="el-icon-search" type="primary" @click="getChannels">查询</el-button>
             <el-button icon="el-icon-search" type="primary" @click="getChannels">查询</el-button>
+            <el-button @click="resetChannelQuery">重置</el-button>
           </el-form-item>
           </el-form-item>
         </el-form>
         </el-form>
 
 
-        <el-table v-loading="channelLoading" :data="channelList" border
-                  height="calc(100vh - 310px)"
-                  style="width: 100%"
+        <div class="action-bar" style="margin-bottom: 20px;">
+          <el-button icon="el-icon-plus" type="success" @click="openChannelDialog()">新增通道</el-button>
+        </div>
+
+        <el-table
+          v-loading="channelLoading"
+          :data="channelList"
+          border
+          height="calc(100vh - 390px)"
+          style="width: 100%"
         >
         >
+          <el-table-column :index="channelIndex" type="index" label="序号" width="70" align="center"></el-table-column>
           <el-table-column align="center" label="ID" prop="id" width="60"></el-table-column>
           <el-table-column align="center" label="ID" prop="id" width="60"></el-table-column>
+          <template v-if="channelQuery.data_type === '1' || channelQuery.data_type === '2'">
+            <el-table-column label="支付公司编码" min-width="120" prop="payment_company" align="center"></el-table-column>
+            <el-table-column label="支付公司" min-width="120" prop="payment_company_label" align="center"></el-table-column>
+          </template>
           <el-table-column label="名称" min-width="120" prop="name"></el-table-column>
           <el-table-column label="名称" min-width="120" prop="name"></el-table-column>
           <el-table-column label="标识(Key)" prop="key" width="120"></el-table-column>
           <el-table-column label="标识(Key)" prop="key" width="120"></el-table-column>
           <el-table-column label="类型" prop="type" width="100"></el-table-column>
           <el-table-column label="类型" prop="type" width="100"></el-table-column>
-          <el-table-column label="费率" prop="rate" width="100"></el-table-column>
+          <el-table-column label="费率" width="100">
+            <template slot-scope="scope">{{ formatRate(scope.row.rate) }}</template>
+          </el-table-column>
+          <el-table-column label="固定金额" width="100">
+            <template slot-scope="scope">{{ displayValue(scope.row.fixed_amount != null ? scope.row.fixed_amount : scope.row.fixed) }}</template>
+          </el-table-column>
           <el-table-column align="center" label="限额(最小/最大)" min-width="150">
           <el-table-column align="center" label="限额(最小/最大)" min-width="150">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              {{ scope.row.min || '0' }} / {{ scope.row.max || '无' }}
+              {{ displayValue(scope.row.min, '0') }} / {{ displayValue(scope.row.max, '无') }}
             </template>
             </template>
           </el-table-column>
           </el-table-column>
           <el-table-column align="center" label="排序" prop="sort" width="80"></el-table-column>
           <el-table-column align="center" label="排序" prop="sort" width="80"></el-table-column>
@@ -43,102 +66,184 @@
               </el-tag>
               </el-tag>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
-          <el-table-column align="center" fixed="right" label="操作" width="100">
+          <el-table-column align="center" fixed="right" label="操作" width="150">
             <template slot-scope="scope">
             <template slot-scope="scope">
               <el-button size="mini" type="primary" @click="openChannelDialog(scope.row)">编辑</el-button>
               <el-button size="mini" type="primary" @click="openChannelDialog(scope.row)">编辑</el-button>
+              <el-button v-if="channelQuery.data_type === '1' || channelQuery.data_type === '2'" size="mini" type="danger" @click="removeChannel(scope.row)">删除</el-button>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
         </el-table>
         </el-table>
+        <el-pagination
+          background
+          class="channel-pagination"
+          layout="total, sizes, prev, pager, next, jumper"
+          :current-page="channelQuery.page"
+          :page-size="channelQuery.limit"
+          :page-sizes="pageSizes"
+          :total="channelTotal"
+          @size-change="handleChannelSizeChange"
+          @current-change="handleChannelPageChange"
+        />
       </el-tab-pane>
       </el-tab-pane>
 
 
       <el-tab-pane label="层级设置" name="groups">
       <el-tab-pane label="层级设置" name="groups">
         <div class="action-bar" style="margin-bottom: 20px;">
         <div class="action-bar" style="margin-bottom: 20px;">
-          <el-button icon="el-icon-plus" type="success" @click="openGroupDialog()">新增组合</el-button>
+          <el-button icon="el-icon-plus" type="success" @click="openGroupDialog()">新增层级</el-button>
         </div>
         </div>
 
 
-        <el-table v-loading="groupLoading" :data="groupList" border
-                  height="calc(100vh - 220px)"
-                  style="width: 100%"
+        <el-table
+          v-loading="groupLoading"
+          :data="groupList"
+          border
+          height="calc(100vh - 270px)"
+          style="width: 100%"
         >
         >
-          <el-table-column align="center" label="组合ID" prop="id" width="80"></el-table-column>
-          <el-table-column label="组合名称" min-width="150" prop="name"></el-table-column>
+          <el-table-column type="index" label="序号" width="70" align="center"></el-table-column>
+          <el-table-column align="center" label="层级ID" prop="id" width="80"></el-table-column>
+          <el-table-column label="层级名称" min-width="150" prop="name"></el-table-column>
 
 
           <el-table-column label="充值配置" min-width="200">
           <el-table-column label="充值配置" min-width="200">
             <template slot-scope="scope">
             <template slot-scope="scope">
               <el-tag
               <el-tag
-                v-for="channel in scope.row.rechargeTypes"
-                :key="channel.id"
+                v-for="channel in groupChannels(scope.row, 'recharge')"
+                :key="channel.type || channel.id"
                 size="mini"
                 size="mini"
                 style="margin-right: 5px; margin-bottom: 5px;"
                 style="margin-right: 5px; margin-bottom: 5px;"
               >
               >
-                {{ channel.name }}
+                {{ channel.display_name || channel.name }}
               </el-tag>
               </el-tag>
-              <span v-if="!scope.row.rechargeTypes || scope.row.rechargeTypes.length === 0">-</span>
+              <span v-if="groupChannels(scope.row, 'recharge').length === 0">-</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
 
 
           <el-table-column label="提现配置" min-width="200">
           <el-table-column label="提现配置" min-width="200">
             <template slot-scope="scope">
             <template slot-scope="scope">
               <el-tag
               <el-tag
-                v-for="channel in scope.row.withdrawTypes"
-                :key="channel.id"
+                v-for="channel in groupChannels(scope.row, 'withdraw')"
+                :key="channel.type || channel.id"
                 size="mini"
                 size="mini"
                 style="margin-right: 5px; margin-bottom: 5px;"
                 style="margin-right: 5px; margin-bottom: 5px;"
               >
               >
-                {{ channel.name }}
+                {{ channel.display_name || channel.name }}
               </el-tag>
               </el-tag>
-              <span v-if="!scope.row.withdrawTypes || scope.row.withdrawTypes.length === 0">-</span>
+              <span v-if="groupChannels(scope.row, 'withdraw').length === 0">-</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
 
 
           <el-table-column label="活动配置" min-width="200">
           <el-table-column label="活动配置" min-width="200">
             <template slot-scope="scope">
             <template slot-scope="scope">
               <el-tag
               <el-tag
-                v-for="channel in scope.row.activityTypes"
-                :key="channel.id"
+                v-for="channel in groupChannels(scope.row, 'activity')"
+                :key="channel.type || channel.id"
                 size="mini"
                 size="mini"
                 style="margin-right: 5px; margin-bottom: 5px;"
                 style="margin-right: 5px; margin-bottom: 5px;"
               >
               >
-                {{ channel.name }}
+                {{ channel.display_name || channel.name }}
               </el-tag>
               </el-tag>
-              <span v-if="!scope.row.activityTypes || scope.row.activityTypes.length === 0">-</span>
+              <span v-if="groupChannels(scope.row, 'activity').length === 0">-</span>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
 
 
           <el-table-column align="center" fixed="right" label="操作" width="100">
           <el-table-column align="center" fixed="right" label="操作" width="100">
             <template slot-scope="scope">
             <template slot-scope="scope">
-              <el-button size="mini" type="primary" @click="openGroupDialog(scope.row)">编辑</el-button>
+              <div class="group-actions">
+                <el-button size="mini" type="primary" @click="openGroupDialog(scope.row)">编辑</el-button>
+                <el-button size="mini" type="danger" :loading="groupDeletingId === scope.row.id" :disabled="groupDeletingId !== null" @click="removeGroup(scope.row)">删除</el-button>
+              </div>
             </template>
             </template>
           </el-table-column>
           </el-table-column>
         </el-table>
         </el-table>
       </el-tab-pane>
       </el-tab-pane>
-    </el-tabs>
 
 
-    <el-dialog :title="channelForm.id ? '编辑通道状态' : '新增通道'" :visible.sync="channelDialogVisible" width="550px">
-      <el-form :model="channelForm" label-width="100px" size="small">
-        <template v-if="!channelForm.id">
-          <el-form-item label="通道名称">
-            <el-input v-model="channelForm.name"></el-input>
+      <el-tab-pane label="支付公司管理" name="companies">
+        <el-form :inline="true" :model="companyQuery" class="filter-form" @submit.native.prevent="getCompanies">
+          <el-form-item label="公司代码">
+            <el-input v-model="companyQuery.payment_company" clearable placeholder="请输入公司代码"></el-input>
           </el-form-item>
           </el-form-item>
-          <el-form-item label="标识(Key)">
-            <el-input v-model="channelForm.key"></el-input>
+          <el-form-item label="状态">
+            <el-select v-model="companyQuery.status" clearable placeholder="请选择状态">
+              <el-option label="启用" :value="1"></el-option>
+              <el-option label="禁用" :value="0"></el-option>
+            </el-select>
           </el-form-item>
           </el-form-item>
-          <el-form-item label="类型(Type)">
-            <el-input v-model="channelForm.type"></el-input>
+          <el-form-item>
+            <el-button icon="el-icon-search" type="primary" @click="getCompanies">查询</el-button>
+            <el-button @click="resetCompanyQuery">重置</el-button>
           </el-form-item>
           </el-form-item>
-          <el-row>
-            <el-col :span="12">
-              <el-form-item label="费率">
-                <el-input v-model="channelForm.rate"></el-input>
-              </el-form-item>
-            </el-col>
-            <el-col :span="12">
-              <el-form-item label="排序">
-                <el-input-number v-model="channelForm.sort" style="width: 100%"></el-input-number>
-              </el-form-item>
-            </el-col>
-          </el-row>
-        </template>
+        </el-form>
+        <el-table v-loading="companyLoading" :data="companyList" border height="calc(100vh - 350px)" style="width: 100%">
+          <el-table-column type="index" label="序号" width="70" align="center"></el-table-column>
+          <el-table-column prop="payment_company" label="公司代码" min-width="120" align="center"></el-table-column>
+          <el-table-column prop="payment_company_label" label="支付公司" min-width="120" align="center"></el-table-column>
+          <el-table-column label="支持方向" min-width="120" align="center">
+            <template slot-scope="scope">{{ companyDataTypes(scope.row) }}</template>
+          </el-table-column>
+          <el-table-column prop="signature_algorithm" label="签名算法" min-width="120" align="center"></el-table-column>
+          <el-table-column prop="channel_count" label="通道数" width="90" align="center"></el-table-column>
+          <el-table-column prop="enabled_channel_count" label="启用通道数" width="110" align="center"></el-table-column>
+          <el-table-column label="状态" width="100" align="center">
+            <template slot-scope="scope">
+              <el-switch :value="scope.row.status === 1" @change="toggleCompanyStatus(scope.row)"></el-switch>
+            </template>
+          </el-table-column>
+        </el-table>
+        <el-pagination background class="channel-pagination" layout="total, sizes, prev, pager, next, jumper" :current-page="companyQuery.page" :page-size="companyQuery.limit" :page-sizes="pageSizes" :total="companyTotal" @size-change="handleCompanySizeChange" @current-change="handleCompanyPageChange"></el-pagination>
+      </el-tab-pane>
+    </el-tabs>
+
+    <el-dialog :title="channelForm.id ? '编辑通道' : '新增通道'" :visible.sync="channelDialogVisible" width="550px">
+      <el-form v-loading="channelOptionsLoading" :model="channelForm" label-width="100px" size="small">
+        <el-form-item label="通道来源">
+          <el-select v-model="channelForm.from" :disabled="!channelIdentityEditable" placeholder="请选择通道来源" @change="handleChannelFromChange">
+            <el-option v-for="item in channelOptions.from_options" :key="optionValue(item)" :label="optionLabel(item)" :value="optionValue(item)"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="(channelForm.data_type === '1' || channelForm.data_type === '2') && channelOptions.payment_companies.length" label="支付公司">
+          <el-select v-model="channelForm.payment_company" :disabled="!channelIdentityEditable" clearable placeholder="请选择支付公司" @change="handleChannelCompanyChange">
+            <el-option v-for="item in channelOptions.payment_companies" :key="optionValue(item)" :label="optionLabel(item)" :value="optionValue(item)"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="channelOptions.identity_edit_reason && !channelIdentityEditable" label="提示">
+          <span>{{ channelOptions.identity_edit_reason }}</span>
+        </el-form-item>
+        <el-form-item label="通道名称">
+          <el-input v-model="channelForm.name"></el-input>
+        </el-form-item>
+        <el-form-item label="标识(Key)">
+          <el-input v-model="channelForm.key"></el-input>
+        </el-form-item>
+        <el-form-item label="类型(Type)">
+          <el-select v-model="channelForm.type" :disabled="!channelIdentityEditable" placeholder="请选择类型" @change="handleChannelTypeChange">
+            <el-option v-for="item in filteredChannelTypes" :key="optionValue(item)" :label="optionLabel(item)" :value="optionValue(item)" :disabled="item.disabled"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="费率">
+              <el-input v-model="channelForm.rate" placeholder="如 0.03"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="排序">
+              <el-input-number v-model="channelForm.sort" style="width: 100%"></el-input-number>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="最小限额">
+              <el-input v-model="channelForm.min"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="最大限额">
+              <el-input v-model="channelForm.max"></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="固定金额">
+          <el-input v-model="channelForm.fixed_amount"></el-input>
+        </el-form-item>
 
 
         <el-form-item label="通道状态">
         <el-form-item label="通道状态">
           <el-radio-group v-model="channelForm.status">
           <el-radio-group v-model="channelForm.status">
@@ -153,14 +258,21 @@
       </div>
       </div>
     </el-dialog>
     </el-dialog>
 
 
-    <el-dialog :title="groupForm.id ? '编辑组合' : '新增组合'" :visible.sync="groupDialogVisible" width="650px">
+    <el-dialog :title="groupForm.id ? '编辑层级' : '新增层级'" :visible.sync="groupDialogVisible" width="650px">
       <el-form :model="groupForm" label-width="80px" size="small">
       <el-form :model="groupForm" label-width="80px" size="small">
-        <el-form-item label="组合名称">
-          <el-input v-model="groupForm.name" placeholder="请输入组合名称"></el-input>
+        <el-form-item label="层级名称">
+          <el-input v-model="groupForm.name" placeholder="请输入层级名称"></el-input>
         </el-form-item>
         </el-form-item>
 
 
         <el-form-item label="充值通道">
         <el-form-item label="充值通道">
           <div class="channel-selector-card">
           <div class="channel-selector-card">
+            <div class="selection-actions">
+              <el-checkbox
+                :value="isGroupAllSelected('recharge_type', rechargeChannelPool)"
+                :indeterminate="isGroupIndeterminate('recharge_type', rechargeChannelPool)"
+                @change="toggleAllGroupChannels('recharge_type', rechargeChannelPool, $event)"
+              >全选</el-checkbox>
+            </div>
             <el-checkbox-group v-model="groupForm.recharge_type">
             <el-checkbox-group v-model="groupForm.recharge_type">
               <el-checkbox
               <el-checkbox
                 v-for="(item, index) in rechargeChannelPool"
                 v-for="(item, index) in rechargeChannelPool"
@@ -169,7 +281,7 @@
                 border
                 border
                 class="channel-checkbox-item"
                 class="channel-checkbox-item"
               >
               >
-                {{ item.name }}
+                {{ item.display_name || item.name }}
               </el-checkbox>
               </el-checkbox>
             </el-checkbox-group>
             </el-checkbox-group>
           </div>
           </div>
@@ -177,6 +289,13 @@
 
 
         <el-form-item label="提现通道">
         <el-form-item label="提现通道">
           <div class="channel-selector-card">
           <div class="channel-selector-card">
+            <div class="selection-actions">
+              <el-checkbox
+                :value="isGroupAllSelected('withdraw_type', withdrawChannelPool)"
+                :indeterminate="isGroupIndeterminate('withdraw_type', withdrawChannelPool)"
+                @change="toggleAllGroupChannels('withdraw_type', withdrawChannelPool, $event)"
+              >全选</el-checkbox>
+            </div>
             <el-checkbox-group v-model="groupForm.withdraw_type">
             <el-checkbox-group v-model="groupForm.withdraw_type">
               <el-checkbox
               <el-checkbox
                 v-for="(item, index) in withdrawChannelPool"
                 v-for="(item, index) in withdrawChannelPool"
@@ -185,7 +304,7 @@
                 border
                 border
                 class="channel-checkbox-item"
                 class="channel-checkbox-item"
               >
               >
-                {{ item.name }}
+                {{ item.display_name || item.name }}
               </el-checkbox>
               </el-checkbox>
             </el-checkbox-group>
             </el-checkbox-group>
           </div>
           </div>
@@ -193,6 +312,13 @@
 
 
         <el-form-item label="活动通道">
         <el-form-item label="活动通道">
           <div class="channel-selector-card">
           <div class="channel-selector-card">
+            <div class="selection-actions">
+              <el-checkbox
+                :value="isGroupAllSelected('activity_type', activityChannelPool)"
+                :indeterminate="isGroupIndeterminate('activity_type', activityChannelPool)"
+                @change="toggleAllGroupChannels('activity_type', activityChannelPool, $event)"
+              >全选</el-checkbox>
+            </div>
             <el-checkbox-group v-model="groupForm.activity_type">
             <el-checkbox-group v-model="groupForm.activity_type">
               <el-checkbox
               <el-checkbox
                 v-for="(item, index) in activityChannelPool"
                 v-for="(item, index) in activityChannelPool"
@@ -201,7 +327,7 @@
                 border
                 border
                 class="channel-checkbox-item"
                 class="channel-checkbox-item"
               >
               >
-                {{ item.name }}
+                {{ item.display_name || item.name }}
               </el-checkbox>
               </el-checkbox>
             </el-checkbox-group>
             </el-checkbox-group>
           </div>
           </div>
@@ -221,9 +347,14 @@
 import {
 import {
   getRechargeChannelList,
   getRechargeChannelList,
   updateRechargeChannel,
   updateRechargeChannel,
+  getRechargeChannelOptions,
+  deleteRechargeChannel,
   getRechargeChannelGroupList,
   getRechargeChannelGroupList,
   updateRechargeChannelGroup,
   updateRechargeChannelGroup,
-  getRechargeChannelGetChannel
+  deleteRechargeChannelGroup,
+  getRechargeChannelGetChannel,
+  getPaymentCompanyList,
+  setPaymentCompanyStatus
 } from '@/api/data'
 } from '@/api/data'
 
 
 export default {
 export default {
@@ -234,15 +365,26 @@ export default {
       // 通道列表
       // 通道列表
       channelLoading: false,
       channelLoading: false,
       channelList: [],
       channelList: [],
-      channelQuery: { key: '', name: '', data_type: '1' },
+      channelQuery: { key: '', name: '', payment_company: '', data_type: '1', page: 1, limit: 10 },
+      pageSizes: [10, 20, 50, 100],
+      channelTotal: 0,
       // 通道表单
       // 通道表单
       channelDialogVisible: false,
       channelDialogVisible: false,
-      channelForm: { id: null, status: 1, name: '', key: '', type: '', rate: '', sort: 0 },
+      channelOptionsLoading: false,
+      channelOptions: { from_options: [], payment_companies: [], types: [], identity_editable: true, identity_edit_reason: '' },
+      channelForm: { id: null, data_type: '1', from: '', payment_company: '', payment_company_label: '', status: 1, name: '', key: '', type: '', rate: '', min: '', max: '', fixed_amount: '', sort: 0 },
+
+      // 支付公司列表
+      companyLoading: false,
+      companyList: [],
+      companyQuery: { page: 1, limit: 10, payment_company: '', status: '' },
+      companyTotal: 0,
 
 
       // 组合列表
       // 组合列表
       groupLoading: false,
       groupLoading: false,
       groupList: [],
       groupList: [],
       groupQuery: {},
       groupQuery: {},
+      groupDeletingId: null,
       // 组合表单
       // 组合表单
       groupDialogVisible: false,
       groupDialogVisible: false,
       groupForm: { id: null, name: '', recharge_type: [], withdraw_type: [], activity_type: [] },
       groupForm: { id: null, name: '', recharge_type: [], withdraw_type: [], activity_type: [] },
@@ -256,6 +398,21 @@ export default {
   created() {
   created() {
     this.getChannels()
     this.getChannels()
   },
   },
+  computed: {
+    channelPaymentCompanies() {
+      return this.companyList.map(item => ({ value: item.payment_company, label: item.payment_company_label }))
+    },
+    channelIdentityEditable() {
+      return this.channelOptions.identity_editable !== false
+    },
+    filteredChannelTypes() {
+      return this.channelOptions.types.filter(item => {
+        const fromMatch = item.from == null || this.channelForm.from === '' || String(item.from) === String(this.channelForm.from)
+        const companyMatch = item.payment_company == null || item.payment_company === '' || String(item.payment_company) === String(this.channelForm.payment_company)
+        return fromMatch && companyMatch
+      })
+    }
+  },
   methods: {
   methods: {
     handleTabClick(tab) {
     handleTabClick(tab) {
       if (tab.name === 'channels') this.getChannels()
       if (tab.name === 'channels') this.getChannels()
@@ -263,37 +420,152 @@ export default {
         this.getGroups()
         this.getGroups()
         this.loadChannelPool()
         this.loadChannelPool()
       }
       }
+      if (tab.name === 'companies') this.getCompanies()
     },
     },
     // --- 通道管理逻辑 ---
     // --- 通道管理逻辑 ---
+    resetChannelQuery() {
+      this.channelQuery = { key: '', name: '', payment_company: '', data_type: this.channelQuery.data_type, page: 1, limit: this.channelQuery.limit }
+      this.getChannels()
+    },
+    optionValue(item) {
+      return item && item.value != null ? item.value : item
+    },
+    optionLabel(item) {
+      return item && item.label != null ? item.label : item
+    },
+    channelIndex(index) {
+      return (this.channelQuery.page - 1) * this.channelQuery.limit + index + 1
+    },
+    formatRate(value) {
+      if (value == null || value === '') return '--'
+      const number = Number(value)
+      return Number.isFinite(number) && Math.abs(number) <= 1 ? `${number * 100}%` : `${value}%`
+    },
+    displayValue(value, empty = '--') {
+      return value == null || value === '' ? empty : value
+    },
+    groupChannels(row, type) {
+      const displayKey = `${type}Types`
+      if (Array.isArray(row && row[displayKey])) return row[displayKey]
+      const values = row && (row[`${type}_type`] || row[`${type}Types`])
+      if (!Array.isArray(values)) return []
+      const pool = type === 'recharge' ? this.rechargeChannelPool : (type === 'withdraw' ? this.withdrawChannelPool : this.activityChannelPool)
+      return values.map(value => {
+        const typeValue = value && typeof value === 'object' ? value.type : value
+        return pool.find(item => String(item.type) === String(typeValue)) || { type: typeValue, name: value && typeof value === 'object' ? (value.name || typeValue) : typeValue }
+      })
+    },
     async getChannels() {
     async getChannels() {
       this.channelLoading = true
       this.channelLoading = true
       try {
       try {
         const res = await getRechargeChannelList(this.channelQuery)
         const res = await getRechargeChannelList(this.channelQuery)
         if (res.code === 0) {
         if (res.code === 0) {
-          this.channelList = res.data.data || []
+          const data = res.data || {}
+          this.channelList = Array.isArray(data) ? data : (data.data || [])
+          this.channelTotal = Array.isArray(data) ? this.channelList.length : Number(data.total || 0)
         }
         }
       } finally {
       } finally {
         this.channelLoading = false
         this.channelLoading = false
       }
       }
     },
     },
-    openChannelDialog(row) {
+    handleChannelTabClick() {
+      this.channelQuery.page = 1
+      this.getChannels()
+    },
+    handleChannelSizeChange(size) {
+      this.channelQuery.limit = size
+      this.channelQuery.page = 1
+      this.getChannels()
+    },
+    handleChannelPageChange(page) {
+      this.channelQuery.page = page
+      this.getChannels()
+    },
+    async openChannelDialog(row) {
       if (row) {
       if (row) {
-        // 编辑模式:只关注 ID 和状态
-        this.channelForm = { id: row.id, status: row.status }
+        this.channelForm = {
+          id: row.id,
+          data_type: row.data_type == null ? this.channelQuery.data_type : String(row.data_type),
+          from: row.from == null ? '' : row.from,
+          payment_company: row.payment_company || '',
+          payment_company_label: row.payment_company_label || '',
+          status: row.status,
+          name: row.name || '',
+          key: row.key || '',
+          type: row.type || '',
+          rate: row.rate == null ? '' : row.rate,
+          min: row.min == null ? '' : row.min,
+          max: row.max == null ? '' : row.max,
+          fixed_amount: row.fixed_amount == null ? (row.fixed == null ? '' : row.fixed) : row.fixed_amount,
+          sort: row.sort == null ? 0 : row.sort
+        }
       } else {
       } else {
-        // 兼容原逻辑
-        this.channelForm = { id: null, status: 1, name: '', key: '', type: '', rate: '', sort: 0 }
+        this.channelForm = { id: null, data_type: this.channelQuery.data_type, from: '', payment_company: '', payment_company_label: '', status: 1, name: '', key: '', type: '', rate: '', min: '', max: '', fixed_amount: '', sort: 0 }
       }
       }
       this.channelDialogVisible = true
       this.channelDialogVisible = true
+      await this.loadChannelOptions()
+    },
+    async loadChannelOptions() {
+      this.channelOptionsLoading = true
+      try {
+        const params = { data_type: this.channelForm.data_type }
+        if (this.channelForm.id) params.id = this.channelForm.id
+        const res = await getRechargeChannelOptions(params)
+        if (res.code === 0) {
+          const data = res.data || {}
+          this.channelOptions = {
+            from_options: data.from_options || [],
+            payment_companies: data.payment_companies || [],
+            types: data.types || [],
+            identity_editable: data.identity_editable !== false,
+            identity_edit_reason: data.identity_edit_reason || ''
+          }
+        }
+      } finally {
+        this.channelOptionsLoading = false
+      }
+    },
+    handleChannelFromChange() {
+      this.channelForm.type = ''
+      this.channelForm.payment_company = ''
+    },
+    handleChannelCompanyChange() {
+      this.channelForm.type = ''
+    },
+    handleChannelTypeChange(value) {
+      const item = this.channelOptions.types.find(option => String(this.optionValue(option)) === String(value))
+      if (item) {
+        this.channelForm.from = item.from == null ? this.channelForm.from : item.from
+        this.channelForm.payment_company = item.payment_company || ''
+        this.channelForm.payment_company_label = item.payment_company_label || ''
+      }
     },
     },
     async submitChannelForm() {
     async submitChannelForm() {
-      const res = await updateRechargeChannel(this.channelForm)
+      const payload = { ...this.channelForm, fixed: this.channelForm.fixed_amount }
+      delete payload.fixed_amount
+      delete payload.payment_company_label
+      if (this.channelForm.data_type === '3' || !this.channelForm.payment_company) payload.payment_company = null
+      const res = await updateRechargeChannel(payload)
       if (res.code === 0) {
       if (res.code === 0) {
         this.$message.success('操作成功')
         this.$message.success('操作成功')
         this.channelDialogVisible = false
         this.channelDialogVisible = false
         this.getChannels()
         this.getChannels()
+        this.loadChannelPool()
       }
       }
     },
     },
+    removeChannel(row) {
+      this.$confirm('是否删除该通道?删除后不可再选择', '提示', { type: 'warning' }).then(async() => {
+        const res = await deleteRechargeChannel({ id: row.id })
+        if (res.code === 0) {
+          this.$message.success('删除成功')
+          this.getChannels()
+          this.getGroups()
+          this.loadChannelPool()
+        } else {
+          this.$message.error(res.msg || '删除失败')
+        }
+      }).catch(() => {})
+    },
 
 
     // --- 通道组合逻辑 ---
     // --- 通道组合逻辑 ---
     async getGroups() {
     async getGroups() {
@@ -301,13 +573,60 @@ export default {
       try {
       try {
         const res = await getRechargeChannelGroupList(this.groupQuery)
         const res = await getRechargeChannelGroupList(this.groupQuery)
         if (res.code === 0) {
         if (res.code === 0) {
-          this.groupList = res.data.data || []
+          const data = res.data || {}
+          this.groupList = Array.isArray(data) ? data : (data.data || [])
         }
         }
       } finally {
       } finally {
         this.groupLoading = false
         this.groupLoading = false
       }
       }
     },
     },
 
 
+    async getCompanies() {
+      this.companyLoading = true
+      try {
+        const res = await getPaymentCompanyList(this.companyQuery)
+        if (res.code === 0) {
+          const data = res.data || {}
+          this.companyList = Array.isArray(data) ? data : (data.data || [])
+          this.companyTotal = Array.isArray(data) ? this.companyList.length : Number(data.total || 0)
+        }
+      } finally {
+        this.companyLoading = false
+      }
+    },
+    resetCompanyQuery() {
+      this.companyQuery = { page: 1, limit: this.companyQuery.limit, payment_company: '', status: '' }
+      this.getCompanies()
+    },
+    handleCompanySizeChange(size) {
+      this.companyQuery.limit = size
+      this.companyQuery.page = 1
+      this.getCompanies()
+    },
+    handleCompanyPageChange(page) {
+      this.companyQuery.page = page
+      this.getCompanies()
+    },
+    companyDataTypes(row) {
+      const values = Array.isArray(row.data_types) ? row.data_types : []
+      return values.map(value => Number(value) === 1 ? '充值' : '提现').join('、') || '--'
+    },
+    toggleCompanyStatus(row) {
+      const nextStatus = row.status === 1 ? 0 : 1
+      const confirmText = nextStatus === 0 ? '将暂停该公司的新充值及新代付,是否继续?' : '是否启用该支付公司?'
+      this.$confirm(confirmText, '提示', { type: 'warning' }).then(async() => {
+        const res = await setPaymentCompanyStatus({ payment_company: row.payment_company, status: nextStatus })
+        if (res.code === 0) {
+          this.$message.success('操作成功')
+          this.getCompanies()
+          this.getChannels()
+          this.loadChannelPool()
+        } else {
+          this.$message.error(res.msg || '操作失败')
+        }
+      }).catch(() => {})
+    },
+
     // 按 data_type 请求三个列表
     // 按 data_type 请求三个列表
     async loadChannelPool() {
     async loadChannelPool() {
       this.rechargeChannelPool = await this.fetchChannelByDataType('1')
       this.rechargeChannelPool = await this.fetchChannelByDataType('1')
@@ -317,7 +636,8 @@ export default {
     async fetchChannelByDataType(dataType) {
     async fetchChannelByDataType(dataType) {
       const res = await getRechargeChannelGetChannel({ data_type: dataType })
       const res = await getRechargeChannelGetChannel({ data_type: dataType })
       if (res.code === 0) {
       if (res.code === 0) {
-        const list = res.data?.data || []
+        const data = res.data || {}
+        const list = Array.isArray(data) ? data : (data.data || [])
         const uniqueList = []
         const uniqueList = []
         const map = new Map()
         const map = new Map()
         for (const item of list) {
         for (const item of list) {
@@ -336,22 +656,67 @@ export default {
         this.groupForm = {
         this.groupForm = {
           id: row.id,
           id: row.id,
           name: row.name,
           name: row.name,
-          recharge_type: row.recharge_type || [],
-          withdraw_type: row.withdraw_type || [],
-          activity_type: row.activity_type || []
+          recharge_type: this.groupTypeValues(row, 'recharge'),
+          withdraw_type: this.groupTypeValues(row, 'withdraw'),
+          activity_type: this.groupTypeValues(row, 'activity')
         }
         }
       } else {
       } else {
         this.groupForm = { id: null, name: '', recharge_type: [], withdraw_type: [], activity_type: [] }
         this.groupForm = { id: null, name: '', recharge_type: [], withdraw_type: [], activity_type: [] }
       }
       }
       this.groupDialogVisible = true
       this.groupDialogVisible = true
     },
     },
+    isGroupAllSelected(field, pool) {
+      const values = pool.map(item => item.type).filter(value => value != null && value !== '')
+      return values.length > 0 && values.every(value => this.groupForm[field].includes(value))
+    },
+    isGroupIndeterminate(field, pool) {
+      const values = pool.map(item => item.type).filter(value => value != null && value !== '')
+      const selectedCount = values.filter(value => this.groupForm[field].includes(value)).length
+      return selectedCount > 0 && selectedCount < values.length
+    },
+    toggleAllGroupChannels(field, pool, checked) {
+      this.groupForm[field] = checked
+        ? pool.map(item => item.type).filter(value => value != null && value !== '')
+        : []
+    },
     async submitGroupForm() {
     async submitGroupForm() {
-      const res = await updateRechargeChannelGroup(this.groupForm)
+      const payload = {
+        ...this.groupForm,
+        recharge_type: this.groupTypeValues(this.groupForm, 'recharge'),
+        withdraw_type: this.groupTypeValues(this.groupForm, 'withdraw'),
+        activity_type: this.groupTypeValues(this.groupForm, 'activity')
+      }
+      const res = await updateRechargeChannelGroup(payload)
       if (res.code === 0) {
       if (res.code === 0) {
-        this.$message.success('保存成功')
+        this.$message.success(res.msg || '保存成功')
         this.groupDialogVisible = false
         this.groupDialogVisible = false
         this.getGroups()
         this.getGroups()
+        this.loadChannelPool()
+      } else {
+        this.$message.error(res.msg || '保存失败')
       }
       }
+    },
+    removeGroup(row) {
+      this.$confirm('是否删除该层级?删除后不可恢复', '提示', { type: 'warning' }).then(async() => {
+        this.groupDeletingId = row.id
+        try {
+          const res = await deleteRechargeChannelGroup({ id: row.id })
+          if (res.code === 0) {
+            this.$message.success(res.msg || '删除成功')
+            this.getGroups()
+            this.loadChannelPool()
+          } else {
+            this.$message.error(res.msg || '删除失败')
+          }
+        } finally {
+          this.groupDeletingId = null
+        }
+      }).catch(() => {})
+    },
+    groupTypeValues(row, type) {
+      const raw = row && (row[`${type}_type`] || row[`${type}Types`])
+      if (!Array.isArray(raw)) return []
+      return raw.map(item => item && typeof item === 'object' ? item.type : item).filter(value => value != null && value !== '')
     }
     }
   }
   }
 }
 }
@@ -360,12 +725,23 @@ export default {
 <style scoped>
 <style scoped>
 .recharge-container {
 .recharge-container {
   margin: 20px;
   margin: 20px;
+  height: calc(100vh - 40px);
+  overflow: hidden;
+}
+
+.recharge-container >>> .el-tabs__content {
+  overflow: hidden;
 }
 }
 
 
 .filter-form {
 .filter-form {
   margin-bottom: 20px;
   margin-bottom: 20px;
 }
 }
 
 
+.channel-pagination {
+  margin-top: 8px;
+  text-align: right;
+}
+
 /* 选框组样式优化 */
 /* 选框组样式优化 */
 .channel-selector-card {
 .channel-selector-card {
   border: 1px solid #ebeef5;
   border: 1px solid #ebeef5;
@@ -375,6 +751,21 @@ export default {
   overflow-y: auto;
   overflow-y: auto;
 }
 }
 
 
+.group-actions {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 6px;
+}
+
+.group-actions .el-button {
+  margin-left: 0;
+}
+
+.selection-actions {
+  margin-bottom: 12px;
+}
+
 .channel-checkbox-item {
 .channel-checkbox-item {
   margin-bottom: 10px;
   margin-bottom: 10px;
   margin-left: 0 !important;
   margin-left: 0 !important;

Некоторые файлы не были показаны из-за большого количества измененных файлов