20250904-初步功能已完成

This commit is contained in:
2025-09-11 18:55:35 +08:00
parent a2287b47d5
commit a408a01110
3 changed files with 137 additions and 110 deletions

47
.idea/workspace.xml generated
View File

@@ -4,12 +4,7 @@
<option name="autoReloadType" value="SELECTIVE" /> <option name="autoReloadType" value="SELECTIVE" />
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成"> <list default="true" id="eceeff5e-51c1-459c-a911-d21ec090a423" name="Changes" comment="20250904-初步功能已完成" />
<change afterPath="$PROJECT_DIR$/123.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/data/abc.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Utils/AiUtils.py" beforeDir="false" afterPath="$PROJECT_DIR$/Utils/AiUtils.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -95,7 +90,30 @@
<visibility group="运行配置" flag="true" /> <visibility group="运行配置" flag="true" />
</myKeys> </myKeys>
</component> </component>
<component name="RunManager" selected="Python.123"> <component name="RunManager" selected="Python.12">
<configuration name="12" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="iOSAI" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/12.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<configuration name="123" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true"> <configuration name="123" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="iOSAI" /> <module name="iOSAI" />
<option name="ENV_FILES" value="" /> <option name="ENV_FILES" value="" />
@@ -144,6 +162,7 @@
</configuration> </configuration>
<recent_temporary> <recent_temporary>
<list> <list>
<item itemvalue="Python.12" />
<item itemvalue="Python.123" /> <item itemvalue="Python.123" />
</list> </list>
</recent_temporary> </recent_temporary>
@@ -216,7 +235,7 @@
<workItem from="1757480739367" duration="14580000" /> <workItem from="1757480739367" duration="14580000" />
<workItem from="1757498954175" duration="6736000" /> <workItem from="1757498954175" duration="6736000" />
<workItem from="1757506636968" duration="5910000" /> <workItem from="1757506636968" duration="5910000" />
<workItem from="1757567423145" duration="16343000" /> <workItem from="1757567423145" duration="16668000" />
</task> </task>
<task id="LOCAL-00001" summary="ai 开始测试"> <task id="LOCAL-00001" summary="ai 开始测试">
<option name="closed" value="true" /> <option name="closed" value="true" />
@@ -250,7 +269,15 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1757513848107</updated> <updated>1757513848107</updated>
</task> </task>
<option name="localTasksCounter" value="5" /> <task id="LOCAL-00005" summary="20250904-初步功能已完成">
<option name="closed" value="true" />
<created>1757587781103</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1757587781103</updated>
</task>
<option name="localTasksCounter" value="6" />
<servers /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
@@ -286,7 +313,7 @@
<SUITE FILE_PATH="coverage/iOSAI$mac_wda_agent.coverage" NAME="mac_wda_agent Coverage Results" MODIFIED="1756473148639" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" /> <SUITE FILE_PATH="coverage/iOSAI$mac_wda_agent.coverage" NAME="mac_wda_agent Coverage Results" MODIFIED="1756473148639" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
<SUITE FILE_PATH="coverage/iOSAI$ScriptManager.coverage" NAME="ScriptManager 覆盖结果" MODIFIED="1756896057801" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" /> <SUITE FILE_PATH="coverage/iOSAI$ScriptManager.coverage" NAME="ScriptManager 覆盖结果" MODIFIED="1756896057801" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/script" />
<SUITE FILE_PATH="coverage/iOSAI$Main.coverage" NAME="Main 覆盖结果" MODIFIED="1757579400023" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" /> <SUITE FILE_PATH="coverage/iOSAI$Main.coverage" NAME="Main 覆盖结果" MODIFIED="1757579400023" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
<SUITE FILE_PATH="coverage/iOSAI$123.coverage" NAME="123 覆盖结果" MODIFIED="1757587517556" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" /> <SUITE FILE_PATH="coverage/iOSAI$123.coverage" NAME="123 覆盖结果" MODIFIED="1757587713569" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
<SUITE FILE_PATH="coverage/iOSAI$2111.coverage" NAME="2111 覆盖结果" MODIFIED="1757330714370" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" /> <SUITE FILE_PATH="coverage/iOSAI$2111.coverage" NAME="2111 覆盖结果" MODIFIED="1757330714370" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
</component> </component>
</project> </project>

View File

