Просмотр исходного кода

feat(buff扫货): 优化扫货功能和界面交互

Made-with: Cursor
wuzilong 6 месяцев назад
Родитель
Сommit
1bf37a406b

+ 39 - 0
client-tauri/src-tauri/src/commands.rs

@@ -470,6 +470,45 @@ pub async fn update_account_card_rate(
     Ok(())
 }
 
+/// 更新账号的是否参与扫货状态
+#[tauri::command]
+pub async fn update_account_is_active(
+    steamUsername: String,
+    isActive: bool,
+) -> Result<(), String> {
+    let steam_msg_dir = get_steam_msg_dir()?;
+    let accounts_file = steam_msg_dir.join(ACCOUNTS_JSON);
+
+    if !accounts_file.exists() {
+        return Err("账号文件不存在".to_string());
+    }
+
+    let text = fs::read_to_string(&accounts_file).map_err(|e| format!("读取账号文件失败: {}", e))?;
+    let mut root: serde_json::Value =
+        serde_json::from_str(&text).unwrap_or(serde_json::json!({ "accounts": {} }));
+
+    let accounts = root
+        .get_mut("accounts")
+        .and_then(|a| a.as_object_mut())
+        .ok_or("账号数据结构异常")?;
+
+    let entry = accounts
+        .get_mut(&steamUsername)
+        .and_then(|v| v.as_object_mut())
+        .ok_or_else(|| format!("未找到账号 {}", steamUsername))?;
+
+    entry.insert(
+        "is_active".to_string(),
+        serde_json::json!(isActive),
+    );
+
+    let content =
+        serde_json::to_string_pretty(&root).map_err(|e| format!("序列化失败: {}", e))?;
+    fs::write(&accounts_file, content).map_err(|e| format!("写入账号文件失败: {}", e))?;
+
+    Ok(())
+}
+
 /// 将指定账号的 maFile 复制到用户选择的路径(下载 maFile)
 #[tauri::command]
 pub async fn export_mafile_to_path(steam_username: String, dest_path: String) -> Result<(), String> {

+ 10 - 0
client-tauri/src-tauri/src/commands/buff_sweep_runner.rs

@@ -698,6 +698,16 @@ fn load_local_accounts_filtered(allowed: Option<&HashSet<String>>) -> Result<Vec
                 continue;
             }
         }
+        // 新增: 检查 is_active 字段,如果明确设置为 false 则跳过(不参与扫货)
+        if let Some(is_active) = obj.get("is_active").and_then(|v| v.as_bool()) {
+            if !is_active {
+                app_log::debug(&format!(
+                    "[load_local_accounts_filtered] 账号 {} 的 is_active=false,不参与扫货,跳过",
+                    uname
+                ));
+                continue;
+            }
+        }
         let mafile = obj
             .get("steam_guard_path")
             .and_then(|v| v.as_str())

+ 1 - 0
client-tauri/src-tauri/src/main.rs

@@ -184,6 +184,7 @@ fn main() {
                 delete_project_steam_account,
                 update_account_is_us_account,
                 update_account_card_rate,
+                update_account_is_active,
                 export_mafile_to_path,
                 get_steam_wallet_balance,
                 read_proxy_config,

+ 41 - 88
client-tauri/src/views/BuffSelectionView.vue

@@ -473,9 +473,6 @@
           <div class="section-header-left">
             <span class="section-icon">🎮</span>
             <span class="section-title">已绑定 Steam 账号</span>
-            <a-tag v-if="selectedBoundSteamCount > 0" color="blue">
-              已选 {{ selectedBoundSteamCount }} / {{ boundSteamAccounts.length }}
-            </a-tag>
           </div>
           <div class="section-actions">
             <a-button
@@ -496,27 +493,8 @@
             :loading="boundSteamLoading"
             :pagination="false"
             :row-key="(record: BoundSteamRow) => record.steam_username"
-            :row-selection="{
-              selectedRowKeys: Array.from(selectedBoundSteamUsernames),
-              onChange: (keys: string[]) => {
-                const newKeys = new Set(keys)
-                // 找出新增的(勾选)和移除的(取消勾选)
-                const addedKeys = keys.filter((k: string) => !prevSelectedBoundSteamKeys.value.has(k))
-                const removedKeys = Array.from(prevSelectedBoundSteamKeys.value).filter(k => !newKeys.has(k))
-                // 更新选中状态
-                selectedBoundSteamUsernames.value = newKeys
-                prevSelectedBoundSteamKeys.value = newKeys
-                // 显示提示
-                if (addedKeys.length > 0) {
-                  message.success(`已勾选 ${addedKeys.length} 个账号`)
-                }
-                if (removedKeys.length > 0) {
-                  message.info(`已取消勾选 ${removedKeys.length} 个账号`)
-                }
-              }
-            }"
             size="small"
