From 4f16a51087d25f65eabc6cc18b499e46c1414ebd Mon Sep 17 00:00:00 2001 From: zhinianboke <115088296+zhinianboke@users.noreply.github.com> Date: Wed, 6 Aug 2025 15:25:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=95=86=E5=93=81=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AUTO_REPLY_PAUSE_README.md | 121 ------------- PAUSE_DURATION_FEATURE.md | 185 ------------------- reply_server.py | 15 +- static/data_management.html | 12 ++ static/index.html | 66 ++++++- static/js/app.js | 342 +++++++++++++++++++++++++++++------- 6 files changed, 358 insertions(+), 383 deletions(-) delete mode 100644 AUTO_REPLY_PAUSE_README.md delete mode 100644 PAUSE_DURATION_FEATURE.md diff --git a/AUTO_REPLY_PAUSE_README.md b/AUTO_REPLY_PAUSE_README.md deleted file mode 100644 index cc49b97..0000000 --- a/AUTO_REPLY_PAUSE_README.md +++ /dev/null @@ -1,121 +0,0 @@ -# 自动回复暂停功能说明 - -## 功能概述 - -当系统检测到某个 `chat_id` 有手动发出的消息时,会自动暂停该 `chat_id` 的自动回复功能10分钟。如果在暂停期间再次检测到手动发出的消息,会重新开始计时10分钟。 - -## 功能特性 - -### 1. 智能检测 -- 系统会自动检测每个聊天会话中的手动发出消息 -- 检测到手动发出时会在日志中显示:`[时间] 【手动发出】 商品(商品ID): 消息内容` - -### 2. 自动暂停 -- 检测到手动发出后,立即暂停该 `chat_id` 的自动回复10分钟 -- 暂停期间会在日志中显示:`【账号ID】检测到手动发出消息,chat_id XXX 自动回复暂停10分钟,恢复时间: YYYY-MM-DD HH:MM:SS` - -### 3. 重新计时 -- 如果在暂停期间再次检测到手动发出,会重新开始计时10分钟 -- 每次手动发出都会刷新暂停时间 - -### 4. 暂停提示 -- 当收到消息但处于暂停状态时,会在日志中显示: - `【账号ID】【系统】chat_id XXX 自动回复已暂停,剩余时间: X分Y秒` - -### 5. 自动恢复 -- 暂停时间到期后,自动恢复该 `chat_id` 的自动回复功能 -- 无需手动干预 - -## 技术实现 - -### 核心组件 - -#### AutoReplyPauseManager 类 -- `pause_chat(chat_id, cookie_id)`: 暂停指定chat_id的自动回复 -- `is_chat_paused(chat_id)`: 检查指定chat_id是否处于暂停状态 -- `get_remaining_pause_time(chat_id)`: 获取剩余暂停时间 -- `cleanup_expired_pauses()`: 清理过期的暂停记录 - -#### 集成点 - -1. **检测手动发出** (第2730行) - ```python - if send_user_id == self.myid: - logger.info(f"[{msg_time}] 【手动发出】 商品({item_id}): {send_message}") - # 暂停该chat_id的自动回复10分钟 - pause_manager.pause_chat(chat_id, self.cookie_id) - return - ``` - -2. **检查暂停状态** (第2750行) - ```python - # 检查该chat_id是否处于暂停状态 - if pause_manager.is_chat_paused(chat_id): - remaining_time = pause_manager.get_remaining_pause_time(chat_id) - remaining_minutes = remaining_time // 60 - remaining_seconds = remaining_time % 60 - logger.info(f"[{msg_time}] 【{self.cookie_id}】【系统】chat_id {chat_id} 自动回复已暂停,剩余时间: {remaining_minutes}分{remaining_seconds}秒") - return - ``` - -3. **定期清理** (第2372行) - ```python - async def pause_cleanup_loop(self): - """定期清理过期的暂停记录""" - while True: - # 每5分钟清理一次过期记录 - pause_manager.cleanup_expired_pauses() - await asyncio.sleep(300) - ``` - -## 配置参数 - -### 暂停时长 -- 默认:10分钟 (600秒) -- 位置:`AutoReplyPauseManager.__init__()` 中的 `self.pause_duration` -- 可根据需要修改 - -### 清理频率 -- 默认:每5分钟清理一次过期记录 -- 位置:`pause_cleanup_loop()` 中的 `await asyncio.sleep(300)` - -## 日志示例 - -### 检测到手动发出 -``` -2025-08-05 14:48:32.209 | INFO | XianyuAutoAsync:handle_message:2673 - [2025-08-05 14:48:31] 【手动发出】 商品(12345): 你好,这个商品还在吗? -2025-08-05 14:48:32.210 | INFO | XianyuAutoAsync:pause_chat:40 - 【dfg】检测到手动发出消息,chat_id chat_123 自动回复暂停10分钟,恢复时间: 2025-08-05 14:58:32 -``` - -### 暂停期间收到消息 -``` -2025-08-05 14:50:15.123 | INFO | XianyuAutoAsync:handle_message:2678 - [2025-08-05 14:50:15] 【收到】用户: 张三 (ID: 67890), 商品(12345): 多少钱? -2025-08-05 14:50:15.124 | INFO | XianyuAutoAsync:handle_message:2754 - [2025-08-05 14:50:15] 【dfg】【系统】chat_id chat_123 自动回复已暂停,剩余时间: 8分17秒 -``` - -### 重新计时 -``` -2025-08-05 14:55:20.456 | INFO | XianyuAutoAsync:handle_message:2673 - [2025-08-05 14:55:20] 【手动发出】 商品(12345): 价格可以商量 -2025-08-05 14:55:20.457 | INFO | XianyuAutoAsync:pause_chat:40 - 【dfg】检测到手动发出消息,chat_id chat_123 自动回复暂停10分钟,恢复时间: 2025-08-05 15:05:20 -``` - -## 注意事项 - -1. **全局管理器**: 使用全局的 `pause_manager` 实例,所有账号共享暂停状态 -2. **内存存储**: 暂停记录存储在内存中,程序重启后会丢失 -3. **自动清理**: 系统会定期清理过期的暂停记录,避免内存泄漏 -4. **线程安全**: 暂停管理器是线程安全的,可以在多个协程中使用 - -## 测试 - -运行测试脚本验证功能: -```bash -python test_pause_manager.py -``` - -测试包括: -- 基本暂停/恢复功能 -- 重新计时机制 -- 多chat_id管理 -- 过期清理功能 -- 时间计算准确性 diff --git a/PAUSE_DURATION_FEATURE.md b/PAUSE_DURATION_FEATURE.md deleted file mode 100644 index f992601..0000000 --- a/PAUSE_DURATION_FEATURE.md +++ /dev/null @@ -1,185 +0,0 @@ -# 账号自动回复暂停时间配置功能 - -## 功能概述 - -为每个账号单独配置自动回复暂停时间,当检测到手动发出消息后,该账号的自动回复会暂停指定的时间长度。 - -## 功能特性 - -### 1. 个性化配置 -- 每个账号可以单独设置暂停时间(1-60分钟) -- 默认暂停时间为10分钟 -- 支持实时修改,立即生效 - -### 2. 直观界面 -- 在账号管理表格中新增"暂停时间"列 -- 点击暂停时间可直接编辑 -- 带有说明工具提示,解释功能作用 - -### 3. 智能验证 -- 暂停时间范围限制:1-60分钟 -- 输入验证和错误提示 -- 支持键盘操作(Enter保存,Escape取消) - -## 界面展示 - -### 表格列头 -``` -账号ID | Cookie值 | 关键词 | 状态 | 默认回复 | AI回复 | 自动确认发货 | 备注 | 暂停时间 | 操作 -``` - -### 暂停时间列 -- 显示格式:`🕐 10分钟` -- 工具提示:`检测到手动发出消息后,自动回复暂停的时间长度(分钟)。如果在暂停期间再次手动发出消息,会重新开始计时。` -- 点击可编辑,支持数字输入框 - -## 技术实现 - -### 数据库结构 -```sql --- cookies表新增字段 -ALTER TABLE cookies ADD COLUMN pause_duration INTEGER DEFAULT 10; -``` - -### 后端API - -#### 1. 更新暂停时间 -```http -PUT /cookies/{cid}/pause-duration -Content-Type: application/json -Authorization: Bearer {token} - -{ - "pause_duration": 15 -} -``` - -**响应**: -```json -{ - "message": "暂停时间更新成功", - "pause_duration": 15 -} -``` - -#### 2. 获取暂停时间 -```http -GET /cookies/{cid}/pause-duration -Authorization: Bearer {token} -``` - -**响应**: -```json -{ - "pause_duration": 15, - "message": "获取暂停时间成功" -} -``` - -### 前端功能 - -#### 1. 表格显示 -- 在账号列表中显示每个账号的暂停时间 -- 默认显示为"🕐 10分钟"格式 - -#### 2. 内联编辑 -```javascript -function editPauseDuration(cookieId, currentDuration) { - // 创建数字输入框 - // 支持1-60分钟范围 - // Enter保存,Escape取消 - // 实时验证和错误提示 -} -``` - -#### 3. 工具提示 -- 使用Bootstrap Tooltip组件 -- 自动初始化和重新初始化 - -### 暂停管理器集成 - -#### 动态获取暂停时间 -```python -def pause_chat(self, chat_id: str, cookie_id: str): - """暂停指定chat_id的自动回复,使用账号特定的暂停时间""" - # 获取账号特定的暂停时间 - try: - from db_manager import db_manager - pause_minutes = db_manager.get_cookie_pause_duration(cookie_id) - except Exception as e: - logger.error(f"获取账号 {cookie_id} 暂停时间失败: {e},使用默认10分钟") - pause_minutes = 10 - - pause_duration_seconds = pause_minutes * 60 - pause_until = time.time() + pause_duration_seconds - self.paused_chats[chat_id] = pause_until - - # 记录日志 - end_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(pause_until)) - logger.info(f"【{cookie_id}】检测到手动发出消息,chat_id {chat_id} 自动回复暂停{pause_minutes}分钟,恢复时间: {end_time}") -``` - -## 使用流程 - -### 1. 查看当前设置 -1. 登录系统,进入账号管理页面 -2. 在表格中查看"暂停时间"列 -3. 鼠标悬停在列头的问号图标上查看功能说明 - -### 2. 修改暂停时间 -1. 点击要修改的账号的暂停时间(如"🕐 10分钟") -2. 输入框出现,输入新的暂停时间(1-60分钟) -3. 按Enter键保存,或按Escape键取消 -4. 系统显示成功提示 - -### 3. 验证生效 -1. 修改后的设置立即生效 -2. 下次该账号检测到手动发出消息时,会使用新的暂停时间 -3. 在日志中可以看到使用的暂停时间 - -## 日志示例 - -### 使用自定义暂停时间 -``` -2025-08-05 15:30:15.123 | INFO | XianyuAutoAsync:pause_chat:49 - 【abc123】检测到手动发出消息,chat_id chat_456 自动回复暂停15分钟,恢复时间: 2025-08-05 15:45:15 -``` - -### 获取暂停时间失败时使用默认值 -``` -2025-08-05 15:30:15.124 | ERROR | XianyuAutoAsync:pause_chat:42 - 获取账号 abc123 暂停时间失败: Database error,使用默认10分钟 -2025-08-05 15:30:15.125 | INFO | XianyuAutoAsync:pause_chat:49 - 【abc123】检测到手动发出消息,chat_id chat_456 自动回复暂停10分钟,恢复时间: 2025-08-05 15:40:15 -``` - -## 配置建议 - -### 不同场景的推荐设置 - -1. **高频互动商品**:5-10分钟 - - 适用于需要快速响应的热门商品 - - 减少客户等待时间 - -2. **普通商品**:10-15分钟(默认) - - 平衡自动化和人工干预 - - 适合大多数场景 - -3. **低频互动商品**:20-30分钟 - - 适用于不常有咨询的商品 - - 给予更多人工处理时间 - -4. **特殊商品**:30-60分钟 - - 需要详细沟通的复杂商品 - - 避免自动回复干扰深度交流 - -## 注意事项 - -1. **范围限制**:暂停时间必须在1-60分钟之间 -2. **立即生效**:修改后的设置立即生效,无需重启 -3. **默认值**:新账号默认使用10分钟暂停时间 -4. **错误处理**:获取暂停时间失败时自动使用默认10分钟 -5. **权限控制**:只能修改自己账号的暂停时间设置 - -## 兼容性 - -- **向后兼容**:现有账号自动获得默认10分钟设置 -- **数据迁移**:系统启动时自动添加pause_duration字段 -- **API兼容**:现有API继续正常工作,新增字段可选 diff --git a/reply_server.py b/reply_server.py index 152e456..46232d8 100644 --- a/reply_server.py +++ b/reply_server.py @@ -3658,9 +3658,10 @@ def get_table_data(table_name: str, admin_user: Dict[str, Any] = Depends(require # 验证表名安全性 allowed_tables = [ - 'users', 'cookies', 'keywords', 'default_replies', 'ai_reply_settings', + 'users', 'cookies', 'cookie_status', 'keywords', 'default_replies', 'default_reply_records', + 'ai_reply_settings', 'ai_conversations', 'ai_item_cache', 'item_info', 'message_notifications', 'cards', 'delivery_rules', 'notification_channels', - 'user_settings', 'email_verifications', 'captcha_codes' + 'user_settings', 'system_settings', 'email_verifications', 'captcha_codes' ] if table_name not in allowed_tables: @@ -3694,9 +3695,10 @@ def delete_table_record(table_name: str, record_id: str, admin_user: Dict[str, A # 验证表名安全性 allowed_tables = [ - 'users', 'cookies', 'keywords', 'default_replies', 'ai_reply_settings', + 'users', 'cookies', 'cookie_status', 'keywords', 'default_replies', 'default_reply_records', + 'ai_reply_settings', 'ai_conversations', 'ai_item_cache', 'item_info', 'message_notifications', 'cards', 'delivery_rules', 'notification_channels', - 'user_settings', 'email_verifications', 'captcha_codes' + 'user_settings', 'system_settings', 'email_verifications', 'captcha_codes' ] if table_name not in allowed_tables: @@ -3733,9 +3735,10 @@ def clear_table_data(table_name: str, admin_user: Dict[str, Any] = Depends(requi # 验证表名安全性 allowed_tables = [ - 'cookies', 'keywords', 'default_replies', 'ai_reply_settings', + 'cookies', 'cookie_status', 'keywords', 'default_replies', 'default_reply_records', + 'ai_reply_settings', 'ai_conversations', 'ai_item_cache', 'item_info', 'message_notifications', 'cards', 'delivery_rules', 'notification_channels', - 'user_settings', 'email_verifications', 'captcha_codes' + 'user_settings', 'system_settings', 'email_verifications', 'captcha_codes' ] # 不允许清空用户表 diff --git a/static/data_management.html b/static/data_management.html index 7a84c81..cd0f83a 100644 --- a/static/data_management.html +++ b/static/data_management.html @@ -95,14 +95,20 @@ + + + + + + @@ -254,14 +260,20 @@ const tableDescriptions = { 'users': '用户表', 'cookies': 'Cookie账号表', + 'cookie_status': 'Cookie状态表', 'keywords': '关键字表', 'default_replies': '默认回复表', + 'default_reply_records': '默认回复记录表', 'ai_reply_settings': 'AI回复设置表', + 'ai_conversations': 'AI对话历史表', + 'ai_item_cache': 'AI商品信息缓存表', + 'item_info': '商品信息表', 'message_notifications': '消息通知表', 'cards': '卡券表', 'delivery_rules': '发货规则表', 'notification_channels': '通知渠道表', 'user_settings': '用户设置表', + 'system_settings': '系统设置表', 'email_verifications': '邮箱验证表', 'captcha_codes': '验证码表' }; diff --git a/static/index.html b/static/index.html index 1a28dc1..ed1146b 100644 --- a/static/index.html +++ b/static/index.html @@ -314,16 +314,17 @@
- +
-
+
+
@@ -345,18 +346,33 @@
+ + +
-
商品列表(自动发货根据商品标题和商品详情匹配关键字)
+
+ +
商品列表(自动发货根据商品标题和商品详情匹配关键字)
+
+ +
@@ -375,12 +391,54 @@ - +
加载中...加载中...
+ + +
diff --git a/static/js/app.js b/static/js/app.js index 132771f..f014999 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -17,6 +17,14 @@ let accountKeywordCache = {}; let cacheTimestamp = 0; const CACHE_DURATION = 30000; // 30秒缓存 +// 商品列表搜索和分页相关变量 +let allItemsData = []; // 存储所有商品数据 +let filteredItemsData = []; // 存储过滤后的商品数据 +let currentItemsPage = 1; // 当前页码 +let itemsPerPage = 20; // 每页显示数量 +let totalItemsPages = 0; // 总页数 +let currentSearchKeyword = ''; // 当前搜索关键词 + // ================================ // 通用功能 - 菜单切换和导航 // ================================ @@ -1793,6 +1801,9 @@ document.addEventListener('DOMContentLoaded', async () => { // 初始化工具提示 initTooltips(); + // 初始化商品搜索功能 + initItemsSearch(); + // 点击侧边栏外部关闭移动端菜单 document.addEventListener('click', function(e) { const sidebar = document.getElementById('sidebar'); @@ -4977,94 +4988,291 @@ async function loadItemsByCookie() { // 显示商品列表 function displayItems(items) { + // 存储所有商品数据 + allItemsData = items || []; + + // 应用搜索过滤 + applyItemsFilter(); + + // 显示当前页数据 + displayCurrentPageItems(); + + // 更新分页控件 + updateItemsPagination(); +} + +// 应用搜索过滤 +function applyItemsFilter() { + const searchKeyword = currentSearchKeyword.toLowerCase().trim(); + + if (!searchKeyword) { + filteredItemsData = [...allItemsData]; + } else { + filteredItemsData = allItemsData.filter(item => { + const title = (item.item_title || '').toLowerCase(); + const detail = getItemDetailText(item.item_detail || '').toLowerCase(); + return title.includes(searchKeyword) || detail.includes(searchKeyword); + }); + } + + // 重置到第一页 + currentItemsPage = 1; + + // 计算总页数 + totalItemsPages = Math.ceil(filteredItemsData.length / itemsPerPage); + + // 更新搜索统计 + updateItemsSearchStats(); +} + +// 获取商品详情的纯文本内容 +function getItemDetailText(itemDetail) { + if (!itemDetail) return ''; + + try { + // 尝试解析JSON + const detail = JSON.parse(itemDetail); + if (detail.content) { + return detail.content; + } + return itemDetail; + } catch (e) { + // 如果不是JSON格式,直接返回原文本 + return itemDetail; + } +} + +// 显示当前页的商品数据 +function displayCurrentPageItems() { const tbody = document.getElementById('itemsTableBody'); - if (!items || items.length === 0) { - tbody.innerHTML = '暂无商品数据'; - // 重置选择状态 - const selectAllCheckbox = document.getElementById('selectAllItems'); - if (selectAllCheckbox) { - selectAllCheckbox.checked = false; - selectAllCheckbox.indeterminate = false; - } - updateBatchDeleteButton(); - return; + if (!filteredItemsData || filteredItemsData.length === 0) { + tbody.innerHTML = '暂无商品数据'; + resetItemsSelection(); + return; } - const itemsHtml = items.map(item => { - // 处理商品标题显示 - let itemTitleDisplay = item.item_title || '未设置'; - if (itemTitleDisplay.length > 30) { - itemTitleDisplay = itemTitleDisplay.substring(0, 30) + '...'; - } + // 计算当前页的数据范围 + const startIndex = (currentItemsPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + const currentPageItems = filteredItemsData.slice(startIndex, endIndex); - // 处理商品详情显示 - let itemDetailDisplay = '未设置'; - if (item.item_detail) { - try { - // 尝试解析JSON并提取有用信息 - const detail = JSON.parse(item.item_detail); - if (detail.content) { - itemDetailDisplay = detail.content.substring(0, 50) + (detail.content.length > 50 ? '...' : ''); - } else { - // 如果是纯文本或其他格式,直接显示前50个字符 - itemDetailDisplay = item.item_detail.substring(0, 50) + (item.item_detail.length > 50 ? '...' : ''); + const itemsHtml = currentPageItems.map(item => { + // 处理商品标题显示 + let itemTitleDisplay = item.item_title || '未设置'; + if (itemTitleDisplay.length > 30) { + itemTitleDisplay = itemTitleDisplay.substring(0, 30) + '...'; } - } catch (e) { - // 如果不是JSON格式,直接显示前50个字符 - itemDetailDisplay = item.item_detail.substring(0, 50) + (item.item_detail.length > 50 ? '...' : ''); + + // 处理商品详情显示 + let itemDetailDisplay = '未设置'; + if (item.item_detail) { + const detailText = getItemDetailText(item.item_detail); + itemDetailDisplay = detailText.substring(0, 50) + (detailText.length > 50 ? '...' : ''); } - } - // 多规格状态显示 - const isMultiSpec = item.is_multi_spec; - const multiSpecDisplay = isMultiSpec ? - '多规格' : - '普通'; + // 多规格状态显示 + const isMultiSpec = item.is_multi_spec; + const multiSpecDisplay = isMultiSpec ? + '多规格' : + '普通'; - return ` - - - - - ${escapeHtml(item.cookie_id)} - ${escapeHtml(item.item_id)} - ${escapeHtml(itemTitleDisplay)} - ${escapeHtml(itemDetailDisplay)} - ${multiSpecDisplay} - ${formatDateTime(item.updated_at)} - -
- - - -
- - - `; + return ` + + + + + ${escapeHtml(item.cookie_id)} + ${escapeHtml(item.item_id)} + ${escapeHtml(itemTitleDisplay)} + ${escapeHtml(itemDetailDisplay)} + ${multiSpecDisplay} + ${formatDateTime(item.updated_at)} + +
+ + + +
+ + + `; }).join(''); // 更新表格内容 tbody.innerHTML = itemsHtml; // 重置选择状态 + resetItemsSelection(); +} + +// 重置商品选择状态 +function resetItemsSelection() { const selectAllCheckbox = document.getElementById('selectAllItems'); if (selectAllCheckbox) { - selectAllCheckbox.checked = false; - selectAllCheckbox.indeterminate = false; + selectAllCheckbox.checked = false; + selectAllCheckbox.indeterminate = false; } updateBatchDeleteButton(); } +// 商品搜索过滤函数 +function filterItems() { + const searchInput = document.getElementById('itemSearchInput'); + currentSearchKeyword = searchInput ? searchInput.value : ''; + + // 应用过滤 + applyItemsFilter(); + + // 显示当前页数据 + displayCurrentPageItems(); + + // 更新分页控件 + updateItemsPagination(); +} + +// 更新搜索统计信息 +function updateItemsSearchStats() { + const statsElement = document.getElementById('itemSearchStats'); + const statsTextElement = document.getElementById('itemSearchStatsText'); + + if (!statsElement || !statsTextElement) return; + + if (currentSearchKeyword) { + statsTextElement.textContent = `搜索"${currentSearchKeyword}",找到 ${filteredItemsData.length} 个商品`; + statsElement.style.display = 'block'; + } else { + statsElement.style.display = 'none'; + } +} + +// 更新分页控件 +function updateItemsPagination() { + const paginationElement = document.getElementById('itemsPagination'); + const pageInfoElement = document.getElementById('itemsPageInfo'); + const totalPagesElement = document.getElementById('itemsTotalPages'); + const pageInputElement = document.getElementById('itemsPageInput'); + + if (!paginationElement) return; + + // 分页控件总是显示 + paginationElement.style.display = 'block'; + + // 更新页面信息 + const startIndex = (currentItemsPage - 1) * itemsPerPage + 1; + const endIndex = Math.min(currentItemsPage * itemsPerPage, filteredItemsData.length); + + if (pageInfoElement) { + pageInfoElement.textContent = `显示第 ${startIndex}-${endIndex} 条,共 ${filteredItemsData.length} 条记录`; + } + + if (totalPagesElement) { + totalPagesElement.textContent = totalItemsPages; + } + + if (pageInputElement) { + pageInputElement.value = currentItemsPage; + pageInputElement.max = totalItemsPages; + } + + // 更新分页按钮状态 + updateItemsPaginationButtons(); +} + +// 更新分页按钮状态 +function updateItemsPaginationButtons() { + const firstPageBtn = document.getElementById('itemsFirstPage'); + const prevPageBtn = document.getElementById('itemsPrevPage'); + const nextPageBtn = document.getElementById('itemsNextPage'); + const lastPageBtn = document.getElementById('itemsLastPage'); + + if (firstPageBtn) firstPageBtn.disabled = currentItemsPage <= 1; + if (prevPageBtn) prevPageBtn.disabled = currentItemsPage <= 1; + if (nextPageBtn) nextPageBtn.disabled = currentItemsPage >= totalItemsPages; + if (lastPageBtn) lastPageBtn.disabled = currentItemsPage >= totalItemsPages; +} + +// 跳转到指定页面 +function goToItemsPage(page) { + if (page < 1 || page > totalItemsPages) return; + + currentItemsPage = page; + displayCurrentPageItems(); + updateItemsPagination(); +} + +// 处理页面输入框的回车事件 +function handleItemsPageInput(event) { + if (event.key === 'Enter') { + const pageInput = event.target; + const page = parseInt(pageInput.value); + + if (page >= 1 && page <= totalItemsPages) { + goToItemsPage(page); + } else { + pageInput.value = currentItemsPage; + } + } +} + +// 改变每页显示数量 +function changeItemsPageSize() { + const pageSizeSelect = document.getElementById('itemsPageSize'); + if (!pageSizeSelect) return; + + itemsPerPage = parseInt(pageSizeSelect.value); + + // 重新计算总页数 + totalItemsPages = Math.ceil(filteredItemsData.length / itemsPerPage); + + // 调整当前页码,确保不超出范围 + if (currentItemsPage > totalItemsPages) { + currentItemsPage = Math.max(1, totalItemsPages); + } + + // 重新显示数据 + displayCurrentPageItems(); + updateItemsPagination(); +} + +// 初始化商品搜索功能 +function initItemsSearch() { + // 初始化分页大小 + const pageSizeSelect = document.getElementById('itemsPageSize'); + if (pageSizeSelect) { + itemsPerPage = parseInt(pageSizeSelect.value) || 20; + pageSizeSelect.addEventListener('change', changeItemsPageSize); + } + + // 初始化搜索输入框事件监听器 + const searchInput = document.getElementById('itemSearchInput'); + if (searchInput) { + // 使用防抖来避免频繁搜索 + let searchTimeout; + searchInput.addEventListener('input', function() { + clearTimeout(searchTimeout); + searchTimeout = setTimeout(() => { + filterItems(); + }, 300); // 300ms 防抖延迟 + }); + } + + // 初始化页面输入框事件监听器 + const pageInput = document.getElementById('itemsPageInput'); + if (pageInput) { + pageInput.addEventListener('keydown', handleItemsPageInput); + } +} + // 刷新商品列表 async function refreshItems() { await refreshItemsData();