diff --git a/dashboard/src2/components/JsiteDomainDNSRecords.vue b/dashboard/src2/components/JsiteDomainDNSRecords.vue index 719da8d..e84a833 100644 --- a/dashboard/src2/components/JsiteDomainDNSRecords.vue +++ b/dashboard/src2/components/JsiteDomainDNSRecords.vue @@ -52,58 +52,83 @@ - + + - - - - + + - - - - - + + + + + @@ -112,6 +137,24 @@
+ + + + 主机名 + 类型 - 主机记录 + + 线路类型 - 记录值 + + 对应值 + TTL + + 优先级 + + 状态 + 操作
- - {{ record.type }} - + + + {{ record.item || record.host || '@' }} - {{ record.value }} - - {{ record.ttl || '600' }} - - (优先级: {{ record.level }}) + + + {{ record.type || '未知' }} -
+
+ 默认 + + {{ record.value }} + + {{ record.ttl || '600' }} + + {{ record.type === 'MX' && record.level ? record.level : '-' }} + + + 正常 + + +
-
+ +
+
+ + 已选 0 条 +
+ + + + +
+
+
+ + +
+
+
diff --git a/jcloud/api/domain_west.py b/jcloud/api/domain_west.py index a02a700..45787d9 100644 --- a/jcloud/api/domain_west.py +++ b/jcloud/api/domain_west.py @@ -312,44 +312,106 @@ class WestDomain: return self._make_request('/domain/?act=modifydns', 'POST', body_params=body_params) def add_dns_record(self, domain: str, record_type: str, - host: str, value: str, ttl: int = 600, level: int = 10) -> Dict[str, Any]: + host: str, value: str, ttl: int = 600, level: int = 10, line: str = "") -> Dict[str, Any]: """ 添加DNS记录 Args: domain: 域名 - record_type: 记录类型 (A, CNAME, MX, TXT等) + record_type: 记录类型 (A, CNAME, MX, TXT, AAAA, SRV) host: 主机记录 value: 记录值 - ttl: TTL值 - level: 优先级(MX记录使用) + ttl: TTL值 (60~86400秒,默认900) + level: 优先级(MX记录使用,1-100,默认10) + line: 线路 (默认="", 电信="LTEL", 联通="LCNC", 移动="LMOB", 教育网="LEDU", 搜索引擎="LSEO") """ - record = { - 'type': record_type, + body_params = { + 'act': 'adddnsrecord', + 'domain': domain, 'host': host, + 'type': record_type, 'value': value, 'ttl': ttl, + 'level': level, + 'line': line, + } + return self._make_request('/domain/', 'POST', body_params=body_params) + + def modify_dns_record(self, domain: str, value: str, ttl: int = 600, level: int = 10, + record_id: Optional[str] = None, host: Optional[str] = None, + record_type: Optional[str] = None, line: str = "", old_value: Optional[str] = None) -> Dict[str, Any]: + """ + 修改DNS记录 + + Args: + domain: 域名 + value: 新的解析值 + ttl: TTL值 (60~86400秒,默认900) + level: 优先级(MX记录使用,1-100,默认10) + record_id: 解析记录编号(优先使用) + host: 主机头(当record_id未提供时必填) + record_type: 解析类型(当record_id未提供时必填) + line: 线路 (默认="", 电信="LTEL", 联通="LCNC", 移动="LMOB", 教育网="LEDU", 搜索引擎="LSEO") + old_value: 旧解析值(可选,用于确定唯一记录) + """ + body_params = { + 'act': 'moddnsrecord', + 'domain': domain, + 'value': value, + 'ttl': ttl, + 'level': level, + 'line': line, } - # 如果是MX记录,添加优先级 - if record_type == 'MX': - record['level'] = level - - return self.modify_dns_records(domain, [record]) + # 优先使用record_id + if record_id: + body_params['id'] = record_id + else: + # 必须提供host和type + if not host or not record_type: + return {"status": "error", "message": "当未提供记录ID时,主机头和解析类型为必填项"} + body_params['host'] = host + body_params['type'] = record_type + + # 添加旧值(可选) + if old_value: + body_params['oldvalue'] = old_value + + return self._make_request('/domain/', 'POST', body_params=body_params) - def delete_dns_record(self, domain: str, record_id: str) -> Dict[str, Any]: + def delete_dns_record(self, domain: str, record_id: Optional[str] = None, + host: Optional[str] = None, record_type: Optional[str] = None, + value: Optional[str] = None, line: str = "") -> Dict[str, Any]: """ 删除DNS记录 Args: domain: 域名 - record_id: 记录ID + record_id: 解析记录ID(优先使用) + host: 主机头(当record_id未提供时必填) + record_type: 解析类型(当record_id未提供时必填) + value: 解析值(可选) + line: 线路 (默认="", 电信="LTEL", 联通="LCNC", 移动="LMOB", 教育网="LEDU", 搜索引擎="LSEO") """ body_params = { + 'act': 'deldnsrecord', 'domain': domain, - 'record_id': record_id, + 'line': line, } - return self._make_request('/domain/?act=deletedns', 'POST', body_params=body_params) + + # 优先使用record_id + if record_id: + body_params['id'] = record_id + else: + # 必须提供host和type + if not host or not record_type: + return {"status": "error", "message": "当未提供记录ID时,主机头和解析类型为必填项"} + body_params['host'] = host + body_params['type'] = record_type + if value: + body_params['value'] = value + + return self._make_request('/domain/', 'POST', body_params=body_params) def transfer_domain(self, domain: str, auth_code: str) -> Dict[str, Any]: """ @@ -822,7 +884,7 @@ def get_west_domain_dns_records(**data): @jingrow.whitelist() def west_domain_modify_dns(**data): - """修改域名DNS记录""" + """修改域名DNS记录(批量修改,兼容旧版本)""" client = get_west_client() if not client: return {"status": "error", "message": "API客户端初始化失败"} @@ -835,23 +897,80 @@ def west_domain_modify_dns(**data): if not records: return {"status": "error", "message": "缺少DNS记录参数"} - # 处理记录数据,确保MX记录有正确的优先级字段 - processed_records = [] + # 逐个修改记录 + results = [] for record in records: - processed_record = { - 'type': record.get('type'), - 'host': record.get('host'), - 'value': record.get('value'), - 'ttl': record.get('ttl', 600) - } + record_type = record.get('type') + host = record.get('host') + value = record.get('value') + ttl = record.get('ttl', 600) + level = record.get('level', 10) + line = record.get('line', '') + record_id = record.get('record_id') + old_value = record.get('old_value') - # 如果是MX记录,添加优先级 - if record.get('type') == 'MX': - processed_record['level'] = record.get('level', 10) - - processed_records.append(processed_record) + # 验证必要参数 + if not value: + results.append({"status": "error", "message": "缺少解析值"}) + continue + + # 如果没有提供record_id,则必须提供host和record_type + if not record_id and (not host or not record_type): + results.append({"status": "error", "message": "当未提供记录ID时,主机头和解析类型为必填项"}) + continue + + # 验证TTL值 + if ttl < 60 or ttl > 86400: + results.append({"status": "error", "message": "TTL值必须在60~86400秒之间"}) + continue + + # 验证优先级 + if level < 1 or level > 100: + results.append({"status": "error", "message": "优先级必须在1~100之间"}) + continue + + # 验证记录类型 + if record_type: + valid_types = ['A', 'CNAME', 'MX', 'TXT', 'AAAA', 'SRV'] + if record_type not in valid_types: + results.append({"status": "error", "message": f"不支持的记录类型: {record_type}"}) + continue + + # 调用单个记录修改API + response = client.modify_dns_record( + domain, value, ttl, level, record_id, host, record_type, line, old_value + ) + + if response.get("status") == "error": + results.append(response) + elif response.get("result") != 200: + error_msg = response.get('msg', response.get('message', '未知错误')) + results.append({"status": "error", "message": f"修改DNS记录失败: {error_msg}"}) + else: + results.append({ + "status": "success", + "message": "DNS记录修改成功", + "data": { + "domain": domain, + "value": value, + "ttl": ttl, + "level": level, + "record_id": record_id, + "host": host, + "record_type": record_type, + "line": line + } + }) - return client.modify_dns_records(domain, processed_records) + # 返回批量操作结果 + success_count = sum(1 for r in results if r.get("status") == "success") + error_count = len(results) - success_count + + return { + "status": "success" if error_count == 0 else "partial_success", + "message": f"批量修改完成,成功: {success_count},失败: {error_count}", + "results": results + } @jingrow.whitelist() @@ -867,11 +986,54 @@ def west_domain_add_dns_record(**data): value = data.get('value') ttl = data.get('ttl', 600) level = data.get('level', 10) + line = data.get('line', '') if not all([domain, record_type, host, value]): return {"status": "error", "message": "缺少必要参数"} - return client.add_dns_record(domain, record_type, host, value, ttl, level) + # 验证记录类型 + valid_types = ['A', 'CNAME', 'MX', 'TXT', 'AAAA', 'SRV'] + if record_type not in valid_types: + return {"status": "error", "message": f"不支持的记录类型: {record_type},支持的类型: {', '.join(valid_types)}"} + + # 验证TTL值 + if ttl < 60 or ttl > 86400: + return {"status": "error", "message": "TTL值必须在60~86400秒之间"} + + # 验证优先级 + if level < 1 or level > 100: + return {"status": "error", "message": "优先级必须在1~100之间"} + + response = client.add_dns_record(domain, record_type, host, value, ttl, level, line) + + if response.get("status") == "error": + return response + + try: + # 检查响应格式 + if response.get("result") != 200: + error_msg = response.get('msg', response.get('message', '未知错误')) + return {"status": "error", "message": f"添加DNS记录失败: {error_msg}"} + + # 返回成功结果 + return { + "status": "success", + "message": "DNS记录添加成功", + "data": { + "id": response.get("data", {}).get("id"), + "domain": domain, + "host": host, + "type": record_type, + "value": value, + "ttl": ttl, + "level": level, + "line": line + } + } + + except Exception as e: + jingrow.log_error("添加DNS记录响应解析失败", error=str(e)) + return {"status": "error", "message": "添加DNS记录响应解析失败"} @jingrow.whitelist() @@ -883,13 +1045,52 @@ def west_domain_delete_dns_record(**data): domain = data.get('domain') record_id = data.get('record_id') + host = data.get('host') + record_type = data.get('record_type') + value = data.get('value') + line = data.get('line', '') if not domain: return {"status": "error", "message": "缺少域名参数"} - if not record_id: - return {"status": "error", "message": "缺少记录ID参数"} - return client.delete_dns_record(domain, record_id) + # 如果没有提供record_id,则必须提供host和record_type + if not record_id and (not host or not record_type): + return {"status": "error", "message": "当未提供记录ID时,主机头和解析类型为必填项"} + + # 验证记录类型 + if record_type: + valid_types = ['A', 'CNAME', 'MX', 'TXT', 'AAAA', 'SRV'] + if record_type not in valid_types: + return {"status": "error", "message": f"不支持的记录类型: {record_type},支持的类型: {', '.join(valid_types)}"} + + response = client.delete_dns_record(domain, record_id, host, record_type, value, line) + + if response.get("status") == "error": + return response + + try: + # 检查响应格式 + if response.get("result") != 200: + error_msg = response.get('msg', response.get('message', '未知错误')) + return {"status": "error", "message": f"删除DNS记录失败: {error_msg}"} + + # 返回成功结果 + return { + "status": "success", + "message": "DNS记录删除成功", + "data": { + "domain": domain, + "record_id": record_id, + "host": host, + "record_type": record_type, + "value": value, + "line": line + } + } + + except Exception as e: + jingrow.log_error("删除DNS记录响应解析失败", error=str(e)) + return {"status": "error", "message": "删除DNS记录响应解析失败"} @jingrow.whitelist() @@ -1955,3 +2156,146 @@ def west_upload_real_name_files(**data): return {"status": "error", "message": "实名资料上传响应解析失败"} +@jingrow.whitelist() +def west_domain_modify_dns_record(**data): + """修改DNS记录""" + client = get_west_client() + if not client: + return {"status": "error", "message": "API客户端初始化失败"} + + domain = data.get('domain') + value = data.get('value') + ttl = data.get('ttl', 600) + level = data.get('level', 10) + record_id = data.get('record_id') + host = data.get('host') + record_type = data.get('record_type') + line = data.get('line', '') + old_value = data.get('old_value') + + if not domain: + return {"status": "error", "message": "缺少域名参数"} + if not value: + return {"status": "error", "message": "缺少新的解析值"} + + # 验证TTL值 + if ttl < 60 or ttl > 86400: + return {"status": "error", "message": "TTL值必须在60~86400秒之间"} + + # 验证优先级 + if level < 1 or level > 100: + return {"status": "error", "message": "优先级必须在1~100之间"} + + # 如果没有提供record_id,则必须提供host和record_type + if not record_id and (not host or not record_type): + return {"status": "error", "message": "当未提供记录ID时,主机头和解析类型为必填项"} + + # 验证记录类型 + if record_type: + valid_types = ['A', 'CNAME', 'MX', 'TXT', 'AAAA', 'SRV'] + if record_type not in valid_types: + return {"status": "error", "message": f"不支持的记录类型: {record_type},支持的类型: {', '.join(valid_types)}"} + + response = client.modify_dns_record( + domain, value, ttl, level, record_id, host, record_type, line, old_value + ) + + if response.get("status") == "error": + return response + + try: + # 检查响应格式 + if response.get("result") != 200: + error_msg = response.get('msg', response.get('message', '未知错误')) + return {"status": "error", "message": f"修改DNS记录失败: {error_msg}"} + + # 返回成功结果 + return { + "status": "success", + "message": "DNS记录修改成功", + "data": { + "domain": domain, + "value": value, + "ttl": ttl, + "level": level, + "record_id": record_id, + "host": host, + "record_type": record_type, + "line": line + } + } + + except Exception as e: + jingrow.log_error("修改DNS记录响应解析失败", error=str(e)) + return {"status": "error", "message": "修改DNS记录响应解析失败"} + + +@jingrow.whitelist() +def test_dns_record_management(): + """测试DNS记录管理功能""" + try: + # 测试参数 + test_domain = "test.com" + test_host = "www" + test_value = "127.0.0.1" + test_record_type = "A" + + client = get_west_client() + if not client: + return {"status": "error", "message": "API客户端初始化失败"} + + # 测试1: 添加DNS记录 + jingrow.log_error("DNS测试", "开始测试添加DNS记录") + add_result = client.add_dns_record( + domain=test_domain, + record_type=test_record_type, + host=test_host, + value=test_value, + ttl=900, + level=10, + line="" + ) + jingrow.log_error("DNS测试", f"添加DNS记录结果: {add_result}") + + # 测试2: 获取DNS记录列表 + jingrow.log_error("DNS测试", "开始测试获取DNS记录列表") + list_result = client.get_dns_records_paginated(test_domain, 20, 1) + jingrow.log_error("DNS测试", f"获取DNS记录列表结果: {list_result}") + + # 测试3: 修改DNS记录(如果添加成功) + if add_result.get("result") == 200: + record_id = add_result.get("data", {}).get("id") + if record_id: + jingrow.log_error("DNS测试", f"开始测试修改DNS记录,记录ID: {record_id}") + modify_result = client.modify_dns_record( + domain=test_domain, + value="127.0.0.2", + ttl=600, + level=10, + record_id=record_id, + line="" + ) + jingrow.log_error("DNS测试", f"修改DNS记录结果: {modify_result}") + + # 测试4: 删除DNS记录 + jingrow.log_error("DNS测试", "开始测试删除DNS记录") + delete_result = client.delete_dns_record( + domain=test_domain, + record_id=record_id + ) + jingrow.log_error("DNS测试", f"删除DNS记录结果: {delete_result}") + + return { + "status": "success", + "message": "DNS记录管理功能测试完成", + "data": { + "add_result": add_result, + "list_result": list_result + } + } + + except Exception as e: + jingrow.log_error("DNS测试异常", str(e)) + return {"status": "error", "message": f"DNS记录管理功能测试失败: {str(e)}"} + +