ErisPulse 2.3.0.dev5__tar.gz → 2.3.1__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 (142) hide show
  1. erispulse-2.3.1/.github/workflows/auto-tag-release.yml +95 -0
  2. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.gitignore +1 -0
  3. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/CHANGELOG.md +35 -0
  4. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/PKG-INFO +1 -1
  5. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/README.md +3 -0
  6. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/ai/AIDocs/ErisPulse-AdapterDev.md +1324 -468
  7. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/ai/AIDocs/ErisPulse-Full.md +1369 -503
  8. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/ai/AIDocs/ErisPulse-ModuleDev.md +617 -5
  9. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Bases/__init__.md +2 -2
  10. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Bases/adapter.md +2 -2
  11. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Bases/module.md +2 -2
  12. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/__init__.md +2 -2
  13. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/base.md +2 -2
  14. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/command.md +2 -2
  15. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/exceptions.md +2 -2
  16. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/message.md +2 -2
  17. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/meta.md +2 -2
  18. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/notice.md +2 -2
  19. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/Event/request.md +2 -2
  20. erispulse-2.3.0.dev5/docs/api/ErisPulse/Core/erispulse_config.md → erispulse-2.3.1/docs/api/ErisPulse/Core/_self_config.md +11 -3
  21. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/adapter.md +17 -8
  22. erispulse-2.3.1/docs/api/ErisPulse/Core/config.md +82 -0
  23. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/exceptions.md +2 -2
  24. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/lifecycle.md +2 -2
  25. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/logger.md +28 -4
  26. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/module.md +3 -3
  27. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/router.md +11 -2
  28. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/Core/storage.md +29 -3
  29. erispulse-2.3.1/docs/api/ErisPulse/Core/ux.md +101 -0
  30. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/api/ErisPulse/__init__.md +26 -124
  31. erispulse-2.3.1/docs/api/ErisPulse/__main__.md +30 -0
  32. erispulse-2.3.1/docs/api/ErisPulse/utils/__init__.md +16 -0
  33. erispulse-2.3.1/docs/api/ErisPulse/utils/cli.md +157 -0
  34. erispulse-2.3.0.dev5/docs/api/ErisPulse/__main__.md → erispulse-2.3.1/docs/api/ErisPulse/utils/package_manager.md +5 -211
  35. erispulse-2.3.1/docs/api/ErisPulse/utils/reload_handler.md +69 -0
  36. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/README.md +1 -0
  37. erispulse-2.3.1/docs/core/event-system.md +597 -0
  38. erispulse-2.3.1/docs/core/lazy-loading.md +261 -0
  39. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/modules.md +171 -13
  40. erispulse-2.3.1/docs/core/router.md +535 -0
  41. erispulse-2.3.1/docs/core/self-config.md +188 -0
  42. erispulse-2.3.1/examples/example-adapter/MyAdapter/Converter.py +38 -0
  43. erispulse-2.3.1/examples/example-adapter/MyAdapter/Core.py +141 -0
  44. erispulse-2.3.1/examples/example-adapter/MyAdapter/__init__.py +7 -0
  45. erispulse-2.3.1/examples/example-module/MyModule/Core.py +166 -0
  46. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/packages.json +22 -9
  47. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/pyproject.toml +2 -2
  48. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/_self_config.py +14 -2
  49. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/ux.py +4 -33
  50. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/__init__.py +154 -10
  51. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/utils/__init__.py +2 -0
  52. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/utils/cli.py +72 -82
  53. erispulse-2.3.1/src/ErisPulse/utils/console.py +53 -0
  54. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/utils/package_manager.py +1 -3
  55. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/utils/reload_handler.py +10 -34
  56. erispulse-2.3.0.dev5/.github/workflows/auto-tag-release.yml +0 -117
  57. erispulse-2.3.0.dev5/docs/api/ErisPulse/Core/config.md +0 -44
  58. erispulse-2.3.0.dev5/docs/core/event-system.md +0 -274
  59. erispulse-2.3.0.dev5/examples/example-adapter/MyAdapter/Core.py +0 -73
  60. erispulse-2.3.0.dev5/examples/example-adapter/MyAdapter/__init__.py +0 -5
  61. erispulse-2.3.0.dev5/examples/example-module/MyModule/Core.py +0 -90
  62. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  63. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/ISSUE_TEMPLATE/module_submission.md +0 -0
  64. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  65. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/assets/docs/install_pip.gif +0 -0
  66. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/assets/erispulse_logo.png +0 -0
  67. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/scripts/update_packages.py +0 -0
  68. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/tools/merge_md.py +0 -0
  69. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/tools/update-api-docs.py +0 -0
  70. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/workflows/auto-update-packages.yml +0 -0
  71. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/workflows/code-quality-check.yml +0 -0
  72. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.github/workflows/pypi-publish.yml +0 -0
  73. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/.python-version +0 -0
  74. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/CODE_OF_CONDUCT.md +0 -0
  75. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/CONTRIBUTING.md +0 -0
  76. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/LICENSE +0 -0
  77. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/README.md +0 -0
  78. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/SECURITY.md +0 -0
  79. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test.py +0 -0
  80. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_adapter.py +0 -0
  81. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_cmd.py +0 -0
  82. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_event.py +0 -0
  83. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_files/test.docx +0 -0
  84. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_files/test.jpg +0 -0
  85. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/devs/test_files/test.mp4 +0 -0
  86. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/ai/README.md +0 -0
  87. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/ai/module-generation.md +0 -0
  88. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/adapters.md +0 -0
  89. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/best-practices.md +0 -0
  90. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/cli.md +0 -0
  91. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/core/concepts.md +0 -0
  92. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/development/README.md +0 -0
  93. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/development/adapter.md +0 -0
  94. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/development/cli.md +0 -0
  95. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/development/module.md +0 -0
  96. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/README.md +0 -0
  97. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/email.md +0 -0
  98. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/maintain-notes.md +0 -0
  99. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/onebot11.md +0 -0
  100. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/telegram.md +0 -0
  101. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/platform-features/yunhu.md +0 -0
  102. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/quick-start.md +0 -0
  103. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/standards/README.md +0 -0
  104. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/standards/api-response.md +0 -0
  105. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/standards/event-conversion.md +0 -0
  106. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/styleguide/README.md +0 -0
  107. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/docs/styleguide/docstring_spec.md +0 -0
  108. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-adapter/LICENSE +0 -0
  109. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-adapter/README.md +0 -0
  110. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-adapter/pyproject.toml +0 -0
  111. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-cli-module/LICENSE +0 -0
  112. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-cli-module/README.md +0 -0
  113. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-cli-module/my_cli_module/__init__.py +0 -0
  114. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-cli-module/my_cli_module/cli.py +0 -0
  115. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-cli-module/pyproject.toml +0 -0
  116. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-module/LICENSE +0 -0
  117. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-module/MyModule/__init__.py +0 -0
  118. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-module/README.md +0 -0
  119. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/examples/example-module/pyproject.toml +0 -0
  120. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/scripts/install/install.ps1 +0 -0
  121. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/scripts/install/install.sh +0 -0
  122. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Bases/__init__.py +0 -0
  123. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Bases/adapter.py +0 -0
  124. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Bases/module.py +0 -0
  125. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/__init__.py +0 -0
  126. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/base.py +0 -0
  127. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/command.py +0 -0
  128. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/exceptions.py +0 -0
  129. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/message.py +0 -0
  130. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/meta.py +0 -0
  131. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/notice.py +0 -0
  132. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/Event/request.py +0 -0
  133. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/__init__.py +0 -0
  134. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/adapter.py +0 -0
  135. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/config.py +0 -0
  136. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/exceptions.py +0 -0
  137. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/lifecycle.py +0 -0
  138. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/logger.py +0 -0
  139. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/module.py +0 -0
  140. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/router.py +0 -0
  141. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/Core/storage.py +0 -0
  142. {erispulse-2.3.0.dev5 → erispulse-2.3.1}/src/ErisPulse/__main__.py +0 -0