-            :scroll="{ x: 800 }"
+            :scroll="{ x: 900 }"
           >
             <template #bodyCell="{ column, record }">
               <template v-if="column.key === 'balance'">
@@ -533,6 +511,15 @@
                   </span>
                 </span>
               </template>
+              <template v-else-if="column.key === 'is_active'">
+                <a-switch
+                  :checked="record.is_active !== false"
+                  checked-children="参与"
+                  un-checked-children="不参与"
+                  size="small"
+                  @change="(checked: boolean) => handleBoundSteamActiveChange(record, checked)"
+                />
+              </template>
               <template v-else-if="column.key === 'cardRate'">
                 <a-input-number
                   :value="record.cardRate"
@@ -1223,6 +1210,7 @@ type BoundSteamRow = {
   steam_id: string
   hasSteamLoginSecure: boolean
   cardRate?: number | null
+  is_active?: boolean
 }
 const boundSteamLoading = ref(false)
 const boundSteamAccounts = ref<BoundSteamRow[]>([])
@@ -1565,66 +1553,13 @@ const sweepColumns = [
 const boundSteamColumns = [
   { title: 'Steam ID', dataIndex: 'steam_id', key: 'steam_id', width: 150 },
   { title: 'Steam 账号', dataIndex: 'steam_username', key: 'steam_username', width: 120 },
+  { title: '参与扫货', key: 'is_active', width: 100, align: 'center' as const },
   { title: '余额', key: 'balance', width: 120 },
   { title: '充值卡价比例', key: 'cardRate', width: 100 },
   { title: '状态', key: 'status', width: 120 },
   { title: '操作', key: 'action', width: 180 }
 ]
 
-/** 已绑定 Steam 账号勾选状态 */
-const selectedBoundSteamUsernames = ref<Set<string>>(new Set())
-
-/** 上一次已绑定 Steam 账号选中的 keys(用于对比勾选/取消勾选) */
-const prevSelectedBoundSteamKeys = ref<Set<string>>(new Set())
-
-/** 全部已绑定 Steam 账号是否已勾选 */
-const allBoundSteamSelected = computed(() => {
-  if (boundSteamAccounts.value.length === 0) return false
-  return boundSteamAccounts.value.every(a => selectedBoundSteamUsernames.value.has(a.steam_username))
-})
-
-/** 部分已绑定 Steam 账号被勾选 */
-const someBoundSteamSelected = computed(() => {
-  if (boundSteamAccounts.value.length === 0) return false
-  return boundSteamAccounts.value.some(a => selectedBoundSteamUsernames.value.has(a.steam_username)) && !allBoundSteamSelected.value
-})
-
-/** 选中的 Steam 账号数量 */
-const selectedBoundSteamCount = computed(() => selectedBoundSteamUsernames.value.size)
-
-/** 获取选中的 Steam 账号列表 */
-function getSelectedBoundSteamAccounts(): string[] {
-  return boundSteamAccounts.value
-    .filter(a => selectedBoundSteamUsernames.value.has(a.steam_username))
-    .map(a => a.steam_username)
-}
-
-/** 切换全选/取消全选 */
-function toggleSelectAllBoundSteam(checked: boolean) {
-  if (checked) {
-    boundSteamAccounts.value.forEach(a => selectedBoundSteamUsernames.value.add(a.steam_username))
-  } else {
-    selectedBoundSteamUsernames.value.clear()
-  }
-}
-
-/** 切换单个账号的选择状态 */
-function toggleSelectBoundSteam(username: string, checked: boolean) {
-  if (checked) {
-    selectedBoundSteamUsernames.value.add(username)
-  } else {
-    selectedBoundSteamUsernames.value.delete(username)
-  }
-}
-
-/** 初始化/重置账号选择状态(默认全选) */
-function initSelectedBoundSteamAccounts() {
-  selectedBoundSteamUsernames.value.clear()
-  boundSteamAccounts.value.forEach(a => selectedBoundSteamUsernames.value.add(a.steam_username))
-  // 同步更新 prevSelectedBoundSteamKeys
-  prevSelectedBoundSteamKeys.value = new Set(selectedBoundSteamUsernames.value)
-}
-
 /** 配置中的排除/指定 id 可能为字符串或数组,统一为换行分隔字符串 */
 function normalizeIdsField(v: unknown): string {
   if (v == null) return ''
@@ -2136,6 +2071,22 @@ async function handleBoundSteamCardRateChange(record: BoundSteamRow, rate: numbe
   }
 }
 
+async function handleBoundSteamActiveChange(record: BoundSteamRow, isActive: boolean) {
+  try {
+    await invoke('update_account_is_active', {
+      steamUsername: record.steam_username,
+      isActive
+    })
+    const idx = boundSteamAccounts.value.findIndex(a => a.steam_username === record.steam_username)
+    if (idx !== -1) {
+      boundSteamAccounts.value[idx].is_active = isActive
+    }
+    message.success(isActive ? '已设置为参与扫货' : '已设置为不参与扫货')
+  } catch (err: any) {
+    message.error(err?.message || err?.toString() || '保存失败')
+  }
+}
+
 async function loadBoundSteamAccounts(autoRefreshBalances: boolean = true) {
   const userId = authStore.userId
   if (!userId) {
@@ -2160,9 +2111,12 @@ async function loadBoundSteamAccounts(autoRefreshBalances: boolean = true) {
         .map((item) => String(item.steam_account))
     )
     const localCardRateMap: Record<string, number | null> = {}
+    const localIsActiveMap: Record<string, boolean> = {}
     for (const item of localList) {
       if (item.steam_account) {
         localCardRateMap[item.steam_account] = item.card_rate ?? null
+        const raw = item as Record<string, any>
+        localIsActiveMap[item.steam_account] = raw.is_active !== false
       }
     }
     const boundList = (apiRes.data || [])
@@ -2172,11 +2126,10 @@ async function loadBoundSteamAccounts(autoRefreshBalances: boolean = true) {
         steam_username: item.steam_username,
         steam_id: String(item.steam_id),
         hasSteamLoginSecure: localSecureSet.has(item.steam_username),
-        cardRate: localCardRateMap[item.steam_username] ?? null
+        cardRate: localCardRateMap[item.steam_username] ?? null,
+        is_active: localIsActiveMap[item.steam_username] ?? true
       }))
     boundSteamAccounts.value = boundList
-    // 初始化账号选择状态(默认全选)
-    initSelectedBoundSteamAccounts()
     if (autoRefreshBalances) {
       await refreshBoundSteamBalances(true)
     }
@@ -3403,16 +3356,16 @@ async function handleStartSweep(isAuto: boolean, sourceSelectionRequestId?: numb
     return
   }
 
-  // 验证必须勾选至少一个 Steam 账号
-  const selectedAccounts = getSelectedBoundSteamAccounts()
-  if (selectedAccounts.length === 0) {
-    if (!isAuto) message.warning('请至少勾选一个 Steam 账号后再开始扫货')
+  // 验证至少有一个参与扫货的 Steam 账号
+  const activeAccounts = boundSteamAccounts.value.filter(a => a.is_active !== false)
+  if (activeAccounts.length === 0) {
+    if (!isAuto) message.warning('没有参与扫货的 Steam 账号,请至少开启一个')
     return
   }
-  // 构建选中账号的充值卡价比例映射
+  // 构建参与扫货账号的充值卡价比例映射
   const accountCardRateMap: Record<string, number> = {}
-  for (const account of boundSteamAccounts.value) {
-    if (selectedBoundSteamUsernames.value.has(account.steam_username) && account.cardRate != null) {
+  for (const account of activeAccounts) {
+    if (account.cardRate != null) {
       accountCardRateMap[account.steam_username] = account.cardRate
     }
   }
@@ -3492,7 +3445,7 @@ async function handleStartSweep(isAuto: boolean, sourceSelectionRequestId?: numb
         sweepRid,
         selRid,
         wc,
-        selectedAccounts,
+        activeAccounts.map(a => a.steam_username),
         accountCardRateMap
       )
       if (!spawned.ok && !isAuto) {