LumAPI 1.1.0__tar.gz → 1.1.2__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.
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI/lumapi.py +94 -40
- {lumapi-1.1.0 → lumapi-1.1.2/LumAPI.egg-info}/PKG-INFO +15 -8
- {lumapi-1.1.0/LumAPI.egg-info → lumapi-1.1.2}/PKG-INFO +15 -8
- {lumapi-1.1.0 → lumapi-1.1.2}/README.md +14 -7
- {lumapi-1.1.0 → lumapi-1.1.2}/pyproject.toml +1 -1
- {lumapi-1.1.0 → lumapi-1.1.2}/LICENSE +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI/__init__.py +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI/cli.py +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI/config.json +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI/gui.py +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI.egg-info/SOURCES.txt +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI.egg-info/dependency_links.txt +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI.egg-info/entry_points.txt +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI.egg-info/requires.txt +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/LumAPI.egg-info/top_level.txt +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/setup.cfg +0 -0
- {lumapi-1.1.0 → lumapi-1.1.2}/test/test.py +0 -0
|
@@ -32,14 +32,28 @@ def savemat(filename, data_dict, version='v7.3', auto_transpose=True):
|
|
|
32
32
|
bool
|
|
33
33
|
写入成功返回 True。
|
|
34
34
|
"""
|
|
35
|
+
# 预处理字典,将所有整型转换为浮点型
|
|
36
|
+
processed_dict = {}
|
|
37
|
+
for key, val in data_dict.items():
|
|
38
|
+
data_array = np.asarray(val)
|
|
39
|
+
|
|
40
|
+
# 对齐 MATLAB/scipy.io 的底层维度逻辑
|
|
41
|
+
# 强制将标量(0D)和一维数组(1D)提升为二维矩阵(1x1 或 1xN)
|
|
42
|
+
data_array = np.atleast_2d(data_array)
|
|
43
|
+
|
|
44
|
+
# 针对 FDTD:将所有整数转为双精度浮点数
|
|
45
|
+
if np.issubdtype(data_array.dtype, np.integer):
|
|
46
|
+
data_array = data_array.astype(np.float64)
|
|
47
|
+
|
|
48
|
+
processed_dict[key] = data_array
|
|
49
|
+
|
|
35
50
|
if version == 'v7.3':
|
|
36
51
|
import h5py
|
|
37
52
|
with h5py.File(filename, 'w') as f:
|
|
38
|
-
for key,
|
|
39
|
-
data_array = np.asarray(val)
|
|
53
|
+
for key, data_array in processed_dict.items():
|
|
40
54
|
|
|
41
55
|
# 自动转置处理
|
|
42
|
-
if auto_transpose
|
|
56
|
+
if auto_transpose:
|
|
43
57
|
data_array = data_array.T
|
|
44
58
|
|
|
45
59
|
# 针对复数的特殊封装
|
|
@@ -57,16 +71,16 @@ def savemat(filename, data_dict, version='v7.3', auto_transpose=True):
|
|
|
57
71
|
elif version == 'v7':
|
|
58
72
|
import scipy.io
|
|
59
73
|
# scipy.io 内部会自动处理 C-order 和 F-order 的转换,不需要手动转置
|
|
60
|
-
|
|
61
|
-
scipy.io.savemat(filename, data_dict)
|
|
74
|
+
scipy.io.savemat(filename, processed_dict)
|
|
62
75
|
else:
|
|
63
76
|
raise ValueError("不支持的版本格式,请选择 'v7.3' 或 'v7'。")
|
|
64
77
|
|
|
65
78
|
return True
|
|
66
79
|
|
|
67
|
-
def loadmat(filename, auto_transpose=True):
|
|
80
|
+
def loadmat(filename, auto_transpose=True, squeeze_me=True):
|
|
68
81
|
"""
|
|
69
|
-
自动检测版本并读取 MATLAB .mat
|
|
82
|
+
自动检测版本并读取 MATLAB .mat 文件,支持自动多维数组转置恢复,
|
|
83
|
+
并自动将数据格式转换为符合 Python 直觉的维度习惯。
|
|
70
84
|
|
|
71
85
|
参数 (Parameters):
|
|
72
86
|
------------------
|
|
@@ -74,8 +88,10 @@ def loadmat(filename, auto_transpose=True):
|
|
|
74
88
|
需要读取的 .mat 文件路径。
|
|
75
89
|
auto_transpose : bool, 可选 (默认: True)
|
|
76
90
|
是否自动处理 Python 和 MATLAB 的跨语言内存主序差异。
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
squeeze_me : bool, 可选 (默认: True)
|
|
92
|
+
是否开启数组压缩功能。
|
|
93
|
+
如果开启,会自动将 MATLAB 中的 1xN 或 Nx1 数组降维为真正的 1D NumPy 数组 (N,)。
|
|
94
|
+
同时会将 1x1 的矩阵提取为单纯的标量。
|
|
79
95
|
|
|
80
96
|
返回 (Returns):
|
|
81
97
|
---------------
|
|
@@ -85,11 +101,12 @@ def loadmat(filename, auto_transpose=True):
|
|
|
85
101
|
if not os.path.exists(filename):
|
|
86
102
|
raise FileNotFoundError(f"找不到文件: {filename}")
|
|
87
103
|
|
|
88
|
-
#
|
|
104
|
+
# 读取魔法字节进行初步格式检测
|
|
89
105
|
with open(filename, 'rb') as f:
|
|
90
106
|
header = f.read(8)
|
|
91
107
|
|
|
92
108
|
import h5py
|
|
109
|
+
# 判断是否为 v7.3 HDF5 格式
|
|
93
110
|
is_v73 = h5py.is_hdf5(filename)
|
|
94
111
|
|
|
95
112
|
data_dict = {}
|
|
@@ -104,24 +121,43 @@ def loadmat(filename, auto_transpose=True):
|
|
|
104
121
|
if data.dtype.names is not None and 'real' in data.dtype.names and 'imag' in data.dtype.names:
|
|
105
122
|
data = data['real'] + 1j * data['imag']
|
|
106
123
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
124
|
+
if isinstance(data, np.ndarray):
|
|
125
|
+
# 标量与转置处理 (必须在 squeeze 之前转置,恢复实际物理形状)
|
|
126
|
+
if auto_transpose and data.ndim >= 2:
|
|
127
|
+
data = data.T
|
|
128
|
+
|
|
129
|
+
# 维度压缩
|
|
130
|
+
if squeeze_me:
|
|
131
|
+
# np.squeeze 会自动剥离所有大小为 1 的维度
|
|
132
|
+
data = np.squeeze(data)
|
|
133
|
+
|
|
134
|
+
# 提取标量处理
|
|
135
|
+
if data.ndim == 0:
|
|
136
|
+
# 提取 0维 数组为真正的标量值 (但保留 numpy 数据类型)
|
|
137
|
+
data = data[()]
|
|
138
|
+
elif not squeeze_me and data.shape == (1, 1):
|
|
139
|
+
# 如果用户关闭了压缩,但我们依然保持老版本的 1x1 标量提取兜底
|
|
140
|
+
data = data[0, 0]
|
|
112
141
|
|
|
113
142
|
data_dict[key] = data
|
|
114
143
|
else:
|
|
115
144
|
import scipy.io
|
|
116
|
-
|
|
145
|
+
# 对于 scipy,直接利用它内部极其完善的 squeeze_me 参数
|
|
146
|
+
mat_data = scipy.io.loadmat(filename, squeeze_me=squeeze_me)
|
|
117
147
|
for key, val in mat_data.items():
|
|
118
148
|
if not key.startswith('__'):
|
|
119
|
-
if isinstance(val, np.ndarray)
|
|
120
|
-
|
|
149
|
+
if isinstance(val, np.ndarray):
|
|
150
|
+
# scipy 在开启 squeeze_me 时,也会把 1x1 变成 0 维数组
|
|
151
|
+
if val.ndim == 0:
|
|
152
|
+
val = val[()]
|
|
153
|
+
# 如果用户关闭了压缩,兜底提取 1x1
|
|
154
|
+
elif not squeeze_me and val.shape == (1, 1):
|
|
155
|
+
val = val[0, 0]
|
|
121
156
|
data_dict[key] = val
|
|
122
157
|
|
|
123
158
|
return data_dict
|
|
124
159
|
|
|
160
|
+
|
|
125
161
|
# *****************绘图增强函数******************
|
|
126
162
|
def create_cmap(color_list, cmap_name="custom_cmap"):
|
|
127
163
|
"""
|
|
@@ -194,6 +230,7 @@ def set_colorbar_range(mappable, vmin, vmax):
|
|
|
194
230
|
# 获取当前的 figure 并请求重新绘制以更新显示
|
|
195
231
|
plt.draw()
|
|
196
232
|
|
|
233
|
+
|
|
197
234
|
# *****************近远场变换函数*****************
|
|
198
235
|
def Estimate_focal(lamb, r, focal_theory):
|
|
199
236
|
'''
|
|
@@ -942,6 +979,7 @@ def AngularSpectrum_Vector(lamb, x_near, y_near, E_near_x, E_near_y, x_far, y_fa
|
|
|
942
979
|
else:
|
|
943
980
|
raise ValueError("Invalid mode. Please use 'fft' or 'numba'.")
|
|
944
981
|
|
|
982
|
+
|
|
945
983
|
# ***************lumerical相关函数***************
|
|
946
984
|
def detect_version(lumerical_root):
|
|
947
985
|
"""检测Lumerical安装目录下的有效版本号"""
|
|
@@ -1076,10 +1114,34 @@ class lumerical:
|
|
|
1076
1114
|
return INTERCONNECT(self.lumapi, filename, key, hide, serverArgs, remoteArgs, **kwargs)
|
|
1077
1115
|
|
|
1078
1116
|
class LumFuncBase:
|
|
1079
|
-
"""Lumerical 功能基类,处理通用的 API
|
|
1080
|
-
def __init__(self,
|
|
1081
|
-
#
|
|
1082
|
-
|
|
1117
|
+
"""Lumerical 功能基类,处理通用的 API 转发、兼容性初始化和参数预处理"""
|
|
1118
|
+
def __init__(self, lumapi_module, product_name, filename=None, key=None, hide=False, serverArgs=None, remoteArgs=None, **kwargs):
|
|
1119
|
+
# 修复 Python 可变默认参数陷阱
|
|
1120
|
+
if serverArgs is None:
|
|
1121
|
+
serverArgs = {}
|
|
1122
|
+
if remoteArgs is None:
|
|
1123
|
+
remoteArgs = {}
|
|
1124
|
+
|
|
1125
|
+
# 动态获取对应的 Lumerical 构造函数 (例如 lumapi_module.FDTD)
|
|
1126
|
+
target_constructor = getattr(lumapi_module, product_name)
|
|
1127
|
+
|
|
1128
|
+
try:
|
|
1129
|
+
# 首先尝试 v24R1 及更新版本的完整参数调用
|
|
1130
|
+
self._handle = target_constructor(
|
|
1131
|
+
filename=filename, key=key, hide=hide,
|
|
1132
|
+
serverArgs=serverArgs, remoteArgs=remoteArgs, **kwargs
|
|
1133
|
+
)
|
|
1134
|
+
except TypeError as e:
|
|
1135
|
+
# 捕获旧版本不支持 remoteArgs 的错误并降级调用
|
|
1136
|
+
if 'remoteArgs' in str(e) or 'unexpected keyword argument' in str(e):
|
|
1137
|
+
self._handle = target_constructor(
|
|
1138
|
+
filename=filename, key=key, hide=hide,
|
|
1139
|
+
serverArgs=serverArgs, **kwargs
|
|
1140
|
+
)
|
|
1141
|
+
else:
|
|
1142
|
+
raise # 其他 TypeError 原样抛出
|
|
1143
|
+
|
|
1144
|
+
self.filename = filename
|
|
1083
1145
|
|
|
1084
1146
|
def _process_arg(self, arg):
|
|
1085
1147
|
"""
|
|
@@ -1088,11 +1150,11 @@ class LumFuncBase:
|
|
|
1088
1150
|
2. 一维 ndarray (len > 1) -> 二维 [[...]]
|
|
1089
1151
|
"""
|
|
1090
1152
|
if isinstance(arg, np.ndarray):
|
|
1091
|
-
#
|
|
1153
|
+
# 检查是否为整型数组并转换
|
|
1092
1154
|
if np.issubdtype(arg.dtype, np.integer):
|
|
1093
1155
|
arg = arg.astype(float)
|
|
1094
1156
|
|
|
1095
|
-
#
|
|
1157
|
+
# 检查一维数组且长度不为 1,进行升维
|
|
1096
1158
|
if arg.ndim == 1 and arg.shape[0] != 1:
|
|
1097
1159
|
arg = arg[np.newaxis, :]
|
|
1098
1160
|
return arg
|
|
@@ -1129,28 +1191,20 @@ class LumFuncBase:
|
|
|
1129
1191
|
pass
|
|
1130
1192
|
|
|
1131
1193
|
class FDTD(LumFuncBase):
|
|
1132
|
-
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=
|
|
1133
|
-
|
|
1134
|
-
super().__init__(handle)
|
|
1135
|
-
self.filename = filename
|
|
1194
|
+
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=None, remoteArgs=None, **kwargs):
|
|
1195
|
+
super().__init__(lumapi, 'FDTD', filename, key, hide, serverArgs, remoteArgs, **kwargs)
|
|
1136
1196
|
|
|
1137
1197
|
class MODE(LumFuncBase):
|
|
1138
|
-
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=
|
|
1139
|
-
|
|
1140
|
-
super().__init__(handle)
|
|
1141
|
-
self.filename = filename
|
|
1198
|
+
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=None, remoteArgs=None, **kwargs):
|
|
1199
|
+
super().__init__(lumapi, 'MODE', filename, key, hide, serverArgs, remoteArgs, **kwargs)
|
|
1142
1200
|
|
|
1143
1201
|
class DEVICE(LumFuncBase):
|
|
1144
|
-
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=
|
|
1145
|
-
|
|
1146
|
-
super().__init__(handle)
|
|
1147
|
-
self.filename = filename
|
|
1202
|
+
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=None, remoteArgs=None, **kwargs):
|
|
1203
|
+
super().__init__(lumapi, 'DEVICE', filename, key, hide, serverArgs, remoteArgs, **kwargs)
|
|
1148
1204
|
|
|
1149
1205
|
class INTERCONNECT(LumFuncBase):
|
|
1150
|
-
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=
|
|
1151
|
-
|
|
1152
|
-
super().__init__(handle)
|
|
1153
|
-
self.filename = filename
|
|
1206
|
+
def __init__(self, lumapi, filename=None, key=None, hide=False, serverArgs=None, remoteArgs=None, **kwargs):
|
|
1207
|
+
super().__init__(lumapi, 'INTERCONNECT', filename, key, hide, serverArgs, remoteArgs, **kwargs)
|
|
1154
1208
|
|
|
1155
1209
|
lumapi = lumerical()
|
|
1156
1210
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: LumAPI
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Lumerical Python API 自动化配置工具
|
|
5
5
|
Author-email: JaniQuiz <janiquiz@163.com>
|
|
6
6
|
Maintainer-email: JaniQuiz <janiquiz@163.com>
|
|
@@ -32,23 +32,30 @@ Dynamic: license-file
|
|
|
32
32
|
* **API 增强**:支持原本接口,并对原本接口参数进行优化。
|
|
33
33
|
* **衍射积分函数**:封装了个人常用的衍射积分函数,且每个衍射积分函数结果均进行了验证。
|
|
34
34
|
* **数据保存读取**:封装了matlab数据文件.mat的读取和写入函数,方便与其他软件进行数据交互。
|
|
35
|
-
|
|
35
|
+
* **绘图函数增强**:封装了一些常用的matplotlib绘图功能,方便快速绘制合适的图像。
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
## 📦 如何安装
|
|
39
39
|
[安装方式](install.md)
|
|
40
40
|
|
|
41
|
-
##
|
|
42
|
-
|
|
41
|
+
## 🗂️ 文档目录
|
|
42
|
+
|
|
43
|
+
### 使用指南
|
|
43
44
|
|
|
44
|
-
## 💻 使用指南
|
|
45
45
|
- [使用文档](docs/usage.md)
|
|
46
|
-
- [
|
|
46
|
+
- [使用案例](docs/methods.md)
|
|
47
|
+
|
|
48
|
+
### 衍射积分函数验证
|
|
49
|
+
|
|
50
|
+
- [基尔霍夫(Kirchhoff)标量衍射积分函数验证](docs/Kirchhoff.md)
|
|
51
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)标量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Scalar.md)
|
|
52
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)矢量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Vector.md)
|
|
53
|
+
- [矢量角谱(Angular Spectrum)矢量衍射积分函数验证](docs/AngularSpectrum_Vector.md)
|
|
47
54
|
|
|
48
|
-
## 许可证
|
|
55
|
+
## 📜 许可证
|
|
49
56
|
本库遵循[GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html)开源许可证
|
|
50
57
|
|
|
51
|
-
## 联系作者
|
|
58
|
+
## 📧 联系作者
|
|
52
59
|
- **作者**: [JaniQuiz](https://github.com/JaniQuiz)
|
|
53
60
|
- **邮箱**: janiquiz@163.com
|
|
54
61
|
- **项目主页**: [LumAPI](https://github.com/JaniQuiz/LumAPI)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: LumAPI
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.2
|
|
4
4
|
Summary: Lumerical Python API 自动化配置工具
|
|
5
5
|
Author-email: JaniQuiz <janiquiz@163.com>
|
|
6
6
|
Maintainer-email: JaniQuiz <janiquiz@163.com>
|
|
@@ -32,23 +32,30 @@ Dynamic: license-file
|
|
|
32
32
|
* **API 增强**:支持原本接口,并对原本接口参数进行优化。
|
|
33
33
|
* **衍射积分函数**:封装了个人常用的衍射积分函数,且每个衍射积分函数结果均进行了验证。
|
|
34
34
|
* **数据保存读取**:封装了matlab数据文件.mat的读取和写入函数,方便与其他软件进行数据交互。
|
|
35
|
-
|
|
35
|
+
* **绘图函数增强**:封装了一些常用的matplotlib绘图功能,方便快速绘制合适的图像。
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
## 📦 如何安装
|
|
39
39
|
[安装方式](install.md)
|
|
40
40
|
|
|
41
|
-
##
|
|
42
|
-
|
|
41
|
+
## 🗂️ 文档目录
|
|
42
|
+
|
|
43
|
+
### 使用指南
|
|
43
44
|
|
|
44
|
-
## 💻 使用指南
|
|
45
45
|
- [使用文档](docs/usage.md)
|
|
46
|
-
- [
|
|
46
|
+
- [使用案例](docs/methods.md)
|
|
47
|
+
|
|
48
|
+
### 衍射积分函数验证
|
|
49
|
+
|
|
50
|
+
- [基尔霍夫(Kirchhoff)标量衍射积分函数验证](docs/Kirchhoff.md)
|
|
51
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)标量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Scalar.md)
|
|
52
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)矢量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Vector.md)
|
|
53
|
+
- [矢量角谱(Angular Spectrum)矢量衍射积分函数验证](docs/AngularSpectrum_Vector.md)
|
|
47
54
|
|
|
48
|
-
## 许可证
|
|
55
|
+
## 📜 许可证
|
|
49
56
|
本库遵循[GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html)开源许可证
|
|
50
57
|
|
|
51
|
-
## 联系作者
|
|
58
|
+
## 📧 联系作者
|
|
52
59
|
- **作者**: [JaniQuiz](https://github.com/JaniQuiz)
|
|
53
60
|
- **邮箱**: janiquiz@163.com
|
|
54
61
|
- **项目主页**: [LumAPI](https://github.com/JaniQuiz/LumAPI)
|
|
@@ -8,23 +8,30 @@
|
|
|
8
8
|
* **API 增强**:支持原本接口,并对原本接口参数进行优化。
|
|
9
9
|
* **衍射积分函数**:封装了个人常用的衍射积分函数,且每个衍射积分函数结果均进行了验证。
|
|
10
10
|
* **数据保存读取**:封装了matlab数据文件.mat的读取和写入函数,方便与其他软件进行数据交互。
|
|
11
|
-
|
|
11
|
+
* **绘图函数增强**:封装了一些常用的matplotlib绘图功能,方便快速绘制合适的图像。
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
## 📦 如何安装
|
|
15
15
|
[安装方式](install.md)
|
|
16
16
|
|
|
17
|
-
##
|
|
18
|
-
|
|
17
|
+
## 🗂️ 文档目录
|
|
18
|
+
|
|
19
|
+
### 使用指南
|
|
19
20
|
|
|
20
|
-
## 💻 使用指南
|
|
21
21
|
- [使用文档](docs/usage.md)
|
|
22
|
-
- [
|
|
22
|
+
- [使用案例](docs/methods.md)
|
|
23
|
+
|
|
24
|
+
### 衍射积分函数验证
|
|
25
|
+
|
|
26
|
+
- [基尔霍夫(Kirchhoff)标量衍射积分函数验证](docs/Kirchhoff.md)
|
|
27
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)标量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Scalar.md)
|
|
28
|
+
- [瑞利-索末菲(Rayleigh-Sommerfeld)矢量衍射积分函数验证](docs/Rayleigh-Sommerfeld_Vector.md)
|
|
29
|
+
- [矢量角谱(Angular Spectrum)矢量衍射积分函数验证](docs/AngularSpectrum_Vector.md)
|
|
23
30
|
|
|
24
|
-
## 许可证
|
|
31
|
+
## 📜 许可证
|
|
25
32
|
本库遵循[GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html)开源许可证
|
|
26
33
|
|
|
27
|
-
## 联系作者
|
|
34
|
+
## 📧 联系作者
|
|
28
35
|
- **作者**: [JaniQuiz](https://github.com/JaniQuiz)
|
|
29
36
|
- **邮箱**: janiquiz@163.com
|
|
30
37
|
- **项目主页**: [LumAPI](https://github.com/JaniQuiz/LumAPI)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|