📖 项目简介KNav 是一个纯前端的浏览器新标签页起始页，把时钟、搜索、快捷入口和壁纸整合到一个干净的页面上。🌐 在线体验 💻 开源地址✨ 功能特性🔍 多搜索引擎 —— 内置多个搜索源，支持新增、编辑、删除、拖拽排序与启用/禁用🕘 搜索历史 —— 记录最近搜索，支持查看与一键清空⏰ 数字时钟 —— 支持 12/24 小时制、星期显示、秒钟显示🎨 多种壁纸 —— 纯色、渐变、Bing 每日/随机、本地图片四种模式🖌️ 渐变编辑器 —— 支持 HEX / RGB 取色、多色停靠点与方向调整👓 背景可读性 —— 根据壁纸自动调整蒙层、文字颜色与毛玻璃效果⭐ 快捷入口 —— 预设 + 自定义，支持 Iconify 图标、拖拽排序与启用/禁用🌍 多语言 —— 简体中文 / English，可跟随系统🌗 主题切换 —— 深色 / 浅色 / 跟随系统📤 配置导入导出 —— 一键备份与恢复，包含本地上传的壁纸� 本地存储 —— 数据保存在浏览器本地，纯前端离线运行� 响应式布局 —— 适配桌面与移动端🧩 技术栈分类技术框架React 19构建Vite 6语言TypeScript 5样式Tailwind CSS 4UI 基础组件Radix UI图标Iconify + Lucide状态管理Zustand路由React Router 7拖拽排序dnd-kit虚拟列表TanStack Virtual提示Sonner国际化i18next + react-i18next存储IndexedDB + localStorage🚀 快速开始项目使用 pnpm 作为包管理器。克隆项目git clone https://github.com/kindyear/KNav.git cd KNav安装依赖pnpm install启动开发服务器pnpm dev构建生产版本pnpm build本地预览构建产物pnpm preview其他脚本：pnpm lint # 代码检查 pnpm format # 代码格式化 pnpm typecheck # 类型检查📂 项目结构src/ ├── app/ # 应用根组件 ├── assets/ # 静态资源 ├── components/ # UI 组件（首页、设置、图标系统、基础组件） ├── config/ # 默认配置与常量（设置、壁纸、可读性等） ├── features/ # 业务功能模块（时钟、搜索、快捷入口） ├── hooks/ # 通用 React Hooks ├── layouts/ # 页面布局 ├── lib/ # 底层库（配置导入导出、i18n、工具） ├── locales/ # 多语言资源（zh-CN / en-US） ├── providers/ # 全局 Provider 与副作用 ├── router/ # 路由定义 ├── services/ # 数据与业务服务（壁纸、主题、可读性等） ├── stores/ # Zustand 状态仓库 ├── styles/ # 全局样式与设计 Token ├── types/ # TypeScript 类型定义 └── utils/ # 工具函数⚙️ 配置说明KNav 无需任何环境变量或后端配置即可运行，所有用户配置均在界面「设置」中完成，并持久化到浏览器本地。配置项说明通用语言、主题、时间格式、日期格式、星期与秒钟显示、自动聚焦搜索、Enter 打开方式搜索搜索源的增删改、排序、启用/禁用壁纸纯色 / 渐变 / Bing / 本地图片，以及背景可读性相关选项快捷入口图标、名称、链接的增删改与排序数据导入配置、导出配置、恢复默认、清空本地数据导出的配置文件采用统一的版本化格式，包含全部用户配置（含本地上传的壁纸），可在其他设备上完整导入恢复。关于 Bing 壁纸的代理Bing 的图片接口不返回 CORS 头，浏览器无法直接请求，因此项目通过同源路径 /bing-api 转发到 https://www.bing.com：开发环境：已在 vite.config.ts 的 server.proxy 中配置，开箱即用。生产环境：需要在你的反向代理（如 Nginx、CDN）中把 /bing-api 转发到 https://www.bing.com，否则 Bing 壁纸会请求失败。❓ 常见问题部署后 Bing 壁纸请求 404？Bing 壁纸依赖 /bing-api 代理。该代理仅在开发服务器中生效，生产环境需要在反向代理里手动配置转发（见上文「关于 Bing 壁纸的代理」）。如何修改默认搜索引擎？进入「设置 → 搜索」，可以新增自定义搜索源、编辑现有搜索源、拖拽排序，并启用或禁用任意搜索源。数据保存在哪里？会上传吗？不会上传。本地上传的壁纸（二进制）保存在 IndexedDB，其余配置（通用设置、搜索源、快捷入口、搜索历史等）保存在 localStorage，全部数据仅存在于当前浏览器。换电脑或换浏览器后如何迁移配置？在「设置 → 数据」中导出配置文件，然后在新环境导入即可，导出内容包含本地上传的壁纸。📄 License本项目采用 KNav Community License Version 1.0。✅ 允许个人、教育及非商业用途的使用、复制、修改与分发✅ 允许 Fork 与二次修改（需保留原始版权声明并注明改动）❌ 未经授权禁止任何形式的商业用途完整条款见 LICENSE。如需商业授权，请联系 me@kindyear.cn。
✨ AI摘要：本教程详细介绍了如何将Chevereto图床迁移至兰空图床，主要针对本地存储类型。迁移步骤包括安装兰空图床、备份旧站点数据、配置数据库连接、编写Python脚本进行数据迁移、上传图片文件夹以及设置文件权限。最后，提供了Nginx重定向配置，以便保留旧站点地址并自动重定向到新站点。整个过程确保数据完整性和访问顺畅。Powered by SparkU AI Platform本教程针对的图片存储类型主要为本地存储Chevereto版本为Free 1.3.0版本兰空图床版本为开源版2.1版本前期准备在新站点地址上安装好兰空图床程序备份旧站点（Chevereto）的数据库和网站目录并下载到本地准保好新旧站点的MySQL数据库连接信息电脑安装好Python环境（推荐3.11版本）并使用pip安装pymysql库pip install pymysql迁移过程解压备份下载好的Chevereto程序，找到里面的images文件夹，在与images文件夹同级的目录下创建一个Python脚本文件app.py内容如下，请阅读注释并修改对应的内容import os import hashlib import pymysql from datetime import datetime # ===== 数据库配置 ===== CHEVERETO_DB = { "host": "旧数据库地址", "user": "数据库用户名", "password": "数据库密码", "database": "数据库", "charset": "utf8mb4" } LSKY_DB = { "host": "新数据库地址", "user": "数据库用户名", "password": "数据库密码", "database": "数据库", "charset": "utf8mb4" } CHEVERETO_STORAGE_PATH = "images" # 本地存储路径 # ===== 文件哈希 ===== def calc_hash(file_path): md5_hash = hashlib.md5() sha1_hash = hashlib.sha1() try: with open(file_path, "rb") as f: for chunk in iter(lambda: f.read(8192), b""): md5_hash.update(chunk) sha1_hash.update(chunk) return md5_hash.hexdigest(), sha1_hash.hexdigest() except FileNotFoundError: print(f"[WARN] 文件不存在: {file_path}") return None, None EXT_MIME_MAP = { "jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png", "gif": "image/gif", "webp": "image/webp" } def get_mimetype(ext): return EXT_MIME_MAP.get(ext.lower(), f"image/{ext.lower()}") # ===== 更新专辑图片数量（避免负数） ===== def update_album_image_num(lsky_cur, album_id, delta): if delta < 0: lsky_cur.execute( "UPDATE albums SET image_num = GREATEST(image_num + %s, 0) WHERE id = %s", (delta, album_id) ) else: lsky_cur.execute( "UPDATE albums SET image_num = image_num + %s WHERE id = %s", (delta, album_id) ) # ===== 迁移逻辑 ===== def migrate(): che_conn = pymysql.connect(**CHEVERETO_DB) lsky_conn = pymysql.connect(**LSKY_DB) che_cur = che_conn.cursor(pymysql.cursors.DictCursor) lsky_cur = lsky_conn.cursor() che_cur.execute("SELECT * FROM chv_images") rows = che_cur.fetchall() insert_sql = """ INSERT INTO images ( user_id, album_id, group_id, strategy_id, `key`, `path`, `name`, origin_name, alias_name, size, mimetype, extension, md5, sha1, width, height, permission, is_unhealthy, uploaded_ip, created_at, updated_at ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s ) """ log_file = open("migrate_error.log", "w", encoding="utf-8") for row in rows: date_path = row["image_date"].strftime("%Y/%m/%d") filename = f"{row['image_name']}.{row['image_extension']}" file_path = os.path.join(CHEVERETO_STORAGE_PATH, date_path, filename) md5, sha1 = calc_hash(file_path) if not md5: log_file.write(f"缺失文件: {file_path}\n") continue mimetype = get_mimetype(row["image_extension"]) key = row["image_name"] created_updated_time = row["image_date"].replace(hour=0, minute=0, second=0, microsecond=0) date_str = created_updated_time.strftime("%Y-%m-%d %H:%M:%S") data = ( 1, 1, 1, 1, # 这里的四个数字对应着四个ID，分别是user_id、album_id、group_id和strategy_id，请根据实际情况进行调整，如果不知道怎么获取请看兰空图床后台中的接口部分的说明 key, date_path, filename, row["image_original_filename"], row["image_title"] or "", round(row["image_size"]/1024, 2), mimetype, row["image_extension"], md5, sha1, row["image_width"], row["image_height"], 0, 0, "0.0.0.0", date_str, date_str # 这里是默认上传IP地址，如有需要请自行替换 ) s try: lsky_cur.execute(insert_sql, data) update_album_image_num(lsky_cur, 1, 1) # 成功添加时增加数量 except pymysql.err.IntegrityError as e: if "Duplicate entry" in str(e): new_key = f"{row['image_name']}_{row['image_id']}" data = list(data) data[4] = new_key try: lsky_cur.execute(insert_sql, tuple(data)) update_album_image_num(lsky_cur, 1, 1) except Exception as e2: log_file.write(f"再次插入失败 {filename}: {e2}\n") else: log_file.write(f"插入失败 {filename}: {e}\n") except Exception as e: log_file.write(f"插入失败 {filename}: {e}\n") lsky_conn.commit() print("[OK] 迁移完成") log_file.close() che_cur.close() lsky_cur.close() che_conn.close() lsky_conn.close() if __name__ == "__main__": migrate() 然后运行该脚本进行数据迁移python app.py然后将Chevereto里面的images的文件夹内的所有年份文件夹上传到新站点的/storage/app/uploads内最后请记住将这里面所有年份的文件夹和子文件夹权限设置为和程序主题一致的权限，例如755/www迁移完成重定向如果你还想保留旧的站点地址但是想重定向到新站点的地址，若您使用Nginx作为Web服务，在旧站点中的重定向配置文件部分使用下面的配置：location ~ ^/images/(.*)$ { return 301 https://新站点地址/i/$1; } location / { return 301 https://新站点地址; }访问旧站点的图片时会被301自动永久重定向到新站点的地址和路径上至此完整的迁移流程已经结束
✨ AI摘要：ZITADEL是一个开源身份和访问管理（IAM）平台，特别适合云原生应用，支持多个身份验证协议并提供细粒度权限控制。本文介绍了在宝塔环境中使用Docker部署ZITADEL的步骤，包括所需的依赖、Docker配置、PostgreSQL配置和反向代理设置。通过这些步骤，用户能够高效构建和管理跨平台的用户系统，提升系统安全性和管理便利性。Powered by SparkU AI Platform前言什么是ZITADELZITADEL 是一个开源的身份和访问管理（IAM）平台，专为现代云原生应用设计。它提供用户身份验证、授权和管理功能，支持多种身份验证协议（如 OAuth 2.0、OIDC、SAML），并允许开发者轻松集成到他们的应用中。ZITADEL 强调安全性、隐私性和可扩展性，提供细粒度的权限控制和强大的审计跟踪。它可以自托管或作为 SaaS 服务使用，适用于各种规模的企业和组织，帮助他们简化身份管理并增强安全性。为什么要用ZITADEL本人在开发一个系列项目时，需要用到跨平台，跨网站的用户系统，如果单独为每一个项目开发一套用户系统，所耗费的时间成本和互通成本是极其高昂，而且这些项目均为一个总系列产品，为了更好的提供用户服务，故使用ZITADEL服务作为我们本地化部署的用户管理系统。过程依赖准备我使用的是宝塔环境 + NGINX + Docker形式部署宝塔NGINX负责反向代理ZITADEL，Docker运行ZITADEL，连接到宿主机的PostgreSQL服务器需安装以下依赖服务PostgreSQL（>=14.0）NginxDockerDocker ComposeDocker配置准备好一个文件夹，在文件夹内放置下面这些配置文件docker-compose.yamlservices: zitadel: restart: "always" network_mode: "host" # 使用宿主机的网络，为了连接宿主机的PostgreSQL image: "ghcr.io/zitadel/zitadel:latest" command: 'start-from-init --config /example-zitadel-config.yaml --config /example-zitadel-secrets.yaml --steps /example-zitadel-init-steps.yaml --masterkey {32位key} --tlsMode disabled' # 这里替换为32字节长度的masterkey，tlsMode建议设置为external ports: - "8080:8080" volumes: - "./example-zitadel-config.yaml:/example-zitadel-config.yaml:ro" - "./example-zitadel-secrets.yaml:/example-zitadel-secrets.yaml:ro" - "./example-zitadel-init-steps.yaml:/example-zitadel-init-steps.yaml:ro" volumes: data:官方文档中对tlsMode的解释：TLS ModesTo run ZITADEL on any kind of infrastructure, you can configure on how to handle TLS connections. There are three modes of operation: disabled, external, enabled.Generally this command is set as argument while starting ZITADEL. For example like this:zitadel start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabledDisabledWith the mode disabled, you instruct ZITADEL to await all connections with plain http without TLS.cautionBe aware this is not a secure setup and should only be used for test systems!ExternalThe mode external allows you to configure ZITADEL in such a way that it will instruct its clients to use https. However ZITADEL delegates the management of TLS connections to a reverseproxy, web application firewall or a service mesh.EnabledWhen using the mode enabled ZITADEL is setup to await incoming connections in an encrypted fashion. Whether it is from a client directly, a reverse proxy or web application firewall. This allows HTTP connections to be secured at the transport level the whole way.example-zitadel-config.yaml# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml Log: Level: 'info' # Make ZITADEL accessible over HTTP, not HTTPS # 如果你直接部署到正式环境，拥有正式域名和Https，请修改 ExternalDomain: '正式域名地址，不带协议头' ExternalPort: '正式域名的端口，https使用443，不带单引号' ExternalSecure: true # If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL Database: postgres: Host: '0.0.0.0' # 修改为宿主机的IP地址 Port: 5432 # 宿主机PostgreSQL的端口 Database: '数据库' Password: '数据库密码' User: SSL: Mode: 'disable' Admin: SSL: Mode: 'disable'example-zitadel-init-steps.yaml# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/setup/steps.yaml FirstInstance: Org: Human: # use the loginname root@zitadel.localhost # 你的超级管理员用户名和密码，密码需要含有数字大小写和字符 Username: 'user' Password: 'password'example-zitadel-secrets.yaml# All possible options and their defaults: https://github.com/zitadel/zitadel/blob/main/cmd/defaults.yaml # If not using the docker compose example, adjust these values for connecting ZITADEL to your PostgreSQL Database: postgres: User: # If the user doesn't exist already, it is created # PostgreSQL的用户，用于用户权限，在后面的PostgreSQL配置内创建和设置权限，用户名请根据实际情况自行修改 Username: 'user' Password: 'password' Admin: # PostgreSQL的用户，用于管理员权限，在后面的PostgreSQL配置内创建和设置权限，用户名请根据实际情况自行修改 Username: 'admin' Password: 'password'配置完成后在当前目录运行以下命令，即可创建容器，就可以在宝塔面板内看见容器了docker compose up -dPostgreSQL配置创建用户和授予权限CREATE USER user WITH PASSWORD 'password'; CREATE USER admin WITH PASSWORD 'password' CREATEDB CREATEROLE; GRANT ALL PRIVILEGES ON DATABASE {数据库名称} TO user;在客户端认证配置文件内添加来源和权限# Zitadel connections: host {数据库名称} admin {宿主机IP地址}/32 scram-sha-256 host {数据库名称} user {宿主机IP地址}/32 scram-sha-256 host postgres admin {宿主机IP地址}/32 scram-sha-256NGINX反向代理配置将发送域名要设置为和example-zitadel-config.yaml内ExternalDomain一致的域名，不带协议头运行登录启动Docker后，设置好反向代理，查看日志出现如下所示的内容后即代表启动成功，就可以通过设置好的域名进行访问_____ ___ _____ _ ____ _____ _ |__ / |_ _| |_ _| / \ | _ \ | ____| | | / / | | | | / _ \ | | | | | _| | | / /_ | | | | / ___ \ | |_| | | |___ | |___ /____| |___| |_| /_/ \_\ |____/ |_____| |_____| =============================================================== Version : v2.71.1 TLS enabled : false External Secure : false Machine Id Method : Private Ip Console URL : http://192.168.0.8:8080/ui/console Health Check URL : http://192.168.0.8:8080/debug/healthz Warning: you're using plain http without TLS. Be aware this is not a secure setup and should only be used for test systems. Visit: https://zitadel.com/docs/self-hosting/manage/tls_modes =============================================================== time="2025-03-07T07:04:01Z" level=info msg="auth request cache disabled" caller="/home/runner/work/zitadel/zitadel/internal/auth_request/repository/cache/cache.go:31" error="must provide a positive size" time="2025-03-07T07:04:01Z" level=info msg="auth request cache disabled" caller="/home/runner/work/zitadel/zitadel/internal/auth_request/repository/cache/cache.go:36" error="must provide a positive size" time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/authorize time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/device_authorization time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/token time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/introspect time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oidc/v1/userinfo time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/revoke time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oidc/v1/end_session time=2025-03-07T07:04:01.120Z level=INFO msg="registered route" endpoint=/oauth/v2/keys time="2025-03-07T07:04:01Z" level=info msg="server is listening on [::]:8080" caller="/home/runner/work/zitadel/zitadel/cmd/start/start.go:605"登录用户名是这个格式：{yaml内设置的用户名}@zitadel.{你的域名地址}，密码就是你之前设置的用户名首次登录可能需要你修改密码，修改完成登录后就可以看到控制台咯参考https://zitadel.com/docs
浅浅记录下使用OpenArk工具排查Windows 11组合键冲突问题
✨ AI摘要：本文记录了使用OpenArk工具排查Windows 11组合键冲突的过程。作者日常使用Snipaste截图工具，因快捷键无法正常调用而寻找解决方案。OpenArk是一款开源逆向分析工具，可以用于检查系统热键。文章详细介绍了OpenArk的安装步骤及使用方法，包括如何进入内核模式和查找被占用的快捷键。最终，作者成功找到并解除与Parsec的快捷键冲突。Powered by SparkU AI Platform前言我平日是个截图工具重度使用者，日常使用的截图工具一直是Snipaste，而我将截图快捷键绑定为Ctrl+F1，甚至鼠标的侧键也绑定了这个组合键。而在近期突然发现我的截图工具无法正常调用于是乎去工具设置内检查突然发现这个组合键直接绑定不上去，起初我以为是键盘出了问题但是连接其它电脑后发现快捷键正常，后面开始尝试去搜寻有关组合键检查的工具，于是乎找到了OpenArk。OpenArk是一个开源适用于逆向分析的工具，当然它的一些高级功能咱也用不到，我们主要使用他的系统热键功能，下面浅浅的记录一下自己的排查过程。Github地址：https://github.com/BlackINT3/OpenArk安装该工具需要使用内核权限，所以需要基于管理员权限，可能还需要关闭内核完整性保护和安全软件，请自行判断是否需要进行下一步操作Github内的发布版本最新只有1.3.6版本，对于Windows 11 23H2及以上可能无法正常工作，这边建议使用OpenArk交流群内的1.3.8 beta版本进行操作官方介绍，群入口在最下面：https://github.com/BlackINT3/OpenArk/blob/master/doc/README-zh.md你可以选择从本博客下载1.3.8 beta版本，来源为官方5群的群文件，安全性和真实性请自行辨别，本站不作任何担保和负责下载地址：https://bandbbs.lanzoub.com/ip2iR2fjefpg下载完成后将其放置在C盘根目录，右键以管理员身份运行，打开后点击底部的进入内核模式，等待片刻即可成功加载组合键页面如果加载后依然无法显示请按照以下方式进行排查和处理：在OpenArk软件内退出内核模式任务管理器内关闭所有的OpenArk进程前往%APPDATA%目录的OpenArk目录删除symbols文件夹右键管理员重新打开OpenArk，点击进入内核模式使用进入内核模式后应该可以正常加载其快捷键目录，只需在底部的过滤器内输入你要查找的键值，例如我查找F1，于是乎我看见了我的快捷键被Parsec占用，前往Parsec内解除绑定即可，尽量不要使用OpenArk内的解除绑定，防止出现其它异常问题
✨ AI摘要：本文介绍了如何在Mac mini 2024上运行ComfyUI和Stable Diffusion 3.5。首先，作者对Mac的统一内存架构表示兴趣，并详细描述了环境部署步骤，包括安装Homebrew、Anaconda和Git，创建虚拟环境等。接着，介绍了ComfyUI的安装和Stable Diffusion模型的下载过程，最后展示了如何调整工作流并运行生成图像。尽管内存为16GB，使用Swap交换分区使得模型运行成为可能，生成时间约为60-100秒。Powered by SparkU AI Platform前言现如今大部分的AI绘画创作工作流基于NVIDIA的硬件解决方案，而近期作者购入了新款Mac mini 2024（M4）机器，正好对Mac的统一内存架构（UMA）感兴趣，因为在其它NVIDIA硬件上主要利用的设备的显存来进行数据处理，而UMA将显存和内存合二为一，那么意味着我可以使用其运行一些对显存要求较高的模型，经过对比和研究故决定在这台Mac mini上进行尝试。环境部署设备信息型号：Mac mini 2024处理器：M4（10核）内存：16GB系统：macOS 15.1可用硬盘空间：大于50GB基础环境部署Homebrew：官方安装指南：https://brew.sh/Anaconda：官方下载地址：https://www.anaconda.com/download/success请注意下载Apple Slicon版本，也就是arm64版本Git：安装完Anaconda后在终端内执行brew install git创建Conda虚拟环境：conda create -n sd-env python=3.10请自行准备好一个文件夹作为我们的工作目录，路径不要含有中文。创建虚拟环境可以自定义你的虚拟环境名称，修改sd-env这一项即可，python版本固定为3.10，以防止出现部分依赖包不兼容的情况切换至创建的虚拟环境：conda activate sd-env如果你在前面修改了你的虚拟环境名称，请在这里替换为你的虚拟环境名称。在后续的终端操作请确保你在之前创建的工作目录以及使用已经创建的虚拟环境，防止依赖丢失和文件管理混乱ComfyUI安装 / 启动在之前打开的终端内使用cd命令切换到你的工作目录文件夹，我们通过Git拉取最新的ComfyUI项目代码git clone https://github.com/comfyanonymous/ComfyUI.git使用cd命令进入ComfyUI目录，安装依赖pip install -r requirements.txt如果下载缓慢请替换Conda和Pip的镜像源，建议使用清华开源镜像站提供的镜像源Conda修改镜像源：https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/Pip修改镜像源：https://mirrors.tuna.tsinghua.edu.cn/help/pypi/修改完成后重新安装依赖即可尝试启动python main.py启动成功后浏览器打开http://127.0.0.1:8188/即可看到ComfyUI工作流页面但是目前无法使用因为还没有部署模型，我们在下一部分开始部署Stable Diffusion 3.5模型模型下载由于我的Mac mini只有16GB的内存，所以我选择的SD模型为stable-diffusion-3.5-medium模型，如果你的Mac拥有更多的内存可尝试使用Large系列模型安装HuggingFace cli工具pip install -U huggingface_hub使用cd指令切换至该目录ComfyUI/models/checkpoints，使用HuggingFace cli工具下载模型如果你要使用其它模型，请修改命令中的模型信息部分下载过程可能需要Token验证，请将token参数后的hf_开头部分的token替换为你的tokenToken获取地址：https://huggingface.co/settings/tokens创建Token时请根据实际需求选择权限，如果不知道怎么选择请参考官网文档或者全部选择，后续删除即可huggingface-cli download --token hf_yourtoken --resume-download stabilityai/stable-diffusion-3.5-medium --local-dir stable-diffusion-3.5-medium下载时间可能会比较长而且文件较大，请确保你的磁盘拥有足够的空间如果下载缓慢可以尝试使用国内的HF-Mirror项目来加速下载：https://hf-mirror.com/若下载失败可终止操作重新下载即可，下载过程具有断点续传功能下载完成后的目录结构应该如图所示移动Clip模型至clip文件夹，将模型文件夹text_encoders内的文件复制到和checkpoints同级的clip文件夹内，移动完成后的目录结构应该如图所示移动完成我们回到网页的ComfyUI工作流网页中进行下一步操作工作流调整打开UI后应该能看到一个默认的项目文件，我们在空白处右键，依次选择Add Node -> advanced -> loaders -> TripleCLIPLoader创建完成后选择我们之前添加的clip，前面两个cliip加载器按图选择即可，第三个加载器这里根据我的内存大小选择了fp8参数的模型，然后将clip端点和后面的提示词和反向提示词的clip端点连接起来，如图所示连接即可。完成后在上面的ckpt_name中选择sd3.5_medium.safetensors模型即可。运行在上面的模型选择好和端点连接完成后，点击页面右下角的Queue运行即可，这个时候你可以关注系统的占用和终端进度，按照我的提示词以及其它参数保持默认，平均一张图的生成时间为60-100秒左右，进程内存占用最高为16GB左右你可以在这里使用我的提示词进行生成测试，其它参数保持默认即可，生成过程可以通过终端查看进度提示词A young woman in cyberpunk attire, standing in a futuristic urban landscape, daytime setting with neon accents reflecting on glass buildings, intricate network cables and holographic projections in the background, surrounded by a busy technological environment, glowing cityscape, sleek and modern design, detailed character design, futuristic hairstyle, vibrant colors, ultra-realistic rendering.反向提示词blurry, low resolution, poor anatomy, deformed body, extra limbs, overexposed, too dark, cartoonish, low-quality textures之所以16GB内存的机器能运行内存占用16GB以上的进程主要使用了Swap交换分区，在macOS的活动监视器内可以看见已使用的交换空间高达8GB之多，如果你的机器内存在24GB或者更高说不定能提升生成性能和降低资源占用参考 / 引用https://blog.comfy.org/sd3-5-comfyui/https://github.com/comfyanonymous/ComfyUI/issues/5388https://hf-mirror.com/https://huggingface.co/stabilityai/stable-diffusion-3.5-mediumhttps://blog.csdn.net/SJJS_1/article/details/143356893
✨ AI摘要：2024款Mac mini搭载M4芯片，起始内存为16GB，价格保持不变，性价比高。外观小巧，铝合金机身设计，便于携带。系统体验流畅，macOS的动画和UI设计令人愉悦。性能测试显示其在视频处理和多核性能上表现优异，适合创作者使用。与iPhone等设备的无缝连接增强了用户体验，整体表现令人满意。Powered by SparkU AI Platform您的浏览器不支持视频播放。👋 温馨提示由于部分工具、设备等缺失，本篇评测部分数据摘自互联网上其它的作者评测数据，文章末尾会一一列出。如有遗漏还望留言提醒，感谢你的耐心阅读和理解。本页面内含有部分Webp格式内容，若无法正常显示请尝试使用最新版本Chrome / Edge / Safari 浏览器进行尝试。初探自大学以来一直想拥有一个属于自己的Mac，但是由于苹果的价格和内存配置一直让人望而却步。直到今年度的Mac发布会，苹果带来了2024款的M4配置的Mac mini，在发布结束前原本以为还是8GB，直到结束的时候告知全系16GB内存起步，而且价格依然不变，属于是加量不加价。即使他的最丐版硬盘是256GB，但是对于3735￥的国行学生优惠价格来说已经非常划算了，本着体验和学习了解有关Apple平台开发的目的，于是乎拿到了人生中自己的第一台Mac。所以自发布以来这款Mac在各大电商平台依然是断货状态（当然用不了教育优惠，国补不在范围内），即使是官方授权线下店铺也没有现货甚至连样机也没有。官网的发货周期长达一个月，最后授权店推荐使用苹果官方小程序的授权商城预约到货，等待2天后收到有货通知，刚下单完成后好奇刷新了一下商品页又显示断货，可见其火爆程度。开箱外包装依然是经典的苹果纸盒包装，白色纸盒印着Mac mini字样和设备的顶部俯视图，直观清晰而不杂乱。由于苹果很早就取消了塑封包装，所以现在使用的是底部的拉条封口设计，封口的胶粘的不是很紧，稍微使一点劲就拉开，抬起盒子看到了小巧的Mac mini。主机 您的浏览器不支持视频播放。整个主机由铝合金打造，顶部依然是标志性的金属苹果Logo，正面配备了两个USB 3（10Gbps）的Type-C接口和一个3.5mm耳机接口，以及一个电源状态指示灯；背面则是一个交流电输入接口、一个以太网接口（我这里买的是千兆版本）、一个HDMI 2.1接口（苹果终于舍得给入门款配备满血版HDMI2.1了）、以及三个雷电四接口，传输速率可达40 Gbps（如果你是M4 Pro版本则是三个雷电五接口，速率可达双向80Gbps）。让人比较惊讶的是电源部分，它的电源适配器是内置在主机内的，包装所附赠的电源线没有任何其它部件，就是简单的电源线，不像我的笔记本的电源线上有一个砖形的适配器。但是针对便携性来进行评判了话我觉得笔记本可能还是占优，因为其内置电池以及自带显示器键盘和触控板这几点就足以优势尽显，当然我觉得把Mac mini背着到处跑办公的应该也没有多少人，但是其体积相较于一些台式机器来说，便携性、空间占用率等依旧十分吸睛。当你需要转移办公地点或者对桌面进行摆布整理时，如此小巧的机身恰恰满足了这些需求点。本次的新款Mac mini外观相较于前代Mac mini最大的改变莫过于其尺寸的缩小。由于我之前并没有Mac mini所以无法将其进行对比，这里我贴出我的罗技G502和它一起放置的对比图，可见其体积之小，其长宽均为12.7厘米，甚至可以轻易的塞入我的桌面上的书架空格内。其重量也是令我些许震惊，因为我从来没有接触过如此小巧的“台式”电脑主机，他的大小和重量真的是我一只手就可以轻松拿起把玩，而且也不会给人一种所谓的金属质感很强就代表其重量不轻的体验，而对于我每个学习要背着我的电子产品在开学和放假的奔波过程中，无疑大大减轻了负担，最后来到了本次新款最为争议的部分，也就是电源键的位置。网上众多人都说“Mac不需要关机”“功耗低没必要关机”“又不是Windows动不动死机为什么要反复开关机”等等，确实我感觉这个电源键的位置是有那么一点怪，而且其底部的高度完全不足以一根手指伸进去按下，你只能将其一角抬起来然后去按下，有一种给家里的电视开机需要把手摸索到面板后面寻找开关机的感觉。不过苹果也给这个电源键做了个凹下去的设计，以便于盲按时更加方便快速的找到电源按钮。体验系统系统部分我们不会去介绍macOS的各个功能，仅从我个人的使用上分享自己的使用体验作为一个Windows的老用户，之前在虚拟机和其它人的电脑上或多或少体验过macOS，但是之前的体验要么是时间短或者性能受限无法完整的体验到macOS，但是其大体逻辑和组织结构个人感觉是差不多的。自己之前也有过使用iOS/iPadOS还有Linux的使用经验和习惯，体验几天后的上手速度还是挺快的。当然感觉让人最不适应的是它的快捷键，例如Windows / Linux中常用的复制（Ctrl+C）在macOS里面就是command+C，当然其他的粘贴撤回剪切等操作亦如此。早已形成肌肉记忆的快捷键姿势在macOS上又要重新适应，而且有时候也会忘记依然下意识的去使用Ctrl键来进行操作。macOS在一段时间的使用过程中给我感觉最讨人喜欢的莫过于其动画以及高斯模糊的UI设计，本人也是一直很喜欢高斯模糊这类设计，而Windows内的模糊效果就极其有限且不同软件的实现效果各有差异，或者说大部分软件其实并没有这一方面的特点。而动画方面，我们在这里不具体探讨某些地方的细节表现，但从日常体验来说，流畅的动画衔接，渐入渐出等过程虽然平常并不会刻意关注，但是当我需要切换回Windows时，之间的体验割裂感就异常明显。当然也不是说Windows的动画不好，只是当我使用iOS / iPadOS很久后在去入手macOS后依然能够保持一致的动效体验，有时候确实会有不一样的体验。（所以说微软你的Windows Phone呢）性能性能测试部分我想了一段时间，一开始其实是想选游戏进行测试，但是想了想macOS似乎和游戏这个词还是多多少少没有太搭边，即使苹果已经开始反反复复的强调游戏，而且发布了例如GPTK等工具，但是考虑到其转译性能以及原生适配性，我觉得还是从一些能够充分释放性能的测试和应用场景上进行尝试。这里我以我的PC笔记本和Mac mini 2024进行性能测试，测试项目涵盖了多个应用场景：包括视频处理、性能测试、网络浏览等。以下是两台设备的配置表。本性能测试对比并不完全严谨，由于时间和设备硬件等关系，部分硬件参数并不一致，对比过程 / 结果可能并不符合标准的实验流程，性能比较项目少、仅供参考各硬件Mac mini 2024PC笔记本（运行Windows 11）CPUM4（10核心）i7-13650HX（14核心20线程）GPUM4（10核心）RTX 4060 LaptopRAM16GB LPDDR532GB DDR5 4800SSD（仅系统所在磁盘）主机内置（256GB）三星 980 Pro 1TB（使用Pcle4.0）FFMPEG 4K视频批处理这里在不同平台使用不同的硬件编码器，Mac使用VideoToolBox作为硬件加速编码器，笔记本使用QSV和NVENC作为硬件加速编码器，以及纯CPU方式负载任务为批量处理20个4K游戏视频，压缩码率至10000kbps以及调整分辨率到1080P且以H.265（HEVC）进行编码 VideoToolBox（M4）NVENC（NVIDIA）QSV（Intel集成显卡）纯CPU（i7-13650HX）纯CPU（M4）耗时142s99s391s550s553sGeekbench 6（CPU） Mac mini 2024PC笔记本单核分数38122494多核分数1497714372Speedometer 3.0均使用Chrome 131.0.6778.70 Mac mini 2024PC笔记本分数42.1（± 0.84）25.4（± 0.49）偏好功能iPhone镜像之前在Windows时，iOS和电脑的互联可以使用Windows的连接到Windows功能，可以使用短信、电话、消息通知以及照片功能。而在macOS可体验到iPhone镜像功能，也就类似于Android的ADB投屏远程控制功能。当然也可以在上面使用隔空投送等功能，快捷的传输文件和剪切板等。iPad扩展iPad扩展有两个使用方式，其一是直接用macOS的键鼠控制iPadOS，将鼠标往你的iPad的方向使劲移动几次，你便可以看见你的指针移动到了iPad的屏幕上（苹果如何判断iPad的方位其实并不复杂，就是靠猜，当你一个劲的往iPad的方向移动指针的时候系统就会认为iPad在这一侧边会把指针转移过去，当然你朝反方向移动指针也能获得相同的效果，即使iPad在另一个方向）；其二是将iPad作为系统的扩展屏幕，但是这个功能和iPhone的镜像功能冲突，只能开启其中一个。通过控制中心显示器部分开启扩展屏幕后iPad就会自动扩展macOS的屏幕。XCode开发如果你想给iOS / iPadOS开发应用程序，那么你必须要有一台Mac来运行XCode，你可以在XCode内创建多个模拟器，包括iOS、iPadOS、VisionOS、watchOS等，使用swift语言构造对应的App。低噪音 / 低功耗这几天的使用下来，其噪音可以说基本听不见，以至于我无法用更多的篇幅去描述它的噪音。风扇绝大部分都是只有1000rmp，和我的Windows笔记本的风扇噪音相比可以说是高下立判。因为我的笔记本使用的是蓝天公模，而这个模具的风扇噪音就是格外的吵设置有点比肩台式机箱的风扇声音。到了晚上使用电脑时，码字写代码或者看视频时Mac给我的感受就是极其安静，在获得相似流畅度体验的同时基本上没有噪音而且功耗极低，有时候甚至在想是不是可以买一个小型的VPS作为它的储备电源，即使断电也可以有相当长时间的工作时间。杂言自使用电子产品以来，一直想打破各类生态设备屏障。在Windows下我使用KDE Connect来实现多设备和电脑的文件传输，剪切板共享；使用连接到Windows来实现iPhone的电话、短信、照片同步，但是无论如何进行尝试依然有不少的点无法实现完整的流畅体验。苹果的生态一直是我本人想要完整体验的，而其关键链条上终于也补齐了Mac这一重要拼图，体验到诸如iPhone镜像、随航、iCloud同步等功能，相较于之前费尽心思去使用各类工具去尝试串起我的各类主力设备，无疑令人感到新奇和愉悦。铝合金的机身内搭载着性能澎湃的M4芯片，而其内部蕴含的动力也将驱动着成千上万的创作者利用其创作出令人惊叹的作品，而广大创作者中无论是视频创作者、开发者、设计师等，也将利用其充沛的性能去构造出属于自己的梦中世界，即使它很小，但是依旧心动澎湃。
让小米手环6成为直播可显示的心率数值来源
✨ AI摘要：本文介绍了如何将小米手环6的心率数据用于直播。用户需下载特定工具，开启手环的蓝牙和心率广播，并选择冷门运动模式以避免自动暂停。通过输入手环的Mac地址进行扫描，心率数据将显示在日志中。接着，用户可使用OBS等软件添加浏览器源，并通过自定义CSS调整显示样式。Powered by SparkU AI Platform似乎小米手环7及以上的设备阉割掉了心率广播，有兴趣的朋友可以试试是否正常工作使用方法​下载：MibandHeartRateScan.zip打开小米运动健康中手环设置内的“蓝牙广播”和“心率广播”然后在手环上启用一个比较冷门的运动模式，例如跳舞（因为跑步等模式检测到没有运动会自动暂停）然后在扫描器内输入手环的Mac地址（带冒号），然后保存后选择已经保存的Mac地址后点击开始扫描稍等片刻右侧日志就会显示出心率情况你可以使用OBS等直播软件添加浏览器源： http://localhost:8080然后使用下面的自定义css进行字体和颜色以及大小的自定义可根据自身需求进行修改即可body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; } #heart-rate { color: red; font-family: 得意黑}
✨ AI摘要：本文介绍了如何在Windows的HyperV上安装macOS。首先，确保系统符合要求并启用HyperV。接着，下载UEFI和OpenCore，并获取macOS恢复镜像。然后，创建HyperV虚拟机，配置内存、网络和磁盘设置，关闭安全启动和检查点，添加UEFI虚拟磁盘，并调整启动项。最后，启动虚拟机并通过磁盘工具格式化虚拟磁盘，安装macOS。完成后可进行初始化设置，成功进入macOS桌面。Powered by SparkU AI Platform前言作为一个非全家桶Apple用户只有iPad和iPhone，一直想体验一下macOS。之前在VMware上安装过macOS但是需要调整很多东西，突然想到Windows自带的HyperV安装macOS虚拟机效果如何，故有了本篇文章准备工作请确保你的Windows电脑符合以下要求或者尽量符合要求Windows 10 / 11 专业版已经在Windows控制面板中启用了HyperV组件16GB及其以上的RAM32GB的可用空间（最好是SSD）电脑已经预先安装了Python3下载UEFI打开Github项目地址：https://github.com/balopez83/macOS_On_Hyper-V/releases找到最新的release版本，在底部下载最新的压缩包解压到一个文件夹下载OpenCore打开Github项目地址：https://github.com/acidanthera/OpenCorePkg/releases找到最新的release版本，在底部下载最新的压缩包解压到一个文件夹（最好和之前的在一个文件夹内）下载系统恢复镜像打开OpenCore的目录。找到该目录 Utilities\macrecovery ，打开Windows终端（请确保终端执行路径在该文件夹内）打开 https://dortania.github.io/OpenCore-Install-Guide/installer-guide/windows-install.html#downloading-macos 该网页，查看你想要安装下载的系统版本我这里以macOS Sequoia为例，在终端内输入（请根据实际情况替换python的调用指令）python.exe macrecovery.py -b Mac-937A206F2EE63C01 -m 00000000000000000 download等待下载，下载完成后你能在当前目录内看到一个名为 com.apple.recovery.boot 的文件夹整合UEFI将之前下载好的UEFI压缩包解压后你会得到一个 UEFI.vhdx 虚拟硬盘文件，直接双击打开它将刚刚下载得到的 com.apple.recovery.boot 复制到里面，目录结构如图所示然后退出后在Windows资源管理器内找到挂载的这个UEFI磁盘，右键弹出即可配置创建HyperV虚拟机右键宿主机，创建虚拟机（不要使用快速创建）命名你的虚拟机选择第二代虚拟机，不要选择第一代虚拟机，否则会无法使用内存请分配8GB，并勾选上下面的使用动态内存网络选项请选择默认交换机根据个人偏好设置虚拟磁盘的名称、路径、大小（30GB即可，后续可动态扩容）后面的选项保持默认，最后的总结部分验证一下创建的虚拟机是否符合要求，点击完成即可关闭安全启动右键虚拟机 - 设置 - 安全 - 关闭安全启动即可关闭检查点右键虚拟机 - 设置 - 检查点 - 关闭检查点即可启用集成服务右键虚拟机 - 设置 - 集成服务 - 全部勾选即可添加UEFI点击SCSI控制器，找到右侧的添加按钮添加一个虚拟磁盘点击浏览，选择我们之前编辑好的 UEFI.vhdx 虚拟磁盘即可调整启动项在固件部分将 UEFI.vhdx 移动到第一启动项，其次是默认虚拟磁盘和网络适配器启动虚拟机以上的操作完成后保存即可，点击虚拟机点击启动即可开机，开机过程比较慢请耐心等待安装启动完成后会进入macOS Recovery界面选择磁盘工具（Disk Utility），在左侧找到我们的虚拟磁盘，有上架选择抹除磁盘文件系统选择为APFS，磁盘名称自定义，我输入的是macOS，其他的保持默认，点击擦除即可然后回到上一级， 选择重新安装macOS选择我们刚刚格式化为APFS的虚拟磁盘安装过程比较长，而且会遇到安装失败的情况，请多尝试几次，期间会重启请耐心等待然后成功进入初始化界面，按照流程一步一步配置即可进入桌面，大功告成结尾由于虚拟机的缘故macOS的显存也只有可怜的3MB，如果你有macOS原生支持的AMD显卡可以通过显卡直连的功能尝试分配给虚拟机来提升使用体验本文章参考引用了一下内容/项目，在此对下列文章作者表达感谢https://blog.csdn.net/u012153104/article/details/1397712214https://blog.gazer.win/essay/install-macos-on-hyperv-vm-with-opencore-bootloader.htmlhttps://github.com/balopez83/macOS_On_Hyper-Vhttps://github.com/acidanthera/OpenCorePkg
✨ AI摘要：OWER-API-v2是一个用于获取《守望先锋2》国际服玩家生涯数据的接口，旨在替代不再维护的原版本。该接口支持获取玩家的基础信息、竞技比赛数据及各英雄的详细统计信息。用户需在NodeJS环境下部署，并通过API密钥进行认证。由于网络环境限制，建议在境外服务器上运行。项目不隶属于暴雪，数据仅供学习交流使用。Powered by SparkU AI Platform若你还使用OWER-API，请切换至本v2版本，原版本不再维护且不再可用接口规范基本无改变，可在不影响原工作环境的基础上进行迁移更新OWER-API-v2是一个守望先锋2（Overwatch2）国际服玩家生涯数据获取程序、这个项目的名字来源于Overwatch Player，于是缩写成了OWER部署要求：NodeJS 18.19.0（此版本上正常运行，其他版本未做测试）端口默认为16524注意：由于中国大陆的网络环境，国际服的数据获取速度可能会很慢，甚至无法获取，所以建议在境外的服务器上部署确保部署主机上已经安装了Git，并在准备部署的目录下执行以下命令：git clone https://github.com/kindyear/OWER-API-v2.git然后运行项目node app.js不建议将端口设置为80或者其它常用端口，防止和已有服务，例如Nginx或者Apache等服务冲突，你可以使用反向代理功能将其代理到80端口或者其它你想设置的端口上API文档API路径为：http(s)://yourdomain.com:port/v2/api/{ROUTER}其中将ROUTER替换为你要请求的路由接口全局参数apiKey：必需，用于认证访问API的访问密钥。可在项目目录/config/config.js中修改playerTag：必需，玩家的BattleTag（战网ID），例如：KINDYEAR-1336，将#替换为-refreshCache：可选，是否刷新缓存(true / false)，默认情况下为自动处理，配置文件默认设置缓存有效期为12小时，当缓存过期时程序会自动获取新的内容，如果手动指定为true则该次请求会刷新缓存数据API端点获取玩家基础生涯信息URL：/v2/api/playerInfo?{playerTag}&{apiKey}方法：GET响应{ "private": false, "playerBaseInfo": { "playerTag": "KINDYEAR-1336", "playerName": "KINDYEAR", "playerTitle": "Extraterrestrial", "playerIcon": "https://d15f34w2p8l1cc.cloudfront.net/overwatch/5c670baeda5a7b2ed707c940f6b17773e9fd41fe783a8810ea9283cd55d6fd43.png", "playerIconID": "0x02500000000068A2", "playerNameCardID": "0x02500000000068A2", "endorsementLevel": 2 }, "playerCompetitiveInfo": { "PC": { "Tank": { "playerCompetitivePCTank": "Platinum", "playerCompetitivePCTankTier": 2 }, "Damage": { "playerCompetitivePCDamage": "Gold", "playerCompetitivePCDamageTier": 2 }, "Support": { "playerCompetitivePCSupport": "Gold", "playerCompetitivePCSupportTier": 3 } }, "Console": { "Tank": null, "Damage": null, "Support": null } }, "refreshCache": false, "currentTime": 1690110879 }数据解释：private：玩家是否设置了隐私，如果设置了隐私，将会返回true，否则返回falseplayerBaseInfo：玩家基础信息playerTag：玩家的BattleTag（战网ID）playerName：玩家的昵称playerTitle：玩家的头衔playerIcon：玩家的头像playerIconID：玩家的头像IDplayerNameCardID：玩家的名片IDendorsementLevel：玩家的赞赏等级playerCompetitiveInfo：玩家的竞技比赛信息PC/Console：玩家的PC端竞技比赛信息Tank：玩家的坦克信息playerCompetitivePC / ConsoleTank：玩家的坦克段位playerCompetitivePC / ConsoleTankTier：玩家的坦克段位等级Damage：玩家的输出信息playerCompetitivePC / ConsoleDamage：玩家的输出段位playerCompetitivePC / ConsoleDamageTier：玩家的输出段位等级Support：玩家的辅助信息playerCompetitivePC / ConsoleSupport：玩家的辅助段位playerCompetitivePC / ConsoleSupportTier：玩家的辅助段位等级currentTime：当前时间戳refreshCache：是否刷新缓存由于暴雪的限制，无法获取到五百强的具体排名，所有五百强的段位显示为GrandMaster-1，也就是宗师1段位只显示当前赛季段位，无法查看之前赛季的段位此外，暴雪似乎并没有提供开放职责的段位信息（游戏里面有但是我弄不出来），所以这里全部显示的是预设职责的段位守望先锋2在第九赛季更新后，无法查询生涯为隐私的玩家信息即如果该玩家设置为隐私生涯，则会直接提示无法找到该玩家，也就意味着无法获取其赞赏等级，名片以及头衔信息平台端口数据这里以PC平台为例，若要使用主机数据，将API路径中的PC替换为Console即可，本文不做过多赘述获取玩家快速游戏排行信息URL：/v2/api/playerPCQuickInfo?{playerTag}&{apiKey}&{type}方法：GET参数：{type}：必需，请求的排行榜类型，具体参数以解释如下type类型解释说明time-played角色游戏时间games-won角色胜利场数weapon-accuracy角色武器命中率eliminations-per-life角色击杀数 / 每条生命critical-hit-accuracy角色暴击率multikill-best角色最多单次消灭objective-kills角色目标点内击杀注释：其中目标点内击杀为玩家在目标内/附近击杀的玩家总数，包含运载目标或者目标点。此外数据排列格式为由多到少排列，具体可看响应响应{ "private": false, "playerTag": "KINDYEAR-1336", "playerName": "KINDYEAR", "playerIcon": "https://d15f34w2p8l1cc.cloudfront.net/overwatch/7680cd5f24ef316f4218917ef5a8e8f1b9d2d39c14805c35a9a5542440464ffa.png", "playerIconID": "0x02500000000068A2", "playerNameCardID": "0x02500000000068A2", "gameMode": "quickPlay", "platform": "pc", "type": "weapon-accuracy", "heroRankings": [ { "heroName": "Sigma", "heroData": "46%" }, { "heroName": "Mei", "heroData": "44%" }, { "heroName": ".......", "heroData": "......." }, { "heroName": "Moira", "heroData": "0" } ], "refreshCache": false, "currentTime": 1690184120150 }数据解释：private：玩家是否设置了隐私，如果设置了隐私，将会返回true，否则返回falseplayerTag：玩家的BattleTag（战网ID）playerName：玩家的昵称playerIcon：玩家的头像playerIconID：玩家的头像IDplayerNameCardID：玩家的名片IDgameMode：游戏模式（分为quickPlay快速模式和competitive竞技模式）platform：平台，分为pc和consoletype：请求的数据排行类型heroRankings：英雄排行数据heroName：英雄名称heroData：英雄数据........currentTime：当前时间戳refreshCache：是否刷新缓存获取玩家竞技游戏排行信息URL：/v2/api/playerPCCompetitiveInfo?{playerTag}&{apiKey}&{type}方法：GET参数：{type}：必需，请求的排行榜类型，具体参数以解释如下type类型解释说明time-played角色游戏时间games-won角色胜利场数weapon-accuracy角色武器命中率win-percentage角色胜率（竞技模式独有）eliminations-per-life角色击杀数 / 每条生命critical-hit-accuracy角色暴击率multikill-best角色最多单次消灭objective-kills角色目标点内击杀注释：win-percentage参数为竞技模式独有快速模式不可用其中目标点内击杀为玩家在目标内/附近击杀的玩家总数，包含运载目标或者目标点。此外，竞技模式的数据只显示当前赛季的数据，无法查看之前赛季的数据。此外数据排列格式为由多到少排列，响应和数据解释与快速游戏模式相似，这里不再复述。获取玩家快速游戏英雄数据信息URL：/v2/api/playerPCQuickHerosInfo?{playerTag}&{apiKey}&{heroID}方法：GET参数：{heroID}：必需，请求的英雄ID，具体的heroID和英雄名称对应表请查阅：heroID和英雄名称对应表响应（这里以ALL HEROS为例，不同的英雄对应的数据是不相同的）{ "private": false, "playerTag": "KINDYEAR-1336", "playerName": "KINDYEAR", "playerIcon": "https://d15f34w2p8l1cc.cloudfront.net/overwatch/7680cd5f24ef316f4218917ef5a8e8f1b9d2d39c14805c35a9a5542440464ffa.png", "playerIconID": "0x02500000000068A2", "playerNameCardID": "0x02500000000068A2", "gameMode": "quickPlay", "platform": "pc", "heroID": 0, "heroName": "ALL HEROES", "heroSourceID": "0", "quickHeroData": [ { "categoryName": "Best", "categoryData": [ { "statName": "Eliminations - Most in Game", "statValue": "42" }, { "statName": "Final Blows - Most in Game", "statValue": "19" }, { "statName": "Healing Done - Most in Game", "statValue": "18075" }, { "statName": "Objective Kills - Most in Game", "statValue": "24" }, { "statName": "Objective Time - Most in Game", "statValue": "06:42" }, { "statName": "Multikill - Best", "statValue": "4" }, { "statName": "Solo Kills - Most in Game", "statValue": "19" }, { "statName": "Melee Final Blows - Most in Game", "statValue": "4" }, { "statName": "Kill Streak - Best", "statValue": "22" }, { "statName": "Hero Damage Done - Most in Game", "statValue": "19236" }, { "statName": "Assists - Most in Game", "statValue": "30" }, { "statName": "Objective Contest Time - Most in Game", "statValue": "05:09" }, { "statName": "Recon Assists - Most in Game", "statValue": "14" } ] }, { "categoryName": "Average", "categoryData": [ { "statName": "Hero Damage Done - Avg per 10 Min", "statValue": "4747" }, { "statName": "Deaths - Avg per 10 Min", "statValue": "4.82" }, { "statName": "Assists - Avg per 10 min", "statValue": "11.65" }, { "statName": "Eliminations - Avg per 10 Min", "statValue": "12.37" }, { "statName": "Healing Done - Avg per 10 Min", "statValue": "5783" }, { "statName": "Objective Kills - Avg per 10 Min", "statValue": "5.05" }, { "statName": "Objective Time - Avg per 10 Min", "statValue": "01:23" }, { "statName": "Final Blows - Avg per 10 Min", "statValue": "4.73" }, { "statName": "Time Spent on Fire - Avg per 10 Min", "statValue": "00:32" }, { "statName": "Objective Contest Time - Avg per 10 Min", "statValue": "00:43" }, { "statName": "Solo Kills - Avg per 10 Min", "statValue": "0.61" } ] }, { "categoryName": "Game", "categoryData": [ { "statName": "Time Played", "statValue": "51:59:15" }, { "statName": "Games Played", "statValue": "368" }, { "statName": "Games Won", "statValue": "192" }, { "statName": "Games Lost", "statValue": "176" } ] }, { "categoryName": "Combat", "categoryData": [ { "statName": "Environmental Kills", "statValue": "12" }, { "statName": "Multikills", "statValue": "24" }, { "statName": "Hero Damage Done", "statValue": "1480665" }, { "statName": "Deaths", "statValue": "1504" }, { "statName": "Eliminations", "statValue": "3858" }, { "statName": "Damage Done", "statValue": "1480665" }, { "statName": "Objective Kills", "statValue": "1575" }, { "statName": "Final Blows", "statValue": "1475" }, { "statName": "Objective Time", "statValue": "07:09:06" }, { "statName": "Melee Final Blows", "statValue": "65" }, { "statName": "Time Spent on Fire", "statValue": "02:44:23" }, { "statName": "Objective Contest Time", "statValue": "03:45:18" }, { "statName": "Solo Kills", "statValue": "189" } ] }, { "categoryName": "Assists", "categoryData": [ { "statName": "Recon Assists", "statValue": "81" }, { "statName": "Assists", "statValue": "3633" }, { "statName": "Healing Done", "statValue": "1803937" }, { "statName": "Defensive Assists", "statValue": "2951" }, { "statName": "Offensive Assists", "statValue": "1422" } ] } ], "refreshCache": false, "currentTime": 1690344710459 }数据解释：private：玩家是否设置了隐私，如果设置了隐私，将会返回true，否则返回falseplayerTag：玩家的BattleTag（战网ID）playerName：玩家的昵称playerIcon：玩家的头像playerIconID：玩家的头像IDplayerNameCardID：玩家的名片IDgameMode：游戏模式（分为quickPlay快速模式和competitive竞技模式）platform：平台，分为pc和consoleheroID：英雄IDheroName：英雄名称heroSourceID：英雄源ID（使用者不必关注此数据，该值的解释可以看后面）quickHeroData：英雄数据categoryName：数据分类名称categoryData：数据分类数据statName：数据名称statValue：数据值............currentTime：当前时间戳refreshCache：是否刷新缓存获取玩家竞技游戏英雄数据信息URL：/v2/api/playerPCCompetitiveHerosInfo?{playerTag}&{apiKey}&{heroID}方法：GET参数：{heroID}：必需，请求的英雄ID，具体的heroID和英雄名称对应表请查阅：heroID和英雄名称对应表响应于快速模式英雄数据响应相似，数据解释也相似，这里不做赘述部分数据解释heroSourceID:由于不同玩家的英雄列表不相同，有可能某个玩家不玩某个英雄，导致herosData.json文件中的heroID无法一一对应，于是在处理过程中临时内建维护了一个专属于玩家自己的heroID对应表，而heroSourceID就是当heroID在页面上实际的ID值，而不存在的则为null值，这样就可以保证数据的准确性，同时也可以保证数据的完整性，不会因为某个英雄的数据不存在而导致数据不完整。heroID和英雄名称对应表heroID英雄名称（heroName）英雄简体中文名称0ALL HEROS全部英雄1Ana安娜2Ashe艾什3Baptiste巴蒂斯特4Bastion堡垒5Brigitte布里吉塔6Cassidy卡西迪（永远的麦克雷）7D.VaD.Va8Doomfist末日铁拳9Echo回声10Genji源氏11Hanzo半藏12Junker Queen渣客女王13Junkrat狂鼠14Kiriko雾子15Lifeweaver生命之梭16Lúcio卢西奥17Mei美18Mercy天使19Moira莫伊拉20Orisa奥丽莎21Pharah法老之鹰22Ramattra拉玛刹23Reaper死神24Reinhardt莱因哈特25Roadhog路霸26Sigma西格玛27Sojourn索杰恩28Soldier: 76士兵：7629Sombra黑影30Symmetra秩序之光31Torbjörn托比昂32Tracer猎空33Widowmaker黑百合34Winston温斯顿35Wrecking Ball破坏球36Zarya查莉娅37Zenyatta禅雅塔38Illari伊拉锐39Mauga毛加40Venture探奇41Juno朱诺TODO[x] 实现缓存功能[x] 多线程处理（多核）[x] 玩家基础游戏信息[x] PC玩家快速游戏信息[x] PC玩家竞技游戏信息[x] PC玩家快速游戏各英雄信息[x] PC玩家竞技游戏各英雄信息[x] 主机玩家快速游戏信息[x] 主机玩家快速游戏信息[x] 主机玩家快速游戏各英雄信息[x] 主机玩家竞技游戏各英雄信息启发 / 感谢排名不分前后https://zusor.io/（项目启发）Linus花散里低调做人免责声明OWER项目不隶属于暴雪，也不反映暴雪或任何正式参与制作或管理《守望先锋》的人的观点或意见。Overwatch 和 Blizzard 是 BlizzardEntertainment, Inc. 的商标或注册商标。 Overwatch © Blizzard Entertainment, Inc.其中所产生的部分数据内容版权归暴雪娱乐所有，OWER项目仅用于学习交流，不得用于商业用途。此外，暴雪随时可能会调整数据来源网页的访问规则或者数据格式，项目不保证即时更新。我们不保证正常运行时间、响应时间或支持。您使用此项目的风险由您自行承担。许可证如果满足以下条件，则允许以源代码和二进制形式重新分发和使用，无论是否经过修改：源代码的重新分发必须保留上述版权声明、此条件列表和以下免责声明。以二进制形式重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表以及以下免责声明。本软件由版权所有者和贡献者“按原样”提供，不承担任何明示或默示的保证，包括但不限于适销性和特定用途适用性的默示保证。在任何情况下，版权持有人或贡献者均不对任何直接、间接、附带、特殊、惩戒性或后果性损害（包括但不限于采购替代商品或服务；使用、数据或利润损失；或业务中断）承担责任因使用本软件而以任何方式引起的以及基于任何责任理论的责任，无论是合同责任、严格责任还是侵权行为（包括疏忽或其他），即使已被告知可能发生此类损害。