lkd-pro 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. lkd_pro-0.2.0/PKG-INFO +644 -0
  2. lkd_pro-0.2.0/README.md +607 -0
  3. lkd_pro-0.2.0/lkd/__init__.py +39 -0
  4. lkd_pro-0.2.0/lkd/api/__init__.py +68 -0
  5. lkd_pro-0.2.0/lkd/api/api.py +889 -0
  6. lkd_pro-0.2.0/lkd/cache/__init__.py +9 -0
  7. lkd_pro-0.2.0/lkd/cache/local_cache.py +173 -0
  8. lkd_pro-0.2.0/lkd/client/__init__.py +25 -0
  9. lkd_pro-0.2.0/lkd/client/client.py +201 -0
  10. lkd_pro-0.2.0/lkd/client/request_base.py +93 -0
  11. lkd_pro-0.2.0/lkd/client/request_delete.py +9 -0
  12. lkd_pro-0.2.0/lkd/client/request_params.py +9 -0
  13. lkd_pro-0.2.0/lkd/client/request_patch.py +9 -0
  14. lkd_pro-0.2.0/lkd/client/request_post.py +9 -0
  15. lkd_pro-0.2.0/lkd/client/request_put.py +9 -0
  16. lkd_pro-0.2.0/lkd/env/__init__.py +9 -0
  17. lkd_pro-0.2.0/lkd/env/auto_client.py +325 -0
  18. lkd_pro-0.2.0/lkd/env/device_info.py +160 -0
  19. lkd_pro-0.2.0/lkd/human/__init__.py +0 -0
  20. lkd_pro-0.2.0/lkd/human/human.py +740 -0
  21. lkd_pro-0.2.0/lkd/logs/__init__.py +132 -0
  22. lkd_pro-0.2.0/lkd/logs/err_logs.py +137 -0
  23. lkd_pro-0.2.0/lkd/mwin/__init__.py +0 -0
  24. lkd_pro-0.2.0/lkd/mwin/find_image.py +310 -0
  25. lkd_pro-0.2.0/lkd/mwin/mbot.py +1140 -0
  26. lkd_pro-0.2.0/lkd/py.typed +0 -0
  27. lkd_pro-0.2.0/lkd/settings/__init__.py +10 -0
  28. lkd_pro-0.2.0/lkd/settings/initialization.py +140 -0
  29. lkd_pro-0.2.0/lkd/settings/settings.py +138 -0
  30. lkd_pro-0.2.0/lkd/util/__init__.py +0 -0
  31. lkd_pro-0.2.0/lkd/util/file/__init__.py +0 -0
  32. lkd_pro-0.2.0/lkd/util/file/file.py +211 -0
  33. lkd_pro-0.2.0/lkd/util/file/folder.py +117 -0
  34. lkd_pro-0.2.0/lkd/util/file/mjson.py +48 -0
  35. lkd_pro-0.2.0/lkd/util/file/path.py +247 -0
  36. lkd_pro-0.2.0/lkd/util/network.py +79 -0
  37. lkd_pro-0.2.0/lkd/util/up_c.py +736 -0
  38. lkd_pro-0.2.0/lkd/util/util.py +598 -0
  39. lkd_pro-0.2.0/lkd/var/__init__.py +9 -0
  40. lkd_pro-0.2.0/lkd/var/variables.py +48 -0
  41. lkd_pro-0.2.0/lkd_pro.egg-info/PKG-INFO +644 -0
  42. lkd_pro-0.2.0/lkd_pro.egg-info/SOURCES.txt +46 -0
  43. lkd_pro-0.2.0/lkd_pro.egg-info/dependency_links.txt +1 -0
  44. lkd_pro-0.2.0/lkd_pro.egg-info/not-zip-safe +1 -0
  45. lkd_pro-0.2.0/lkd_pro.egg-info/requires.txt +9 -0
  46. lkd_pro-0.2.0/lkd_pro.egg-info/top_level.txt +1 -0
  47. lkd_pro-0.2.0/setup.cfg +4 -0
  48. lkd_pro-0.2.0/setup.py +55 -0