@@ -0,0 +1,95 @@
1
+ name: 🎀 艾莉丝的版本标签魔法 ~
2
+
3
+ permissions:
4
+ contents: write
5
+
6
+ on:
7
+ push:
8
+ branches: [main, Pre-Release/v2]
9
+
10
+ jobs:
11
+ update-latest-release:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: 检出代码
15
+ uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+ token: ${{ secrets.GITHUB_TOKEN }}
19
+
20
+ - name: 施展版本魔法
21
+ env:
22
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23
+ shell: bash
24
+ run: |
25
+ # 读取当前版本
26
+ version=$(grep '^version' pyproject.toml | head -1 | sed 's/version = "//;s/"//')
27
+ tag_name="v$version"
28
+
29
+ echo "当前版本: $version"
30
+ echo "标签名称: $tag_name"
31
+
32
+ # 从 CHANGELOG.md 提取更新日志
33
+ if [ -f "CHANGELOG.md" ]; then
34
+ # 修复版本号格式:将 -de. 替换为 -dev.
35
+ fixed_version=$(echo "$version" | sed 's/-de\./-dev./g')
36
+
37
+ echo "尝试匹配版本: $version 或 $fixed_version"
38
+
39
+ # 使用 sed 提取版本更新日志
40
+ # 先尝试匹配原始版本号
41
+ changelog_section=$(sed -n "/^## \[$version\] -/,/^## \[.*\] -/p" CHANGELOG.md | sed '$d')
42
+
43
+ # 如果没找到,尝试匹配修复后的版本号
44
+ if [ -z "$changelog_section" ]; then
45
+ changelog_section=$(sed -n "/^## \[$fixed_version\] -/,/^## \[.*\] -/p" CHANGELOG.md | sed '$d')
46
+ fi
47
+
48
+ # 移除第一行(标题行)
49
+ if [ -n "$changelog_section" ]; then
50
+ changelog=$(echo "$changelog_section" | tail -n +2)
51
+
52
+ # 判断是否为开发版本
53
+ if [[ $version =~ dev|alpha|beta|pre|a|b ]]; then
54
+ is_dev="true"
55
+ latest_flag=""
56
+ else
57
+ is_dev="false"
58
+ latest_flag="--latest"
59
+ fi
60
+
61
+ # 检查标签是否已存在
62
+ if ! git rev-parse "$tag_name" >/dev/null 2>&1; then
63
+ echo "🎀🎀 创建新标签 $tag_name..."
64
+ git tag "$tag_name"
65
+ git push origin "$tag_name"
66
+ else
67
+ echo "标签 $tag_name 已存在"
68
+ fi
69
+
70
+ # 检查发行是否存在
71
+ if gh release view "$tag_name" &>/dev/null; then
72
+ # 更新发行
73
+ echo "🔄 更新发行 $tag_name..."
74
+ gh release edit "$tag_name" \
75
+ --notes "$changelog" \
76
+ --prerelease=$is_dev
77
+ echo "✅ 已更新发行 $tag_name"
78
+ else
79
+ # 创建发行
80
+ echo "✨ 创建发行 $tag_name..."
81
+ gh release create "$tag_name" \
82
+ --notes "$changelog" \
83
+ --title "✨ 艾莉丝的魔法更新 $tag_name" \
84
+ --prerelease=$is_dev \
85
+ $latest_flag
86
+ echo "✅ 已创建发行 $tag_name"
87
+ fi
88
+
89
+ echo "📦 发行页面: https://github.com/${{ github.repository }}/releases/tag/$tag_name"
90
+ else
91
+ echo "⚠️ 未找到版本 $version 的更新日志"
92
+ fi
93
+ else
94
+ echo "⚠️ CHANGELOG.md 文件不存在"
95
+ fi
@@ -213,3 +213,4 @@ my_bot
213
213
  modules
