报错:For input string: "filter_imports"。

报错:For input string: "filter_imports"。

正文

报错:For input string: "filter_imports"。
解决方案如下:
进入 $WorkSpace/.metadata/.plugins/org.eclipse.jdt.ui
删除IDE自动保存的一些档案:

    * dialog_settings.xml
    * OpenTypeHistory.xml
    * QualifiedTypeNameHistory.xml

clean所有的工程无效,删除上面的文件后重启eclipse就可以了
import csv import re import time from typing import Optional, Dict, List, Set import requests from bs4 import BeautifulSoup from langdetect import detect # ==== Selenium imports ==== from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.common.exceptions import WebDriverException, TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # ==== Config(已删除SKIP_KEYWORDS)==== INPUT_FILE = "top100000_domains.csv" OUTPUT_FILE = "top100000_domains_with_text.csv" # 若你的 chromedriver 不在 PATH 中,填入绝对路径,例如: # CHROMEDRIVER_PATH = r"E:\drivers\chromedriver.exe" CHROMEDRIVER_PATH: Optional[str] = None # None 表示使用系统 PATH 中的 chromedriver REQUEST_TIMEOUT = 12 SELENIUM_PAGELOAD_TIMEOUT = 20 SELENIUM_RENDER_WAIT = 3 # 页面 readyState 完成后额外等待秒数,给 JS 更多时间 PAUSE_BETWEEN_REQUESTS = 0.4 MAX_CHARS = 15000 # 限制保存的文本长度,避免极大页面带来 IO 压力 MIN_VALID_LENGTH = 100 # 小于该长度视为无效文本,触发 Selenium fallback COMMON_HEADERS = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/118.0 Safari/537.36" ), "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive", } # 多语言无用短语表(可扩展) USELESS_PHRASES_DICT = { 'zh': {"首页", "主页", "返回首页", "联系我们", "关于我们", "隐私政策", "数据保护", "版权声明", "下一页", "上一页", "更多", "返回顶部", "订阅", "分享", "帮助中心", "服务条款", "免责声明", "广告服务", "反馈建议"}, 'en': {"home", "homepage", "contact", "contact us", "about", "about us", "privacy", "privacy policy", "terms of service", "terms and conditions", "sitemap", "navigation", "register", "login", "sign in", "sign up", "next", "previous", "more", "back to top", "subscribe", "share", "help", "disclaimer", "advertising", "feedback"}, 'es': {"inicio", "página principal", "contáctenos", "contacto", "sobre nosotros", "política de privacidad", "mapa del sitio", "navegación", "registrarse", "iniciar sesión", "siguiente", "anterior", "más", "volver arriba", "suscribirse", "compartir", "ayuda", "aviso legal", "publicidad"}, 'fr': {"accueil", "page d'accueil", "contact", "contactez-nous", "à propos", "politique de confidentialité", "plan du site", "navigation", "s'inscrire", "connexion", "suivant", "précédent", "plus", "haut de page", "s'abonner", "partager", "aide", "mention légale", "publicité"}, 'de': {"startseite", "kontakt", "über uns", "datenschutz", "datenschutzerklärung", "seitenverzeichnis", "navigation", "registrieren", "anmelden", "weiter", "zurück", "mehr", "nach oben", "abonnieren", "teilen", "hilfe", "haftungsausschluss", "werbung"} } # ==== 语言检测和文本过滤 ==== def detect_lang(html_text: str) -> str: """优先用 <html lang=""> 检测语言,否则用 langdetect""" soup = BeautifulSoup(html_text, "html.parser") lang_attr = soup.html.get("lang") if soup.html else None if lang_attr: return lang_attr.split("-")[0].lower() try: return detect(soup.get_text()) except: return 'en' # 默认英文 def is_useful_text(text: str, lang: str = 'en') -> bool: """判断文本是否有用""" text = text.strip() if len(text) <= 2: return False if re.fullmatch(r"[\d\W_]+", text): # 全是数字/符号 return False useless_set = USELESS_PHRASES_DICT.get(lang, set()) if text.lower() in useless_set: return False return True def extract_useful_text_from_soup(soup: BeautifulSoup, lang: str) -> str: """从BeautifulSoup对象中提取有用文本""" # 提取不同类型的内容 data = { "title": "", "meta_description": "", "meta_keywords": "", "headings": [], "paragraphs": [], "alt_texts": [], "link_texts": [], "table_contents": [], "list_items": [] } # 标题 if soup.title and is_useful_text(soup.title.string, lang): data["title"] = soup.title.string.strip() # meta 描述 & 关键词 desc_tag = soup.find("meta", attrs={"name": "description"}) if desc_tag and desc_tag.get("content") and is_useful_text(desc_tag["content"], lang): data["meta_description"] = desc_tag["content"].strip() keywords_tag = soup.find("meta", attrs={"name": "keywords"}) if keywords_tag and keywords_tag.get("content") and is_useful_text(keywords_tag["content"], lang): data["meta_keywords"] = keywords_tag["content"].strip() # H 标签 for tag in ["h1", "h2", "h3", "h4", "h5", "h6"]: for h in soup.find_all(tag): txt = re.sub(r"\s+", " ", h.get_text(strip=True)) if is_useful_text(txt, lang): data["headings"].append(txt) # 段落 for p in soup.find_all("p"): txt = re.sub(r"\s+", " ", p.get_text(strip=True)) if is_useful_text(txt, lang): data["paragraphs"].append(txt) # 图片 alt for img in soup.find_all("img"): alt = img.get("alt") if alt and is_useful_text(alt, lang): data["alt_texts"].append(alt.strip()) # 链接文本 for a in soup.find_all("a"): txt = re.sub(r"\s+", " ", a.get_text(strip=True)) if is_useful_text(txt, lang): data["link_texts"].append(txt) # 表格内容 for table in soup.find_all("table"): for row in table.find_all("tr"): cells = [re.sub(r"\s+", " ", c.get_text(strip=True)) for c in row.find_all(["td", "th"])] cells = [c for c in cells if is_useful_text(c, lang)] if cells: data["table_contents"].append(" | ".join(cells)) # 列表项 for li in soup.find_all("li"): txt = re.sub(r"\s+", " ", li.get_text(strip=True)) if is_useful_text(txt, lang): data["list_items"].append(txt) # 合并所有有用文本 combined_parts = [ data["title"], data["meta_description"], data["meta_keywords"], *data["headings"], *data["paragraphs"], *data["alt_texts"], *data["link_texts"], *data["table_contents"], *data["list_items"] ] combined_text = "\n".join(filter(None, combined_parts)) return combined_text # ==== Text cleaning for BERT ==== def clean_text_for_bert(text: str) -> str: # 去除多余空白与特殊符号 text = re.sub(r"\s+", " ", text) text = re.sub(r"[^\w\s.,!?;:()\[\]\'\"-]", "", text) text = text.strip() # 限长 if len(text) > MAX_CHARS: text = text[:MAX_CHARS] return text # ==== Requests-first fetch(已删除SKIP_KEYWORDS判断)==== def fetch_with_requests(url: str) -> str: try: if not url.startswith(("http://", "https://")): url = "https://" + url # 强制 HTTPS,提高成功率 # (已删除)原SKIP_KEYWORDS过滤逻辑:if any(k in url for k in SKIP_KEYWORDS): return "[SKIPPED...]" session = requests.Session() resp = session.get(url, headers=COMMON_HEADERS, timeout=REQUEST_TIMEOUT) # 关键改进:使用自动检测的编码来避免乱码 resp.encoding = resp.apparent_encoding resp.raise_for_status() # 检测页面语言 lang = detect_lang(resp.text) soup = BeautifulSoup(resp.text, "html.parser") # 删除无关标签 for tag in soup(["script", "style", "noscript", "iframe", "header", "footer", "nav", "form", "aside"]): tag.decompose() # 提取有用文本 text = extract_useful_text_from_soup(soup, lang) text = clean_text_for_bert(text) return text if text else "[NO TEXT]" except Exception as e: return f"[ERROR_REQUESTS] {e}" # ==== Selenium driver init ==== def init_selenium_driver() -> Optional[webdriver.Chrome]: try: options = Options() options.add_argument("--headless=new") # Chrome 109+ 推荐 options.add_argument("--disable-gpu") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") options.add_argument("--window-size=1920,1080") # 减少资源加载(可选):禁用图片、字体等,提升速度 prefs = { "profile.managed_default_content_settings.images": 2, "profile.managed_default_content_settings.stylesheets": 1, "profile.managed_default_content_settings.fonts": 1, "profile.managed_default_content_settings.popups": 2, "profile.managed_default_content_settings.notifications": 2, } options.add_experimental_option("prefs", prefs) options.add_argument(f"user-agent={COMMON_HEADERS['User-Agent']}") if CHROMEDRIVER_PATH: service = Service(CHROMEDRIVER_PATH) else: service = Service() # 使用系统 PATH driver = webdriver.Chrome(service=service, options=options) driver.set_page_load_timeout(SELENIUM_PAGELOAD_TIMEOUT) return driver except WebDriverException as e: print(f"[WARN] Selenium 初始化失败: {e}") return None # ==== Selenium render fetch(已删除SKIP_KEYWORDS判断)==== def fetch_with_selenium(url: str, driver: webdriver.Chrome) -> str: try: if not url.startswith(("http://", "https://")): url = "https://" + url # (已删除)原SKIP_KEYWORDS过滤逻辑:if any(k in url for k in SKIP_KEYWORDS): return "[SKIPPED...]" driver.get(url) # 等待文档就绪 WebDriverWait(driver, SELENIUM_PAGELOAD_TIMEOUT).until( lambda d: d.execute_script("return document.readyState") == "complete" ) # 额外等待 JS 渲染 time.sleep(SELENIUM_RENDER_WAIT) # 获取页面内容和编码 html = driver.page_source lang = detect_lang(html) soup = BeautifulSoup(html, "html.parser") # 删除无关标签 for tag in soup(["script", "style", "noscript", "iframe", "header", "footer", "nav", "form", "aside"]): tag.decompose() # 提取有用文本 text = extract_useful_text_from_soup(soup, lang) text = clean_text_for_bert(text) return text if text else "[NO TEXT]" except TimeoutException as e: return f"[ERROR_SELENIUM_TIMEOUT] {e}" except Exception as e: return f"[ERROR_SELENIUM] {e}" # ==== Unified fetch with fallback ==== def fetch_text(url: str, driver: Optional[webdriver.Chrome]) -> str: # 先尝试 requests text = fetch_with_requests(url) if text.startswith("[ERROR_REQUESTS]") or text == "[NO TEXT]" or len(text) < MIN_VALID_LENGTH: # 尝试 Selenium 渲染 if driver is None: # 无驱动时,直接返回 requests 的结果或错误 return text text2 = fetch_with_selenium(url, driver) # 如果 Selenium 也失败,返回更有信息量的结果 if text2.startswith("[ERROR_SELENIUM"): # 将两个错误拼接,便于审计 return f"{text} | {text2}" # 如果 Selenium 成功或者有更长文本,优先返回 Selenium if text2 != "[NO TEXT]" and len(text2) >= len(text): return text2 return text # ==== Process CSV with real-time saving ==== def process_csv(): driver = init_selenium_driver() # 可能返回 None try: with open(INPUT_FILE, newline="", encoding="utf-8") as infile, \ open(OUTPUT_FILE, "a", newline="", encoding="utf-8") as outfile: reader = csv.reader(infile) writer = csv.writer(outfile) # 若是新文件,写表头 if outfile.tell() == 0: writer.writerow(["id", "url", "text"]) # 跳过输入表头 header = next(reader, None) for row in reader: if len(row) < 2: continue id_, url = row[0], row[1] print(f"正在爬取: {url}") result_text = fetch_text(url, driver) writer.writerow([id_, url, result_text]) outfile.flush() # 实时落盘 time.sleep(PAUSE_BETWEEN_REQUESTS) finally: if driver is not None: try: driver.quit() except Exception: pass if __name__ == "__main__": process_csv() 总结介绍这个代码
09-25
bl_info = { "name": "Export Geometry Nodes to Python (Enhanced & Fixed)", "author": "Your Name", "version": (2, 3), "blender": (4, 5, 3), "location": "View3D > Sidebar > Item Tab", "description": "Exports Geometry Nodes with nested groups and external resources to a standalone Python script.", "category": "Object", } import bpy import os import shutil from pathlib import Path from bpy_extras.io_utils import ExportHelper from bpy.props import StringProperty, BoolProperty from bpy.types import Panel, Operator # ====================== # 工具函数 # ====================== def ensure_dir(path): """确保目录存在""" Path(path).mkdir(parents=True, exist_ok=True) def copy_resource(src_path, dst_folder): """复制资源文件到目标目录,返回相对于脚本的路径字符串""" if not src_path: return None abs_path = bpy.path.abspath(src_path) if not os.path.exists(abs_path): print(f"资源不存在,跳过: {abs_path}") return None filename = os.path.basename(abs_path) dst_path = os.path.join(dst_folder, filename) if not os.path.exists(dst_path): shutil.copy(abs_path, dst_path) return f"resources/{filename}" # 定义应跳过的只读或敏感属性 SKIP_ATTRS = { 'name', 'label', 'location', 'parent', 'bl_idname', 'bl_label', 'bl_rna', 'rna_type', 'inputs', 'outputs', 'internal_links', 'dimensions', 'draw_buttons', 'draw_buttons_ext', 'poll', 'poll_instance', 'is_registered_node_type', 'show_options', 'show_preview', 'show_texture', 'width', 'height', 'width_hidden', 'mute', 'hide', 'hide_value', 'is_active_output', 'is_multi_input', # ⚠️ 关键只读属性(禁止写入!) 'bl_static_type', 'type', 'socket_type', 'image', 'color_ramp', 'node_tree', # 特殊处理,不在通用属性中写 } # 允许安全 repr 的基本类型 SAFE_TYPES = (int, float, str, bool, tuple, list, Color) def is_safe_attribute(node, attr): """ 判断一个节点属性是否可以安全地读取并写入到脚本中 """ if attr.startswith('_') or attr in SKIP_ATTRS: return False try: val = getattr(node, attr) except Exception: return False if callable(val): return False if isinstance(val, bpy.types.bpy_struct): return False if type(val) not in SAFE_TYPES: return False return True def write_node_group_recursive(node_group, filepath, exported_groups=None, node_counter=None): """ 递归导出几何节点组及其嵌套子组 :param node_group: 要导出的节点组 :param filepath: 输出的 .py 文件路径 :param exported_groups: 已导出组名集合,防止重复 :param node_counter: 全局节点计数器,避免变量名冲突 """ if exported_groups is None: exported_groups = set() if node_counter is None: node_counter = {'count': 0} # 引用传递实现“全局”计数 # 防止重复导出 if node_group.name in exported_groups: return exported_groups.add(node_group.name) base_dir = Path(filepath).parent resource_dir = str(base_dir / "resources") ensure_dir(resource_dir) group_name_safe = node_group.name.replace(" ", "_") with open(filepath, 'a', encoding='utf-8') as f: f.write(f"\n# ========== 节点组: {node_group.name} ==========\n") f.write(f"if '{group_name_safe}' in bpy.data.node_groups:\n") f.write(f" ng_{group_name_safe} = bpy.data.node_groups['{group_name_safe}']\n") f.write(f"else:\n") f.write(f" ng_{group_name_safe} = bpy.data.node_groups.new('{group_name_safe}', 'GeometryNodeTree')\n\n") # ============ 写入输入接口 ============ f.write("# 输入接口\n") for item in node_group.interface.items_tree: if item.in_out != 'INPUT': continue socket_type = getattr(item, "socket_type", "NodeSocketUnknown") default_value = getattr(item, "default_value", None) dv_repr = repr(default_value) if default_value is not None else "None" f.write(f"sock = ng_{group_name_safe}.interface.new_socket(\n") f.write(f" name='{item.name}',\n") f.write(f" in_out='INPUT',\n") f.write(f" socket_type='{socket_type}'\n") f.write(f")\n") if default_value is not None: f.write(f"sock.default_value = {dv_repr}\n") f.write("\n") # ============ 写入输出接口 ============ f.write("# 输出接口\n") for item in node_group.interface.items_tree: if item.in_out != 'OUTPUT': continue socket_type = getattr(item, "socket_type", "NodeSocketUnknown") default_value = getattr(item, "default_value", None) dv_repr = repr(default_value) if default_value is not None else "None" f.write(f"sock = ng_{group_name_safe}.interface.new_socket(\n") f.write(f" name='{item.name}',\n") f.write(f" in_out='OUTPUT',\n") f.write(f" socket_type='{socket_type}'\n") f.write(f")\n") if default_value is not None: f.write(f"sock.default_value = {dv_repr}\n") f.write("\n") # ============ 写入节点 ============ f.write("# 添加节点\n") node_map = {} # 映射 nodeName -> varName for node in node_group.nodes: var_name = f"node_{node_counter['count']}" node_counter['count'] += 1 node_map[node.name] = var_name f.write(f"{var_name} = ng_{group_name_safe}.nodes.new('{node.bl_idname}')\n") f.write(f"{var_name}.name = '{node.name}'\n") if node.label: f.write(f"{var_name}.label = '{node.label}'\n") f.write(f"{var_name}.location = ({node.location.x}, {node.location.y})\n") # 特殊节点:限制属性写入范围(Group Input/Output, Reroute) SPECIAL_NODES = {'NodeGroupInput', 'NodeGroupOutput', 'NodeReroute'} if node.bl_idname not in SPECIAL_NODES: # 正常写入通用属性 for attr in dir(node): if is_safe_attribute(node, attr): try: val = getattr(node, attr) f.write(f"{var_name}.{attr} = {repr(val)}\n") except Exception as e: print(f"无法写入属性 {node.name}.{attr}: {e}") # 手动设置 use_custom_color 和 color if hasattr(node, 'use_custom_color') and node.use_custom_color: f.write(f"{var_name}.use_custom_color = True\n") f.write(f"{var_name}.color = {list(node.color)}\n") # 特殊处理:图像纹理 if hasattr(node, 'image') and node.image and node.image.source == 'FILE': src_path = node.image.filepath rel_path = copy_resource(src_path, resource_dir) if rel_path: f.write(f"{var_name}.image = bpy.data.images.load(r'{{script_dir}}/{rel_path}', check_existing=True)\n") # 特殊处理:颜色渐变 if hasattr(node, 'color_ramp') and node.color_ramp: cr = node.color_ramp f.write(f"{var_name}.color_ramp.color_mode = '{cr.color_mode}'\n") f.write(f"{var_name}.color_ramp.interpolation = '{cr.interpolation}'\n") if len(cr.elements) > 0: elem0 = cr.elements[0] f.write(f"{var_name}.color_ramp.elements[0].position = {elem0.position}\n") f.write(f"{var_name}.color_ramp.elements[0].color = {list(elem0.color)}\n") if len(cr.elements) > 1: elem1 = cr.elements[1] f.write(f"{var_name}.color_ramp.elements[1].position = {elem1.position}\n") f.write(f"{var_name}.color_ramp.elements[1].color = {list(elem1.color)}\n") # 设置未连接的输入默认值 for i, inp in enumerate(node.inputs): if inp.is_linked or not hasattr(inp, 'default_value'): continue try: dv = inp.default_value f.write(f"{var_name}.inputs[{i}].default_value = {repr(dv)}\n") except Exception as e: print(f"无法写入输入默认值 {node.name}.inputs[{i}]: {e}") # 递归处理嵌套节点组 if hasattr(node, 'node_tree') and node.node_tree is not None: nested_ng = node.node_tree write_node_group_recursive(nested_ng, filepath, exported_groups, node_counter) nested_name_safe = nested_ng.name.replace(" ", "_") f.write(f"{var_name}.node_tree = bpy.data.node_groups['{nested_name_safe}']\n") # ============ 写入连接 ============ f.write(f"\n# 建立连接 - {node_group.name}\n") for link in node_group.links: if not link.is_valid: continue from_var = node_map.get(link.from_node.name) to_var = node_map.get(link.to_node.name) if not from_var or not to_var: print(f"跳过无效连接: {link.from_node.name} -> {link.to_node.name}") continue from_sock_id = link.from_socket.identifier to_sock_id = link.to_socket.identifier f.write(f"ng_{group_name_safe}.links.new({from_var}.outputs['{from_sock_id}'], {to_var}.inputs['{to_sock_id}'])\n") f.write(f"\nprint('✅ 成功重建节点组:', ng_{group_name_safe}.name)\n") class OBJECT_OT_export_geometry_nodes_to_python(Operator, ExportHelper): """将几何节点树导出为包含嵌套组与资源的Python脚本""" bl_idname = "object.export_geometry_nodes_to_python" bl_label = "Export to Python Script" bl_options = {'REGISTER', 'UNDO'} filename_ext: StringProperty(default=".py") filter_glob: StringProperty(default="*.py", options={'HIDDEN'}) use_relative_path: BoolProperty( name="Use Relative Paths in Script", description="Generate script that uses relative paths for resources like images", default=True ) def execute(self, context): obj = context.active_object if not obj: self.report({'ERROR'}, "❌ 没有选中对象") return {'CANCELLED'} mod = None for m in obj.modifiers: if m.type == 'NODES' and m.node_group is not None: mod = m break if not mod: self.report({'ERROR'}, "❌ 选中对象没有有效的几何节点修改器") return {'CANCELLED'} node_group = mod.node_group filepath = self.filepath if not filepath.endswith(".py"): filepath += ".py" # 清空旧文件 if os.path.exists(filepath): os.remove(filepath) # 初始化全局状态 node_counter = {'count': 0} exported_groups = set() try: write_node_group_recursive(node_group, filepath, exported_groups, node_counter) except Exception as e: self.report({'ERROR'}, f"❌ 导出失败: {str(e)}") import traceback print(traceback.format_exc()) return {'CANCELLED'} # ========== 构建最终内容:导入 + 设置 + 内容 + 应用 ========== with open(filepath, 'r', encoding='utf-8') as f: content = f.read() imports = "import bpy\nimport os\nfrom mathutils import Color\n\n" setup_code = "" if self.use_relative_path: setup_code = ( "# 自动设置脚本所在目录为工作目录\n" "script_dir = os.path.dirname(__file__)\n" "os.chdir(script_dir)\n" "\n" ) else: setup_code = "# 注意:资源路径可能为绝对路径\n\n" # 替换模板路径标记 content = content.replace("{script_dir}", "script_dir") root_group_safe = node_group.name.replace(" ", "_") apply_code = f"\n\n# ========== 应用到当前对象 ==========\n" apply_code += "obj = bpy.context.active_object\n" apply_code += "if obj:\n" apply_code += f" mod = obj.modifiers.get('{mod.name}')\n" apply_code += f" if mod:\n" apply_code += f" mod.node_group = bpy.data.node_groups['{root_group_safe}']\n" apply_code += " print('✅ 节点组已成功应用到:', obj.name)\n" apply_code += "else:\n" apply_code += " print('⚠️ 未找到活动对象')\n" final_content = imports + setup_code + content + apply_code with open(filepath, 'w', encoding='utf-8') as f: f.write(final_content) self.report({'INFO'}, f"✅ 成功导出几何节点脚本!\n保存位置:\n{filepath}") return {'FINISHED'} def invoke(self, context, event): if not self.filepath: blend_path = bpy.data.filepath self.filepath = bpy.path.ensure_ext(blend_path if blend_path else "geometry_nodes_export", ".py") context.window_manager.invoke_props_dialog(self) return {'RUNNING_MODAL'} class VIEW3D_PT_export_geometry_nodes_panel(Panel): """在N面板显示导出按钮""" bl_label = "导出几何节点" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' bl_category = 'Item' def draw(self, context): layout = self.layout obj = context.active_object if not obj: layout.label(text="⚠️ 请选中一个对象", icon='INFO') return mod_found = any(m.type == 'NODES' and m.node_group for m in obj.modifiers) if not mod_found: layout.label(text="🚫 无有效几何节点修改器", icon='MODIFIER') else: col = layout.column(align=True) col.scale_y = 1.2 col.operator(OBJECT_OT_export_geometry_nodes_to_python.bl_idname, icon='FILE_SCRIPT') # ================ # 注册/注销 # ================ classes = ( OBJECT_OT_export_geometry_nodes_to_python, VIEW3D_PT_export_geometry_nodes_panel, ) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in reversed(classes): bpy.utils.unregister_class(cls) if __name__ == "__main__": register() 修改代码解决NameError: name 'Color' is not defined错误,给我完整无误的代码。
最新发布
11-15
<template> <div class="data-collection-container"> <!-- 项目信息表单 --> <div class="card-header"> <span>项目信息</span> </div> <el-form :model="projectInfo" label-width="120px" class="project-form"> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="项目名称:"> <el-input v-model="projectInfo.name" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="项目编码:"> <el-input v-model="projectInfo.code" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="采集目的:"> <el-input v-model="projectInfo.purpose" readonly /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="参与者姓名:"> <el-input v-model="projectInfo.participantName" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="参与者手机:"> <el-input v-model="projectInfo.participantPhone" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="设备名称:"> <el-input v-model="projectInfo.deviceName" readonly /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="设备类型:"> <el-input v-model="projectInfo.deviceType" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="采集文件号:"> <el-input v-model="projectInfo.collectionFileNumber" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="设备类别:"> <el-input v-model="projectInfo.deviceCategory" readonly /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="开始时间:"> <el-input v-model="projectInfo.startTime" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="业务与场景:"> <el-input v-model="projectInfo.businessScene" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="采集地域:"> <el-input v-model="projectInfo.collectionRegion" readonly /> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="数据文件名:"> <el-input v-model="projectInfo.dataFileName" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="上传来源:"> <el-input v-model="projectInfo.uploadSource" readonly /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="QT报告:"> <el-input v-model="projectInfo.qtReport" readonly /> </el-form-item> </el-col> </el-row> </el-form> <!-- 数据采集记录表格 --> <div class="table-header"> <span>数据采集记录</span> <div class="header-actions"> <el-input v-model="searchKeyword" placeholder="搜索关键字" style="width: 200px; margin-right: 10px" clearable /> <el-select v-model="filterStatus" placeholder="采集状态" clearable> <el-option label="已覆盖" value="已覆盖" /> <el-option label="覆盖中" value="覆盖中" /> </el-select> </div> </div> <el-table :data="filteredData" stripe style="width: 100%" v-loading="loading" > <el-table-column prop="source" label="来源" width="80" /> <el-table-column prop="filename" label="文件名" width="100"> <template #default="{ row }"> {{ row.filename }}... </template> </el-table-column> <el-table-column prop="status" label="采集状态" width="100"> <template #default="{ row }"> <el-tag :type="row.status === '已覆盖' ? 'success' : 'warning'" size="small" > {{ row.status }} </el-tag> </template> </el-table-column> <el-table-column prop="projectName" label="项目名称" min-width="120" /> <el-table-column prop="projectCode" label="项目编码" width="110" /> <el-table-column prop="purpose" label="采集目的" min-width="120" /> <el-table-column prop="participantId" label="参与者身份" width="100" /> <el-table-column prop="content" label="内容" width="80" /> <el-table-column prop="deviceCategory" label="设备类别" width="100" /> <el-table-column prop="deviceName" label="设备名" min-width="120" /> <el-table-column prop="deviceType" label="设备类型" min-width="120" /> <el-table-column prop="business" label="业务" width="100" /> <el-table-column prop="scene" label="场景" width="100" /> <el-table-column prop="region" label="地域" width="80" /> <el-table-column prop="startTime" label="采集开始时间" width="150" /> <el-table-column prop="endTime" label="采集结束时间" width="150" /> <el-table-column prop="other" label="其他" width="80" /> </el-table> <div class="pagination-container"> <el-pagination :page-size="10" :current-page="currentPage" layout="total, prev, pager, next" :total="filteredData.length" /> </div> </div> </template> <script setup lang="ts"> import { ref, computed, onMounted, reactive } from 'vue' // 项目信息接口 interface ProjectInfo { name: string code: string purpose: string participantName: string participantPhone: string deviceName: string deviceType: string collectionFileNumber: string deviceCategory: string startTime: string businessScene: string collectionRegion: string dataFileName: string uploadSource: string qtReport: string } // 表格数据接口 interface TableDataItem { source: string filename: string status: string projectName: string projectCode: string purpose: string participantId: string content: string deviceCategory: string deviceName: string deviceType: string business: string scene: string region: string startTime: string endTime: string other: string } // 项目信息 const projectInfo = reactive<ProjectInfo>({ name: '插入关键字检索', code: '插入关键字检索', purpose: '插入关键字检索', participantName: '苏州 赵小倩/赵婷', participantPhone: '159777785', deviceName: '插入关键字检索', deviceType: '移动硬盘监控范围', collectionFileNumber: '参与者初见地址', deviceCategory: '1S 1S4', startTime: '开站时间', businessScene: '业务场景', collectionRegion: '参与者的信息域', dataFileName: '上传来源:App Web', uploadSource: 'App Web', qtReport: 'QT报告 Q-报告' }) // 搜索和筛选 const searchKeyword = ref<string>('') const filterStatus = ref<string>('') const currentPage = ref<number>(1) const loading = ref<boolean>(true) // 模拟数据 const tableData = ref<TableDataItem[]>([ { source: 'App', filename: 'K5', status: '已覆盖', projectName: 'Trailer950.0', projectCode: '202501...', purpose: 'FTP自动池', participantId: '749856...', content: '1', deviceCategory: '1', deviceName: 'Ultimate-DCD', deviceType: '华为穿戴', business: '远端电源', scene: '百度地图', region: '腾讯', startTime: '2023-12-24 12:12:00', endTime: '2023-12-24 12:12:00', other: '重启' }, { source: 'Web', filename: 'K5', status: '已覆盖', projectName: 'Mesa项目', projectCode: '202501...', purpose: 'FTP自动池', participantId: '749856...', content: '1', deviceCategory: '1', deviceName: '云端', deviceType: '易品', business: '高尔夫', scene: '百度地图', region: '百度', startTime: '2023-12-24 12:12:00', endTime: '2023-12-24 12:12:00', other: '重启' } ]) // 计算筛选后的数据 const filteredData = computed(() => { let result = tableData.value if (filterStatus.value) { result = result.filter((item) => item.status === filterStatus.value) } if (searchKeyword.value) { const keyword = searchKeyword.value.toLowerCase() result = result.filter( (item) => item.projectName.toLowerCase().includes(keyword) || item.purpose.toLowerCase().includes(keyword) || item.deviceName.toLowerCase().includes(keyword) || item.deviceType.toLowerCase().includes(keyword) ) } return result }) // 模拟加载 onMounted(() => { setTimeout(() => { loading.value = false }, 800) }) </script> <style scoped> .data-collection-container { padding: 20px; background-color: #f5f7fa; min-height: 100vh; } .info-card { margin-bottom: 20px; } .card-header { font-weight: bold; font-size: 16px; } .project-form { padding: 10px; } :deep(.el-form-item__label) { font-weight: bold; color: #606266; } :deep(.el-input__inner) { background-color: #f5f7fa; border: none; color: #303133; } .table-card { border-radius: 4px; } .table-header { display: flex; justify-content: space-between; align-items: center; } .header-actions { display: flex; } .pagination-container { margin-top: 20px; display: flex; justify-content: flex-end; } :deep(.el-card__header) { background-color: #f5f7fa; border-bottom: 1px solid #ebeef5; } </style> w我没加啊
09-18
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值