lkd_pro-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,644 @@
1
+ Metadata-Version: 2.4
2
+ Name: lkd_pro
3
+ Version: 0.2.0
4
+ Summary: 自动注册和认证
5
+ Home-page: https://github.com/songhang/lkddb_pro
6
+ Author: songhang
7
+ Author-email: 1026536804@qq.com
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: pywin32>=311
20
+ Requires-Dist: Pillow>=10.0.0
21
+ Requires-Dist: requests>=2.32.0
22
+ Requires-Dist: cachetools>=5.0.0
23
+ Requires-Dist: pandas>=2.0.0
24
+ Requires-Dist: openpyxl>=3.1.0
25
+ Requires-Dist: psutil>=5.9.0
26
+ Requires-Dist: opencv-python>=4.8.0
27
+ Requires-Dist: pydirectinput>=1.0.4
28
+ Dynamic: author
29
+ Dynamic: author-email
30
+ Dynamic: classifier
31
+ Dynamic: description
32
+ Dynamic: description-content-type
33
+ Dynamic: home-page
34
+ Dynamic: requires-dist
35
+ Dynamic: requires-python
36
+ Dynamic: summary
37
+
38
+ # LKD Python SDK
39
+
40
+ [![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://pypi.org/project/lkd/)
41
+ [![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
42
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
43
+
44
+ ## 📖 项目简介
45
+
46
+ LKD 是电商商品数据处理与自动化上传系统。提供 Excel 表格与图片批量匹配、数据清洗、API 上传、错误日志异步上报等一站式解决方案,帮助电商企业高效管理商品数据。
47
+
48
+ ### 核心特性
49
+
50
+ - 🔐 **自动认证**: Token 自动刷新、设备心跳维护
51
+ - 💾 **本地缓存**: 内存 + 文件双重缓存,支持持久化存储
52
+
53
+ ---
54
+
55
+ ## 📦 快速开始
56
+
57
+ ### 1. 安装依赖
58
+
59
+ ```bash
60
+ pip install -r requirements.txt
61
+ ```
62
+
63
+ 或使用 pip 安装(如已发布):
64
+
65
+ ```bash
66
+ pip install lkd
67
+ ```
68
+
69
+ ### 2. 初始化配置
70
+
71
+ 在使用 LKD 模块前,需要先初始化全局变量和 IP 配置:
72
+
73
+ ```python
74
+ from lkd.var.variables import glv
75
+ from lkd.settings.initialization import default as init_default
76
+
77
+ # 设置服务器 IP(必须在最前面)
78
+ glv.set("LOCAL_IP", "192.168.2.28:8000") # 本地服务器
79
+ # glv.set("REMOTE_IP", "your.remote.ip") # 远程服务器(可选)
80
+
81
+ # 执行完整初始化流程
82
+ success = init_default()
83
+ if success:
84
+ print("LKD 初始化完成")
85
+ ```
86
+
87
+ ### 3. 使用示例
88
+
89
+ #### 用户认证
90
+
91
+ ```python
92
+ from lkd.api import login, register
93
+
94
+ # 登录(密码默认使用设备 ID 后 6 位)
95
+ result = login("your_password")
96
+ if result["success"]:
97
+ print("登录成功")
98
+ access_token = result["data"]["access_token"]
99
+ else:
100
+ # 登录失败可尝试注册
101
+ register_result = register("your_password")
102
+ ```
103
+
104
+ #### 商品上传
105
+
106
+ ```python
107
+ from lkd.api import send_products
108
+
109
+ product_data = {
110
+ "title": "商品名称",
111
+ "price": 99.99,
112
+ "stock": 100,
113
+ "shop_id": "shop_001",
114
+ }
115
+
116
+ result = send_products(product_data)
117
+ if result["success"]:
118
+ print("商品上传成功")
119
+ else:
120
+ print(f"上传失败:{result['error']}")
121
+ ```
122
+
123
+ #### 获取任务列表
124
+
125
+ ```python
126
+ from lkd.api import get_task
127
+
128
+ result = get_task(status="pending", limit=10)
129
+ if result["success"]:
130
+ tasks = result["data"]["tasks"]
131
+ for task in tasks:
132
+ print(f"任务 ID: {task['id']}, 状态:{task['status']}")
133
+ ```
134
+
135
+ #### 错误日志上报
136
+
137
+ ```python
138
+ from lkd.logs.err_logs import send_logs
139
+
140
+ send_logs(
141
+ task="task_001",
142
+ error_message="商品上传失败:库存不足",
143
+ screenshot_path="error.png"
144
+ )
145
+ ```
146
+
147
+ #### 发送设备心跳
148
+
149
+ ```python
150
+ from lkd.api import send_heartbeat
151
+ import datetime
152
+
153
+ start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
154
+ result = send_heartbeat(
155
+ start_heartbeat=start_time,
156
+ access_token="your_access_token",
157
+ ref_token="your_refresh_token",
158
+ status=1 # 1=空闲,2=工作中
159
+ )
160
+ ```
161
+
162
+ ---
163
+
164
+ ## 📁 目录结构
165
+
166
+ ```
167
+ lkd/
168
+ ├── api/ # API 接口与数据上传
169
+ │ ├── __init__.py
170
+ │ └── api.py # 所有 API 接口封装
171
+ ├── cache/ # 缓存管理
172
+ │ ├── __init__.py
173
+ │ └── local_cache.py # 本地缓存与文件缓存
174
+ ├── client/ # HTTP 客户端
175
+ │ ├── __init__.py
176
+ │ ├── client.py # 请求客户端 (CPRequest)
177
+ │ └── request_*.py # 请求对象封装 (BaseRequest 子类)
178
+ ├── env/ # 环境与设备信息
179
+ │ ├── __init__.py
180
+ │ └── device_info.py # 设备唯一标识生成
181
+ ├── human/ # 人工交互工具
182
+ ├── logs/ # 日志系统
183
+ │ ├── __init__.py # 日志配置
184
+ │ └── err_logs.py # 错误日志上报
185
+ ├── mwin/ # Windows 自动化
186
+ ├── settings/ # 配置管理
187
+ │ ├── __init__.py
188
+ │ ├── settings.py # 系统配置 (单例模式)
189
+ │ └── initialization.py # 初始化流程
190
+ ├── util/ # 通用工具
191
+ │ ├── file/ # 文件操作工具
192
+ │ │ ├── file.py # 文件管理
193
+ │ │ ├── folder.py # 文件夹管理
194
+ │ │ └── path.py # 路径管理
195
+ │ └── up_c.py # Excel 上传主流程
196
+ ├── var/ # 全局变量管理
197
+ │ └── variables.py # GlobalVariables 单例
198
+ ├── __init__.py # 包入口
199
+ └── test.py # 测试与初始化工具
200
+ ```
201
+
202
+ ---
203
+
204
+ ## 🔧 架构规范
205
+
206
+ ### 设计模式
207
+
208
+ #### 单例模式
209
+
210
+ 核心模块必须使用单例模式,确保全局唯一实例:
211
+
212
+ - `Settings` - 系统配置管理器
213
+ - `GlobalVariables` - 全局变量管理器
214
+ - `CacheManager` - 缓存管理器
215
+ - `DeviceInfo` - 设备信息生成器
216
+
217
+ ```python
218
+ # Settings 使用示例
219
+ from lkd.settings import get_settings
220
+
221
+ settings = get_settings() # 始终返回同一实例
222
+ host_url = settings.host_url
223
+ ```
224
+
225
+ #### 延迟导入
226
+
227
+ 解决循环依赖问题,在方法内部动态导入:
228
+
229
+ ```python
230
+ def _get_api_module():
231
+ """延迟导入 API 模块,避免循环依赖"""
232
+ from lkd.api import api
233
+ return api
234
+ ```
235
+
236
+ ### 代码规范
237
+
238
+ #### 类型注解
239
+
240
+ 所有公共 API 必须包含完整的类型注解:
241
+
242
+ ```python
243
+ from typing import Dict, Any, Optional
244
+
245
+ def login(password: str) -> Dict[str, Any]:
246
+ """
247
+ 用户登录
248
+
249
+ Args:
250
+ password: 用户密码
251
+
252
+ Returns:
253
+ 登录结果字典
254
+ """
255
+ pass
256
+ ```
257
+
258
+ #### 请求类继承
259
+
260
+ 所有 HTTP 请求类必须继承自 `BaseRequest` 抽象基类:
261
+
262
+ ```python
263
+ from lkd.client.request_base import BaseRequest
264
+
265
+ class RequestPost(BaseRequest):
266
+ def __init__(self, request_url: str) -> None:
267
+ super().__init__(method="POST", request_url=request_url)
268
+ ```
269
+
270
+ ### 安全规范
271
+
272
+ #### 线程安全
273
+
274
+ 共享状态访问必须加锁:
275
+
276
+ ```python
277
+ import threading
278
+
279
+ class CacheManager:
280
+ def __init__(self) -> None:
281
+ self._cache: Dict[str, Any] = {}
282
+ self._lock = threading.Lock()
283
+
284
+ def set(self, key: str, value: Any) -> None:
285
+ with self._lock:
286
+ self._cache[key] = value
287
+ ```
288
+
289
+ #### 上下文管理器
290
+
291
+ 文件/网络操作必须使用上下文管理器:
292
+
293
+ ```python
294
+ def read_file(path: str) -> Optional[str]:
295
+ try:
296
+ with open(path, "r", encoding="utf-8") as f:
297
+ return f.read()
298
+ except Exception as e:
299
+ log_error(f"读取文件失败:{e}")
300
+ return None
301
+ ```
302
+
303
+ ### 容错机制
304
+
305
+ #### 多级降级策略
306
+
307
+ 密码初始化等关键流程必须实现多级降级:
308
+
309
+ ```python
310
+ def _init_password(self) -> None:
311
+ # 优先使用设备 ID 生成的密码
312
+ device_pwd = _get_pwd_from_device()
313
+ if device_pwd:
314
+ self._password = device_pwd
315
+ return
316
+
317
+ # 尝试从缓存获取
318
+ cached_pwd = CACHE.get("pwd", "")
319
+ if cached_pwd:
320
+ self._password = cached_pwd
321
+ return
322
+
323
+ # 生成新密码并保存
324
+ self._password = random_pwd()
325
+ CACHE["pwd"] = self._password
326
+ ```
327
+
328
+ #### 异常处理
329
+
330
+ 认证/注册/心跳流程必须包裹在 try-except 块中:
331
+
332
+ ```python
333
+ try:
334
+ result = api_client.send_heartbeat(...)
335
+ if result["success"]:
336
+ log_print("心跳发送成功")
337
+ except Exception as e:
338
+ log_error(f"心跳发送异常:{e}")
339
+ ```
340
+
341
+ ### 路径规范
342
+
343
+ 文件路径获取必须实现多层降级策略:
344
+
345
+ ```python
346
+ def get_documents_path(self) -> str:
347
+ """获取文档路径(带降级策略)"""
348
+ try:
349
+ # 尝试访问 Documents 目录
350
+ path = get_known_folder_path("Documents")
351
+ if path:
352
+ return os.path.join(path, "0_mt")
353
+ except Exception:
354
+ pass
355
+
356
+ try:
357
+ # 降级到 APPDATA
358
+ path = os.getenv("APPDATA")
359
+ if path:
360
+ return os.path.join(path, "0_mt")
361
+ except Exception:
362
+ pass
363
+
364
+ # 最终降级到临时目录
365
+ return tempfile.gettempdir()
366
+ ```
367
+
368
+ ### 配置加载规范
369
+
370
+ `Settings.host_url` 必须实现动态检查机制,每次访问时自动从 `glv` 重新读取 IP 配置:
371
+
372
+ ```python
373
+ @property
374
+ def host_url(self) -> str:
375
+ """API 主机 URL(动态获取)"""
376
+ # 如果当前 host_url 为空,尝试重新从 glv 加载
377
+ if not self._host_url:
378
+ self._local_ip = glv.get("LOCAL_IP", "")
379
+ self._remote_ip = glv.get("REMOTE_IP", "")
380
+ self._host_url = self._build_host_url()
381
+ return self._host_url
382
+ ```
383
+
384
+ ---
385
+
386
+ ## 📚 主要模块说明
387
+
388
+ ### API 模块 (`lkd.api`)
389
+
390
+ 提供完整的后端 API 接口封装:
391
+
392
+ #### 认证相关
393
+
394
+ - `register(password: str)` - 用户注册
395
+ - `login(password: str)` - 用户登录
396
+ - `refresh_token(ref_token: str, app_name: str)` - 刷新 Token
397
+
398
+ #### 设备管理
399
+
400
+ - `register_device(access_token, ref_token, **kwargs)` - 注册或更新设备
401
+ - `send_heartbeat(start_heartbeat, access_token, ref_token, status, **kwargs)` - 发送心跳
402
+
403
+ #### 任务管理
404
+
405
+ - `get_task(**kwargs)` - 获取任务列表
406
+ - `update_task(id, **kwargs)` - 更新任务
407
+ - `logs(task_id, log_content, screenshot)` - 发送任务日志
408
+
409
+ #### 商品管理
410
+
411
+ - `send_products(data)` - 发送商品信息
412
+ - `get_products(**kwargs)` - 查询商品信息
413
+
414
+ #### 店铺管理
415
+
416
+ - `get_shop(shop_id, **kwargs)` - 获取店铺信息
417
+ - `update_shop(shop_id, **kwargs)` - 更新店铺信息
418
+ - `get_second_categories(**kwargs)` - 获取二级类目
419
+ - `create_or_update_second(**kwargs)` - 创建/更新二级类目
420
+
421
+ #### 采购管理
422
+
423
+ - `get_purchase(**kwargs)` - 获取拼多多采购信息
424
+ - `post_purchase(**kwargs)` - 采购 PDD 商品
425
+ - `put_purchase(**kwargs)` - 更新采购信息
426
+
427
+ #### 绑定关系
428
+
429
+ - `query_pdd_bind_products(**kwargs)` - 查询商品绑定关系
430
+ - `update_pdd_bind_product(id, **kwargs)` - 更新绑定关系
431
+
432
+ ### 缓存模块 (`lkd.cache`)
433
+
434
+ ```python
435
+ from lkd.cache import CACHE, FileCache
436
+
437
+ # 内存缓存(字典式访问)
438
+ CACHE["key"] = "value"
439
+ value = CACHE["key"]
440
+
441
+ # 或使用标准方法
442
+ CACHE.set("key", "value")
443
+ value = CACHE.get("key")
444
+
445
+ # 文件缓存(持久化)
446
+ file_cache = FileCache("/path/to/cache")
447
+ file_cache.start_background_save() # 启动后台自动保存
448
+ ```
449
+
450
+ ### 日志模块 (`lkd.logs`)
451
+
452
+ ```python
453
+ from lkd.logs import log_print, log_error, log_warning, set_log_dir
454
+
455
+ # 设置日志目录
456
+ set_log_dir("/path/to/logs")
457
+
458
+ # 记录日志
459
+ log_print("普通信息") # INFO 级别
460
+ log_error("错误信息") # ERROR 级别
461
+ log_warning("警告信息") # WARNING 级别
462
+ ```
463
+
464
+ ### 全局变量模块 (`lkd.var`)
465
+
466
+ ```python
467
+ from lkd.var.variables import glv
468
+
469
+ # 设置变量
470
+ glv.set("LOCAL_IP", "192.168.2.28:8000")
471
+ glv.set("gvar_task_path", "/path/to/tasks")
472
+
473
+ # 获取变量
474
+ local_ip = glv.get("LOCAL_IP")
475
+ task_path = glv.get("gvar_task_path")
476
+
477
+ # 检查是否存在
478
+ if glv.has("LOCAL_IP"):
479
+ print("IP 已配置")
480
+ ```
481
+
482
+ ---
483
+
484
+ ## ⚙️ 配置说明
485
+
486
+ ### IP 配置
487
+
488
+ ```python
489
+ from lkd.var.variables import glv
490
+
491
+ # 本地服务器(优先使用)
492
+ glv.set("LOCAL_IP", "192.168.2.28:8000")
493
+
494
+ # 远程服务器(备用)
495
+ glv.set("REMOTE_IP", "your.remote.ip:port")
496
+
497
+ # Settings 会自动选择 LOCAL_IP(如果存在),否则使用 REMOTE_IP
498
+ # 并构建完整的 URL: http://{ip}/api
499
+ ```
500
+
501
+ ### 路径配置
502
+
503
+ ```python
504
+ from lkd.var.variables import glv
505
+
506
+ # 配置关键路径
507
+ glv.set("gvar_config_path", "/path/to/config")
508
+ glv.set("gvar_task_path", "/path/to/tasks")
509
+ glv.set("gvar_img_path", "/path/to/images")
510
+ glv.set("gvar_logs_path", "/path/to/logs")
511
+ glv.set("gvar_export_path", "/path/to/export")
512
+ ```
513
+
514
+ ### 自动认证客户端
515
+
516
+ ```python
517
+ from lkd.env.auto_client import AutoClient
518
+
519
+ # 创建自动连接客户端
520
+ auto_client = AutoClient(app_name="solider")
521
+
522
+ # 启动心跳
523
+ auto_client.run()
524
+
525
+ # 客户端会自动处理:
526
+ # 1. Token 检查和刷新
527
+ # 2. 登录/注册
528
+ # 3. 设备注册
529
+ # 4. 定时心跳发送
530
+ ```
531
+
532
+ ---
533
+
534
+ ## ⚠️ 注意事项
535
+
536
+ 1. **初始化顺序**: 必须先设置 IP 配置 (`LOCAL_IP`/`REMOTE_IP`),再执行其他操作
537
+ 2. **Excel 格式规范**: 确保 Excel 表格格式规范,列名与配置一致
538
+ 3. **图片命名**: 图片文件夹命名需与 Excel 表格对应
539
+ 4. **权限要求**: Windows 自动化功能需要相应系统权限
540
+ 5. **Python 版本**: 需要 Python 3.8 或更高版本
541
+ 6. **线程安全**: 多线程环境下请使用锁机制保护共享状态
542
+
543
+ ---
544
+
545
+ ## 🔍 常见问题
546
+
547
+ ### Q: 如何修改 API 服务器地址?
548
+
549
+ A: 通过全局变量配置(必须在初始化前设置):
550
+
551
+ ```python
552
+ from lkd.var.variables import glv
553
+ glv.set("LOCAL_IP", "new.server.ip:port")
554
+ ```
555
+
556
+ ### Q: 日志文件在哪里?
557
+
558
+ A: 默认位于初始化时配置的 `gvar_logs_path` 目录,可通过 `set_log_dir()` 自定义。
559
+
560
+ ### Q: 如何处理大量商品上传?
561
+
562
+ A: 使用 `ExcelUploader` 类,支持并发上传:
563
+
564
+ ```python
565
+ from lkd.util.up_c import ExcelUploader
566
+
567
+ uploader = ExcelUploader(
568
+ excel_path="products.xlsx",
569
+ shop_name="店铺名称",
570
+ max_workers=10 # 并发数
571
+ )
572
+ uploader.run()
573
+ ```
574
+
575
+ ### Q: Token 过期了怎么办?
576
+
577
+ A: 使用 `AutoClient` 会自动处理 Token 刷新。手动刷新可使用:
578
+
579
+ ```python
580
+ from lkd.api import refresh_token
581
+
582
+ result = refresh_token(
583
+ ref_token="your_refresh_token",
584
+ app_name="solider"
585
+ )
586
+ ```
587
+
588
+ ### Q: 设备心跳如何发送?
589
+
590
+ A: 推荐使用 `AutoClient` 自动发送,或手动调用:
591
+
592
+ ```python
593
+ from lkd.api import send_heartbeat
594
+ import datetime
595
+
596
+ result = send_heartbeat(
597
+ start_heartbeat=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
598
+ access_token="your_access_token",
599
+ ref_token="your_refresh_token",
600
+ status=1
601
+ )
602
+ ```
603
+
604
+ ---
605
+
606
+ ## 📝 更新日志
607
+
608
+ 详见 [CHANGELOG.md](CHANGELOG.md) 和 [版本日志.txt](版本日志.txt)
609
+
610
+ ### v0.2.0 (2026-04-02)
611
+
612
+ - ✅ 修复 Settings 动态加载 IP 配置问题
613
+ - ✅ 优化心跳 URL 拼接逻辑
614
+ - ✅ 增强缓存模块线程安全性
615
+ - ✅ 改进路径降级策略
616
+
617
+ ---
618
+
619
+ ## 🤝 贡献指南
620
+
621
+ 欢迎提交 Issue 和 Pull Request!贡献代码请遵循以下规范:
622
+
623
+ 1. 所有公共 API 必须包含完整 docstring
624
+ 2. 保持类型注解风格一致
625
+ 3. 关键流程必须包含异常处理
626
+ 4. 新增功能需补充测试用例
627
+
628
+ ---
629
+
630
+ ## 📄 许可证
631
+
632
+ MIT License
633
+
634
+ ---
635
+
636
+ ## 📧 联系方式
637
+
638
+ 技术支持:请联系项目维护者
639
+
640
+ ---
641
+
642
+ **最后更新**: 2026-04-02
643
+ **版本**: 0.2.0
644
+ **作者**: 松涵