214
214
  config.toml
215
215
  devs/test_st.py
216
+ docs/ux-improvements.md
@@ -31,6 +31,41 @@
31
31
  - 具体功能点2
32
32
  ```
33
33
 
34
+ ## [2.3.1] - 2025/12/28
35
+ ### 修复
36
+ - @wsu2059q
37
+ - 修复 `ep-init` 命令使用 `init_task()` 导致协程未等待的问题
38
+ - 新增 `init_sync()` 同步包装器,用于命令行直接调用初始化功能
39
+
40
+ ---
41
+ ## [2.3.0] - 2025/12/25
42
+ ### 修复
43
+ - @wsu2059q
44
+ - 修复控制台颜色主题导入报错导致安装中断的问题
45
+
46
+ ---
47
+ ## [2.3.0-dev.6] - 2025/12/22
48
+ > 开发版本
49
+
50
+ ### 新增
51
+ - @wsu2059q
52
+ - 新增框架配置解析文档,包括框架的默认配置项及其含义
53
+ - 新增懒加载模块系统、路由管理器和事件系统文档
54
+ - 新增懒加载全局配置支持,允许通过配置文件控制是否使用懒加载
55
+
56
+ ### 变更
57
+ - @wsu2059q
58
+ - 优化懒加载模块初始化逻辑,支持同步初始化和异步初始化分离
59
+ - 新增 `_initialize_sync()` 方法,用于在异步上下文中进行同步调用
60
+ - 新增 `_complete_async_init()` 方法,用于完成异步初始化部分
61
+ - 优化CLI资源清理逻辑:
62
+ - 分离适配器和模块清理逻辑
63
+
64
+ ### 修复
65
+ - @wsu2059q
66
+ - 修复懒加载模块在异步上下文中初始化可能出现的问题
67
+ - 修复配置系统中的缓存一致性检查问题
68
+
34
69
  ---
35
70
  ## [2.3.0-dev.5] - 2025/12/21
36
71
  > 开发版本
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 2.3.0.dev5
3
+ Version: 2.3.1
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>
6
6
  License: MIT License
@@ -20,6 +20,9 @@
20
20
  - [核心模块](core/modules.md) - 存储、配置、日志等核心组件详解
21
21
  - [适配器系统](core/adapters.md) - 平台适配器的使用和开发
22
22
  - [事件系统](core/event-system.md) - Event 模块的使用(事件监听、事件处理、事件分发)
23
+ - [懒加载模块系统](core/lazy-loading.md) - 懒加载模块系统的使用和配置
24
+ - [路由管理器](core/router.md) - HTTP和WebSocket路由管理
25
+ - [框架配置](core/self-config.md) - 框架默认配置说明
23
26
  - [最佳实践](core/best-practices.md) - 开发和部署建议
24
27
 
25
28
  ### 开发指南