@@ -710,103 +710,3 @@ class AiUtils(object):
except Exception as e: except Exception as e:
LogManager.error(f"[delete_anchors_by_ids] 写入失败: {e}") LogManager.error(f"[delete_anchors_by_ids] 写入失败: {e}")
return deleted return deleted
@staticmethod
def _get_data_path(filename: str) -> str:
"""
根据文件名生成 data 目录下的完整路径
"""
base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 当前项目根目录
data_dir = os.path.join(base_dir, "data")
Path(data_dir).mkdir(parents=True, exist_ok=True) # 确保 data 目录存在
return os.path.join(data_dir, filename)
@staticmethod
def read_json(filename: str) -> dict:
"""
读取 JSON 文件,返回字典
如果文件不存在,返回空字典
"""
file_path = AiUtils._get_data_path(filename)
try:
if not os.path.exists(file_path):
return {}
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data if isinstance(data, dict) else {}
except Exception as e:
print(f"读取 JSON 文件失败: {e}")
return {}
@staticmethod
def write_json(filename: str, data: dict, overwrite: bool = True) -> bool:
"""
将字典写入 JSON 文件
:param filename: 文件名(自动放在 data 目录下)
:param data: 要写入的字典
:param overwrite: True=覆盖写False=合并更新
"""
file_path = AiUtils._get_data_path(filename)
try:
if not overwrite and os.path.exists(file_path):
# 读取旧数据
with open(file_path, "r", encoding="utf-8") as f:
old_data = json.load(f)
if not isinstance(old_data, dict):
old_data = {}
# 合并
old_data.update(data)
data = old_data
# 覆盖写(写回最终的 data
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
return True
except Exception as e:
print(f"写入 JSON 文件失败: {e}")
return False
@staticmethod
def update_json(filename: str, new_data: dict) -> bool:
"""
修改 JSON 文件:
- 如果 key 已存在,则修改其值
- 如果 key 不存在,则新增
"""
try:
# 读取旧数据(没有则为空字典)
data = AiUtils.read_json(filename)
if not isinstance(data, dict):
data = {}
# 合并(有则修改,无则新增)
data.update(new_data)
# 写回
return AiUtils.write_json(filename, data)
except Exception as e:
print(f"更新 JSON 文件失败: {e}")
return False
@staticmethod
def delete_json_key(filename: str, key: str) -> bool:
"""
删除 JSON 文件中的某个 key
- 如果 key 存在则删除
- 如果 key 不存在则不处理
"""
try:
# 读取旧数据
data = AiUtils.read_json(filename)
if not isinstance(data, dict):
data = {}
# 删除指定 key
if key in data:
del data[key]
# 写回文件
return AiUtils.write_json(filename, data)
except Exception as e:
print(f"删除 JSON key 失败: {e}")
return False

100
Utils/JsonUtils.py Normal file
View File

@@ -0,0 +1,100 @@
import os
import json
from pathlib import Path
class JsonUtils:
@staticmethod
def _normalize_filename(filename: str) -> str:
"""
确保文件名以 .json 结尾
"""
if not filename.endswith(".json"):
filename = f"{filename}.json"
return filename
@staticmethod
def _get_data_path(filename: str) -> str:
"""
根据文件名生成 data 目录下的完整路径
"""
filename = JsonUtils._normalize_filename(filename)
base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) # 当前项目根目录
data_dir = os.path.join(base_dir, "data")
Path(data_dir).mkdir(parents=True, exist_ok=True) # 确保 data 目录存在
return os.path.join(data_dir, filename)
@staticmethod
def read_json(filename: str) -> dict:
"""
读取 JSON 文件,返回字典
如果文件不存在,返回空字典
"""
file_path = JsonUtils._get_data_path(filename)
try:
if not os.path.exists(file_path):
return {}
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
return data if isinstance(data, dict) else {}
except Exception as e:
print(f"读取 JSON 文件失败: {e}")
return {}
@staticmethod
def write_json(filename: str, data: dict, overwrite: bool = True) -> bool:
"""
将字典写入 JSON 文件
:param filename: 文件名(不用写后缀,自动补 .json
:param data: 要写入的字典
:param overwrite: True=覆盖写False=合并更新
"""
file_path = JsonUtils._get_data_path(filename)
try:
if not overwrite and os.path.exists(file_path):
with open(file_path, "r", encoding="utf-8") as f:
old_data = json.load(f)
if not isinstance(old_data, dict):
old_data = {}
old_data.update(data)
data = old_data
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=4)
return True
except Exception as e:
print(f"写入 JSON 文件失败: {e}")
return False
@staticmethod
def update_json(filename: str, new_data: dict) -> bool:
"""
修改 JSON 文件:
- 如果 key 已存在,则修改其值
- 如果 key 不存在,则新增
"""
try:
data = JsonUtils.read_json(filename)
if not isinstance(data, dict):
data = {}
data.update(new_data)
return JsonUtils.write_json(filename, data)
except Exception as e:
print(f"更新 JSON 文件失败: {e}")
return False
@staticmethod
def delete_json_key(filename: str, key: str) -> bool:
"""
删除 JSON 文件中的某个 key
"""
try:
data = JsonUtils.read_json(filename)
if not isinstance(data, dict):
data = {}
if key in data:
del data[key]
return JsonUtils.write_json(filename, data)
except Exception as e:
print(f"删除 JSON key 失败: {e}")
return False