2026年2月

白山云,新用户「注册并完成实名认证」即赠送 150元 体验金,调用api再给300元,一共450元

能用GLM-5,我测试一下,响应速度挺快的,额度给的也足够多。

认证先给150元,群友反馈,调用api后几个小时后就会再给300

注册链接是这个https://ai.baishan.com

目前还没打算用,写了个node脚本先调用了一下api,把300拿到手

const url = "https://api.edgefn.net/v1/chat/completions";
const apiKey = "你的token";

const headers = {
  Authorization: `Bearer ${apiKey}`,
  "Content-Type": "application/json",
};

const data = {
  model: "Qwen2.5-72B-Instruct",
  messages: [{ role: "user", content: "Hello, how are you?" }],
};

fetch(url, {
  method: "POST",
  headers,
  body: JSON.stringify(data),
})
  .then((res) => res.json())
  .then((json) => console.log(JSON.stringify(json, null, 2)))
  .catch((err) => console.error("Error:", err));

当然用curl调用一下也行,我只是顺便还要开发别的,直接写了个node的

那完了450代金券,直接在OpenClaw里用,真香。

Python日志系统架构设计与ELK集成

日志是系统可观测性的重要组成部分。本文将介绍Python日志系统架构设计和ELK集成方案。

日志系统核心组件

  • Logger:日志记录器
  • Handler:日志处理器
  • Formatter:日志格式化器
  • Filter:日志过滤器

日志系统核心实现

"""
Python日志系统架构设计与ELK集成
包含结构化日志、多处理器、ELK集成等
"""

import logging
import logging.handlers
import json
import sys
from datetime import datetime
from typing import Dict, Any, Optional
from pythonjsonlogger import jsonlogger
import queue
import threading


# ============ 结构化日志格式 ============
class StructuredLogFormatter(jsonlogger.JsonFormatter):
    """结构化日志格式化器"""
    
    def add_fields(self, log_record, record, message_dict):
        super().add_fields(log_record, record, message_dict)
        
        # 添加时间戳
        if not log_record.get('timestamp'):
            log_record['timestamp'] = datetime.utcnow().isoformat()
        
        # 添加日志级别
        if log_record.get('level'):
            log_record['level'] = log_record['level'].upper()
        else:
            log_record['level'] = record.levelname
        
        # 添加源信息
        log_record['source'] = {
            'file': record.filename,
            'line': record.lineno,
            'function': record.funcName,
            'module': record.module
        }


# ============ 自定义日志处理器 ============
class AsyncHandler(logging.Handler):
    """异步日志处理器"""
    
    def __init__(self, handler: logging.Handler, max_queue_size: int = 1000):
        super().__init__()
        self.handler = handler
        self.queue = queue.Queue(maxsize=max_queue_size)
        self.thread = threading.Thread(target=self._process, daemon=True)
        self.thread.start()
    
    def emit(self, record):
        try:
            self.queue.put_nowait(record)
        except queue.Full:
            # 队列满时直接处理
            self.handler.emit(record)
    
    def _process(self):
        while True:
            try:
                record = self.queue.get()
                if record is None:
                    break
                self.handler.emit(record)
            except Exception:
                pass
    
    def close(self):
        self.queue.put(None)
        self.thread.join(timeout=5)
        self.handler.close()
        super().close()


class ContextFilter(logging.Filter):
    """上下文过滤器"""
    
    def __init__(self, context: Dict[str, Any] = None):
        super().__init__()
        self.context = context or {}
        self._local = threading.local()
    
    def filter(self, record):
        # 添加上下文信息
        for key, value in self.context.items():
            setattr(record, key, value)
        
        # 添加线程本地上下文
        if hasattr(self._local, 'request_id'):
            record.request_id = self._local.request_id
        
        return True
    
    def set_request_id(self, request_id: str):
        self._local.request_id = request_id


# ============ 日志配置 ============
def setup_logging(
    level: str = "INFO",
    log_file: Optional[str] = None,
    json_format: bool = True
) -> logging.Logger:
    """配置日志系统"""
    
    # 创建logger
    logger = logging.getLogger("app")
    logger.setLevel(getattr(logging, level.upper()))
    logger.handlers = []  # 清除现有处理器
    
    # 创建格式化器
    if json_format:
        formatter = StructuredLogFormatter(
            '%(timestamp)s %(level)s %(name)s %(message)s'
        )
    else:
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
    
    # 控制台处理器
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)
    
    # 文件处理器
    if log_file:
        file_handler = logging.handlers.RotatingFileHandler(
            log_file,
            maxBytes=10*1024*1024,  # 10MB
            backupCount=5
        )
        file_handler.setFormatter(formatter)
        logger.addHandler(file_handler)
    
    # 添加上下文过滤器
    context_filter = ContextFilter({
        'service': 'my-service',
        'version': '1.0.0'
    })
    logger.addFilter(context_filter)
    
    return logger


# ============ 日志记录器类 ============
class StructuredLogger:
    """结构化日志记录器"""
    
    def __init__(self, logger: logging.Logger):
        self._logger = logger
    
    def _log(self, level: int, message: str, **kwargs):
        """记录结构化日志"""
        extra = {'structured_data': kwargs}
        self._logger.log(level, message, extra=extra)
    
    def info(self, message: str, **kwargs):
        self._log(logging.INFO, message, **kwargs)
    
    def error(self, message: str, **kwargs):
        self._log(logging.ERROR, message, **kwargs)
    
    def debug(self, message: str, **kwargs):
        self._log(logging.DEBUG, message, **kwargs)
    
    def warning(self, message: str, **kwargs):
        self._log(logging.WARNING, message, **kwargs)


# ============ 业务日志记录 ============
class UserService:
    """用户服务"""
    
    def __init__(self, logger: StructuredLogger):
        self.logger = logger
    
    def create_user(self, username: str, email: str):
        """创建用户"""
        self.logger.info(
            "创建用户",
            action="create_user",
            username=username,
            email=email
        )
        # 业务逻辑...
        return {"id": 1, "username": username}
    
    def get_user(self, user_id: int):
        """获取用户"""
        self.logger.info(
            "获取用户",
            action="get_user",
            user_id=user_id
        )
        # 业务逻辑...
        return {"id": user_id, "username": "alice"}


# ============ ELK集成示例 ============
class ELKHandler(logging.Handler):
    """ELK日志处理器"""
    
    def __init__(self, host: str, port: int):
        super().__init__()
        self.host = host
        self.port = port
    
    def emit(self, record):
        """发送日志到ELK"""
        log_entry = self.format(record)
        # 实际实现中这里会发送到Logstash或Elasticsearch
        print(f"[ELK] {log_entry}")


def main():
    """主函数"""
    print("="*60)
    print("Python日志系统架构设计")
    print("="*60)
    
    # 配置日志
    logger = setup_logging(
        level="INFO",
        log_file="app.log",
        json_format=True
    )
    
    structured_logger = StructuredLogger(logger)
    
    # 使用日志
    print("\n【结构化日志示例】")
    user_service = UserService(structured_logger)
    user_service.create_user("alice", "alice@example.com")
    user_service.get_user(1)
    
    # 记录异常
    print("\n【异常日志示例】")
    try:
        1 / 0
    except Exception as e:
        structured_logger.error(
            "发生错误",
            error_type=type(e).__name__,
            error_message=str(e)
        )
    
    print("\n" + "="*60)
    print("日志系统总结")
    print("="*60)
    print("1. 结构化日志: JSON格式便于解析")
    print("2. 多处理器: 同时输出到控制台和文件")
    print("3. 异步处理: 避免日志阻塞业务")
    print("4. 上下文信息: 添加上下文便于追踪")
    print("5. ELK集成: 集中化日志管理")
    print("="*60)


if __name__ == "__main__":
    main()

日志系统架构图

flowchart TB
    subgraph App["应用程序"]
        A1[业务代码]
        A2[结构化日志]
    end
    
    subgraph Logger["日志系统"]
        L1[Logger]
        L2[Handler]
        L3[Formatter]
        L4[Filter]
    end
    
    subgraph Output["输出目标"]
        O1[控制台]
        O2[文件]
        O3[ELK Stack]
    end
    
    App --> Logger --> Output

关键要点

  1. 结构化日志:JSON格式便于解析和分析
  2. 多处理器:同时输出到多个目标
  3. 异步处理:避免日志阻塞业务逻辑
  4. 上下文信息:添加上下文便于问题追踪
  5. ELK集成:集中化日志管理和分析

良好的日志系统是系统可观测性的基础。

Python单元测试框架与Mock对象使用指南

单元测试是保证代码质量的重要手段。本文将介绍Python单元测试框架和Mock对象的使用。

单元测试核心概念

  • unittest:标准库测试框架
  • pytest:第三方测试框架
  • Mock:模拟对象
  • Fixture:测试夹具

单元测试核心实现

"""
Python单元测试框架与Mock对象使用
包含unittest、pytest、mock等
"""

import unittest
from unittest.mock import Mock, patch, MagicMock, call
from typing import List, Dict, Optional
import requests


# ============ 被测试的代码 ============
class Calculator:
    """计算器类"""
    
    def add(self, a: float, b: float) -> float:
        return a + b
    
    def subtract(self, a: float, b: float) -> float:
        return a - b
    
    def multiply(self, a: float, b: float) -> float:
        return a * b
    
    def divide(self, a: float, b: float) -> float:
        if b == 0:
            raise ValueError("除数不能为零")
        return a / b


class UserService:
    """用户服务"""
    
    def __init__(self, db_connection):
        self.db = db_connection
    
    def get_user(self, user_id: int) -> Optional[Dict]:
        return self.db.query(f"SELECT * FROM users WHERE id = {user_id}")
    
    def create_user(self, username: str, email: str) -> Dict:
        if not username or not email:
            raise ValueError("用户名和邮箱不能为空")
        return self.db.insert("users", {"username": username, "email": email})


class PaymentGateway:
    """支付网关"""
    
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://api.payment.com"
    
    def charge(self, amount: float, card_number: str) -> Dict:
        response = requests.post(
            f"{self.base_url}/charge",
            headers={"Authorization": f"Bearer {self.api_key}"},
            json={"amount": amount, "card": card_number}
        )
        return response.json()


# ============ unittest测试 ============
class TestCalculator(unittest.TestCase):
    """计算器测试"""
    
    def setUp(self):
        """测试前准备"""
        self.calc = Calculator()
    
    def test_add(self):
        """测试加法"""
        self.assertEqual(self.calc.add(2, 3), 5)
        self.assertEqual(self.calc.add(-1, 1), 0)
        self.assertEqual(self.calc.add(0.1, 0.2), 0.3, places=7)
    
    def test_subtract(self):
        """测试减法"""
        self.assertEqual(self.calc.subtract(5, 3), 2)
        self.assertEqual(self.calc.subtract(0, 5), -5)
    
    def test_multiply(self):
        """测试乘法"""
        self.assertEqual(self.calc.multiply(3, 4), 12)
        self.assertEqual(self.calc.multiply(-2, 3), -6)
    
    def test_divide(self):
        """测试除法"""
        self.assertEqual(self.calc.divide(6, 2), 3)
        self.assertEqual(self.calc.divide(5, 2), 2.5)
    
    def test_divide_by_zero(self):
        """测试除零异常"""
        with self.assertRaises(ValueError) as context:
            self.calc.divide(5, 0)
        self.assertEqual(str(context.exception), "除数不能为零")


class TestUserService(unittest.TestCase):
    """用户服务测试"""
    
    def setUp(self):
        """测试前准备"""
        # 创建Mock对象
        self.mock_db = Mock()
        self.user_service = UserService(self.mock_db)
    
    def test_get_user(self):
        """测试获取用户"""
        # 设置Mock返回值
        expected_user = {"id": 1, "username": "alice"}
        self.mock_db.query.return_value = expected_user
        
        # 执行测试
        user = self.user_service.get_user(1)
        
        # 验证结果
        self.assertEqual(user, expected_user)
        self.mock_db.query.assert_called_once_with("SELECT * FROM users WHERE id = 1")
    
    def test_create_user(self):
        """测试创建用户"""
        expected_result = {"id": 1, "username": "bob", "email": "bob@example.com"}
        self.mock_db.insert.return_value = expected_result
        
        result = self.user_service.create_user("bob", "bob@example.com")
        
        self.assertEqual(result, expected_result)
        self.mock_db.insert.assert_called_once_with(
            "users",
            {"username": "bob", "email": "bob@example.com"}
        )
    
    def test_create_user_invalid_input(self):
        """测试创建用户无效输入"""
        with self.assertRaises(ValueError):
            self.user_service.create_user("", "email@example.com")


class TestPaymentGateway(unittest.TestCase):
    """支付网关测试"""
    
    @patch('requests.post')
    def test_charge(self, mock_post):
        """测试支付"""
        # 设置Mock响应
        mock_response = Mock()
        mock_response.json.return_value = {"status": "success", "transaction_id": "12345"}
        mock_post.return_value = mock_response
        
        # 执行测试
        gateway = PaymentGateway("test_api_key")
        result = gateway.charge(100.0, "4111111111111111")
        
        # 验证结果
        self.assertEqual(result["status"], "success")
        mock_post.assert_called_once()


# ============ Mock高级用法 ============
class TestMockAdvanced(unittest.TestCase):
    """Mock高级用法测试"""
    
    def test_mock_return_value(self):
        """测试Mock返回值"""
        mock = Mock()
        mock.return_value = 42
        
        result = mock()
        self.assertEqual(result, 42)
    
    def test_mock_side_effect(self):
        """测试Mock副作用"""
        mock = Mock()
        mock.side_effect = [1, 2, 3]
        
        self.assertEqual(mock(), 1)
        self.assertEqual(mock(), 2)
        self.assertEqual(mock(), 3)
    
    def test_mock_side_effect_exception(self):
        """测试Mock抛出异常"""
        mock = Mock()
        mock.side_effect = ValueError("错误")
        
        with self.assertRaises(ValueError):
            mock()
    
    def test_mock_call_count(self):
        """测试Mock调用次数"""
        mock = Mock()
        
        mock()
        mock()
        mock()
        
        self.assertEqual(mock.call_count, 3)
    
    def test_mock_call_args(self):
        """测试Mock调用参数"""
        mock = Mock()
        
        mock(1, 2, key='value')
        
        self.assertEqual(mock.call_args, call(1, 2, key='value'))
    
    def test_mock_multiple_calls(self):
        """测试Mock多次调用"""
        mock = Mock()
        
        mock(1)
        mock(2)
        mock(3)
        
        expected_calls = [call(1), call(2), call(3)]
        mock.assert_has_calls(expected_calls)


# ============ 测试夹具 ============
class TestWithFixtures(unittest.TestCase):
    """使用测试夹具"""
    
    @classmethod
    def setUpClass(cls):
        """类级别设置"""
        print("设置测试类")
        cls.shared_resource = "shared"
    
    @classmethod
    def tearDownClass(cls):
        """类级别清理"""
        print("清理测试类")
    
    def setUp(self):
        """方法级别设置"""
        self.test_data = [1, 2, 3]
    
    def tearDown(self):
        """方法级别清理"""
        self.test_data = None
    
    def test_with_fixture(self):
        """使用夹具的测试"""
        self.assertEqual(len(self.test_data), 3)
        self.assertEqual(self.shared_resource, "shared")


def main():
    """主函数"""
    print("="*60)
    print("Python单元测试框架与Mock对象使用")
    print("="*60)
    
    # 运行测试
    loader = unittest.TestLoader()
    suite = unittest.TestSuite()
    
    # 添加测试
    suite.addTests(loader.loadTestsFromTestCase(TestCalculator))
    suite.addTests(loader.loadTestsFromTestCase(TestUserService))
    suite.addTests(loader.loadTestsFromTestCase(TestPaymentGateway))
    suite.addTests(loader.loadTestsFromTestCase(TestMockAdvanced))
    suite.addTests(loader.loadTestsFromTestCase(TestWithFixtures))
    
    # 运行
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    print("\n" + "="*60)
    print("单元测试总结")
    print("="*60)
    print("1. unittest: 标准库测试框架")
    print("2. Mock: 模拟对象和依赖")
    print("3. patch: 临时替换对象")
    print("4. Fixture: 测试准备和清理")
    print("5. 断言: 验证测试结果")
    print("="*60)


if __name__ == "__main__":
    main()

单元测试架构图

flowchart TB
    subgraph TestCode["测试代码"]
        T1[测试用例]
        T2[测试夹具]
        T3[断言]
    end
    
    subgraph MockObjects["Mock对象"]
        M1[Mock]
        M2[MagicMock]
        M3[Patch]
    end
    
    subgraph Production["生产代码"]
        P1[被测函数]
        P2[被测类]
    end
    
    TestCode --> MockObjects
    TestCode --> Production

关键要点

  1. unittest:标准库测试框架
  2. Mock:模拟对象和依赖
  3. patch:临时替换对象
  4. Fixture:测试准备和清理
  5. 断言:验证测试结果

单元测试是保证代码质量的重要手段。

Python代码重构技巧与坏味道识别

代码重构是改善代码结构而不改变外部行为的过程。本文将介绍Python代码重构技巧和坏味道识别。

代码坏味道

  • 长方法:方法过长,职责过多
  • 重复代码:相同或相似的代码多处出现
  • 过大的类:类包含过多属性和方法
  • 过长参数列表:方法参数过多

重构核心实现

"""
Python代码重构技巧与坏味道识别
包含提取方法、内联、移动方法等重构技巧
"""

from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass
from enum import Enum


# ============ 坏味道示例 ============
class OrderProcessorBad:
    """坏味道示例:过大的类"""
    
    def __init__(self):
        self.orders = []
        self.customers = []
        self.products = []
        self.inventory = {}
        self.shipping_rates = {}
    
    def process_order(self, order_id: int, customer_id: int, 
                     product_ids: List[int], quantities: List[int],
                     shipping_address: str, payment_method: str,
                     discount_code: Optional[str] = None,
                     gift_wrap: bool = False,
                     special_instructions: str = ""):
        """坏味道:过长参数列表"""
        # 验证客户
        customer = None
        for c in self.customers:
            if c['id'] == customer_id:
                customer = c
                break
        
        if not customer:
            raise ValueError("客户不存在")
        
        # 验证产品
        products = []
        for pid in product_ids:
            for p in self.products:
                if p['id'] == pid:
                    products.append(p)
                    break
        
        # 计算价格
        total = 0
        for i, product in enumerate(products):
            qty = quantities[i]
            price = product['price']
            
            # 应用折扣
            if discount_code:
                if discount_code == "SAVE10":
                    price = price * 0.9
                elif discount_code == "SAVE20":
                    price = price * 0.8
            
            total += price * qty
        
        # 计算运费
        if total < 50:
            shipping = 5.99
        elif total < 100:
            shipping = 2.99
        else:
            shipping = 0
        
        total += shipping
        
        # 处理支付
        if payment_method == "credit_card":
            print(f"处理信用卡支付: {total}")
        elif payment_method == "paypal":
            print(f"处理PayPal支付: {total}")
        elif payment_method == "bank_transfer":
            print(f"处理银行转账: {total}")
        
        # 创建订单
        order = {
            'id': order_id,
            'customer': customer,
            'products': products,
            'total': total,
            'shipping_address': shipping_address
        }
        
        self.orders.append(order)
        return order


# ============ 重构后代码 ============
@dataclass
class Customer:
    """客户"""
    id: int
    name: str
    email: str


@dataclass
class Product:
    """产品"""
    id: int
    name: str
    price: float


@dataclass
class OrderItem:
    """订单项"""
    product: Product
    quantity: int
    
    @property
    def subtotal(self) -> float:
        return self.product.price * self.quantity


class DiscountStrategy:
    """折扣策略"""
    
    DISCOUNTS = {
        "SAVE10": 0.9,
        "SAVE20": 0.8,
        "SAVE50": 0.5
    }
    
    @classmethod
    def apply_discount(cls, price: float, code: Optional[str]) -> float:
        if code and code in cls.DISCOUNTS:
            return price * cls.DISCOUNTS[code]
        return price


class ShippingCalculator:
    """运费计算器"""
    
    @staticmethod
    def calculate_shipping(order_total: float) -> float:
        if order_total < 50:
            return 5.99
        elif order_total < 100:
            return 2.99
        return 0


class PaymentProcessor:
    """支付处理器"""
    
    def process_payment(self, amount: float, method: str) -> bool:
        processors = {
            "credit_card": self._process_credit_card,
            "paypal": self._process_paypal,
            "bank_transfer": self._process_bank_transfer
        }
        
        processor = processors.get(method)
        if processor:
            return processor(amount)
        raise ValueError(f"不支持的支付方式: {method}")
    
    def _process_credit_card(self, amount: float) -> bool:
        print(f"处理信用卡支付: {amount}")
        return True
    
    def _process_paypal(self, amount: float) -> bool:
        print(f"处理PayPal支付: {amount}")
        return True
    
    def _process_bank_transfer(self, amount: float) -> bool:
        print(f"处理银行转账: {amount}")
        return True


class CustomerRepository:
    """客户仓储"""
    
    def __init__(self):
        self._customers: Dict[int, Customer] = {}
    
    def add(self, customer: Customer):
        self._customers[customer.id] = customer
    
    def get_by_id(self, customer_id: int) -> Optional[Customer]:
        return self._customers.get(customer_id)


class ProductRepository:
    """产品仓储"""
    
    def __init__(self):
        self._products: Dict[int, Product] = {}
    
    def add(self, product: Product):
        self._products[product.id] = product
    
    def get_by_ids(self, product_ids: List[int]) -> List[Product]:
        return [self._products[pid] for pid in product_ids if pid in self._products]


@dataclass
class Order:
    """订单"""
    id: int
    customer: Customer
    items: List[OrderItem]
    shipping_address: str
    payment_method: str
    discount_code: Optional[str] = None
    
    @property
    def subtotal(self) -> float:
        return sum(item.subtotal for item in self.items)
    
    @property
    def shipping_cost(self) -> float:
        return ShippingCalculator.calculate_shipping(self.subtotal)
    
    @property
    def total(self) -> float:
        discounted = sum(
            DiscountStrategy.apply_discount(item.subtotal, self.discount_code)
            for item in self.items
        )
        return discounted + self.shipping_cost


class OrderService:
    """订单服务(重构后)"""
    
    def __init__(self):
        self.customer_repo = CustomerRepository()
        self.product_repo = ProductRepository()
        self.payment_processor = PaymentProcessor()
        self.orders: List[Order] = []
    
    def create_order(
        self,
        customer_id: int,
        items_data: List[Tuple[int, int]],  # (product_id, quantity)
        shipping_address: str,
        payment_method: str,
        discount_code: Optional[str] = None
    ) -> Order:
        """创建订单"""
        # 获取客户
        customer = self.customer_repo.get_by_id(customer_id)
        if not customer:
            raise ValueError("客户不存在")
        
        # 获取产品并创建订单项
        product_ids = [item[0] for item in items_data]
        products = self.product_repo.get_by_ids(product_ids)
        
        if len(products) != len(product_ids):
            raise ValueError("部分产品不存在")
        
        order_items = [
            OrderItem(product, qty)
            for product, (_, qty) in zip(products, items_data)
        ]
        
        # 创建订单
        order = Order(
            id=len(self.orders) + 1,
            customer=customer,
            items=order_items,
            shipping_address=shipping_address,
            payment_method=payment_method,
            discount_code=discount_code
        )
        
        # 处理支付
        self.payment_processor.process_payment(order.total, payment_method)
        
        self.orders.append(order)
        return order


def demonstrate_refactoring():
    """演示重构"""
    print("="*60)
    print("代码重构演示")
    print("="*60)
    
    # 设置数据
    service = OrderService()
    
    # 添加客户
    service.customer_repo.add(Customer(1, "Alice", "alice@example.com"))
    
    # 添加产品
    service.product_repo.add(Product(1, "Laptop", 999.99))
    service.product_repo.add(Product(2, "Mouse", 29.99))
    
    # 创建订单
    order = service.create_order(
        customer_id=1,
        items_data=[(1, 1), (2, 2)],
        shipping_address="123 Main St",
        payment_method="credit_card",
        discount_code="SAVE10"
    )
    
    print(f"\n订单ID: {order.id}")
    print(f"客户: {order.customer.name}")
    print(f"商品小计: ${order.subtotal:.2f}")
    print(f"运费: ${order.shipping_cost:.2f}")
    print(f"总计: ${order.total:.2f}")
    
    print("\n" + "="*60)
    print("重构改进")
    print("="*60)
    print("1. 提取类: Customer, Product, OrderItem")
    print("2. 提取方法: ShippingCalculator, PaymentProcessor")
    print("3. 引入策略模式: DiscountStrategy")
    print("4. 使用仓储模式: CustomerRepository, ProductRepository")
    print("5. 减少参数: 使用对象封装参数")
    print("="*60)


def main():
    """主函数"""
    demonstrate_refactoring()


if __name__ == "__main__":
    main()

重构架构图

flowchart TB
    subgraph Before["重构前"]
        B1[大类]
        B2[长方法]
        B3[重复代码]
    end
    
    subgraph After["重构后"]
        A1[小类]
        A2[短方法]
        A3[策略模式]
    end
    
    subgraph Techniques["重构技巧"]
        T1[提取方法]
        T2[移动方法]
        T3[引入参数对象]
    end
    
    Before --> Techniques --> After

关键要点

  1. 提取方法:将长方法拆分为小方法
  2. 移动方法:将方法放到合适的类中
  3. 引入参数对象:减少参数数量
  4. 策略模式:替换条件语句
  5. 单一职责:每个类只负责一件事

重构是持续改进代码质量的重要实践。

"注意力,是你最稀缺的资产。" —— 纳瓦尔(Naval Ravikant)

早在战国时期,“亚圣”孟子也在《孟子·离娄下》有云:“人有不为也,而后可以有为。”只有对某些事情“不为”,才能集中精力在更重要的事情上“有为”

这其中蕴含深刻而辩证的工作与人生方法论:
特别在当今AI时代,各种信息狂轰乱炸。“有所不为”更是彰显了高明的战略定力和智慧。绝不是不作为,而是强调要实事求是,懂得主动放弃和拒绝,不干不该干的事。

昨天,我在10个微信群里发了同一段告别留言:

"各位好!我是 Hugo,数字游民一枚。

信息大爆炸的 AI 时代,最最重要的是保护好自己的注意力,把有限的时间用在自己的'第一要事'上。

经过反复探索后,我最终决定聚焦 AI 轻创&Web3&OPC,深耕 AI 编程应用开发实践,赋能个人蜕变成长&组织迭代进化…"

发完这段话,我退掉了10多个与核心目标无关的群。


一、我们正身处一个"注意力被抢劫"的时代

你有没有过这样的体验:

  • 📱 早上拿起手机想查个资料,结果刷了半小时朋友圈
  • 💬 微信群红点一响就忍不住点开,一聊就是半小时无关话题
  • 📺 本想学习 AI 教程,却被算法推荐带进了短视频黑洞
  • 🤔 晚上躺在床上,脑子里全是白天别人的评价和闲聊

明明忙了一整天,却好像什么正事都没做。

这不是你的问题,这是设计好的。

每一个 APP 都在争夺你的眼球,每一条推送都在收割你的专注,每一个"为你好"的建议都在干扰你的判断。

它们不杀人,却在慢性谋杀你的可能性。


二、为什么我选择"退群"?

刘润说过一句话:

"群体的热闹,常常是个体成长的坟墓。"

深以为然。

我曾经的微信群列表里,有各种"资源对接群"、"行业交流群"、"学习打卡群"… 每天消息 999+,看起来人脉很广,信息很多。

但一年后回头看:

  • ❌ 没有促成任何实质性合作
  • ❌ 没有学到任何系统性知识
  • ❌ 没有推动任何项目进展
  • ✅ 唯一收获的是:注意力碎片化、焦虑感倍增、时间被切割成渣

我意识到:我在用"社交勤奋"掩盖"战略懒惰"。

于是我做了一个决定:

只保留与核心目标高度一致的社群,其他全部退出或设置免打扰。

这个决定带来的变化是惊人的——

我省出了每天至少 2 小时的深度工作时间。


三、AI 时代,专注力是第一生产力

纳瓦尔在 2025 最新闭门分享中说:

"生命中最稀缺的资源不是时间,而是注意力。人脑每天只有 2-3 小时深度专注能力,你把 99% 的注意力放到某件事上,你就在这件事上胜过 99% 的人。"

就比如AI 编程,其本质不是写代码,而是清晰表达你的想法。

当你能够屏蔽干扰、保持专注时:

  • 你能更清晰地定义问题
  • 你能更准确地描述需求
  • 你能更有耐心地迭代优化
  • 你能更敏锐地捕捉机会

技术门槛已经被 AI 填平,真正的门槛是:你能否专注到把事情做成。


四、我的 5 条极简实操建议

基于这段时间的实践,我总结了 5 条可立即执行的建议:

1️⃣ 锁定"唯一核心目标"

问自己:"未来 30 天,哪件事不做,我的目标会崩盘?"

答案只有一个。其他事情,全部暂缓。

我的答案:深耕 AI 编程应用开发,做出能落地的产品。

2️⃣ 清理消耗型社群

清理超过 5 个活跃且与核心目标无关的微信群?

退群,或者设置"消息免打扰 + 折叠"。

真正的紧急事,会有人打电话找你。

3️⃣ 守护清晨黄金时间

每天留出 2 小时完全离线时间,用于处理最重要的事。

我选择的是清晨。这段时间不被世界打扰,效率是平时的 3 倍。

4️⃣ 打破"必须立刻回复"的幻觉

99% 的消息都能 2 小时后甚至明天回。

真正的尊重,是理解你的节奏。

5️⃣ 用行动代替焦虑

想学 AI 编程?别等"学完再开始"。

现在就动手,用 AI 帮你写代码,边做边学。

我那个 3 小时做出的小程序,就是这么来的。


五、写在最后

时间是一张大网,你屏蔽了什么,就会收获什么。

屏蔽了噪音,才能听见内心的召唤。
\
屏蔽了干扰,才能聚焦真正重要的事。
\
屏蔽了内耗,才能积攒向前的力量。

人生不过三万天,你无法控制世界有多吵,但可以决定自己听什么。

我选择屏蔽与核心目标无关的群聊,把时间留给 AI 编程、产品打磨、内容创作。

你呢?
从当下开始,也即可行动吧:

当你能屏蔽 99% 的噪音,剩下的 1%,就是你通往卓越的窄门。


我是Hugo,数字游民一枚,聚焦AI轻创&Web3&OPC,深耕AI编程应用开发实践,赋能个人蜕变成长&组织迭代进化,助力构建可持续的智能化增长体系。

如果你也对 AI 轻创&编程感兴趣,欢迎关注我,一起用 AI 把想法变成现实。

👇 评论区告诉我:你准备退掉哪个群?


本文由mdnice多平台发布

上文
https://v2ex.com/t/1170926#reply217

春节前在理发店扫地学徒

在我附近, 除了玩手机时间长还算省心
回家过年了,找小伙伴后 又变了:

  • 没和家里说就和小伙伴的父母去了市区玩 ,
  • 第 2 天 又没和家里说 去了县城, 通话时在日租房 晚 9 点说回来 凌晨 2 点多才到家.
    后来问说是小伙伴好了 3 年,失恋了(16 岁...那 13 岁就谈恋爱了)
    他去陪人喝酒了.

现在有 3 个选项

1 我倾向于考虑让去上中专

2 他自己想法:和小伙伴打零工 "网赚" 发短视频卖东西

  • 容易被骗 , 微信 手机号 淘宝 都被封过
  • 小伙伴抽烟
  • 没长期规划 一时一个想法

3 继续在我身边的理发店

  • 这个好处是不会学坏
  • 但他说就干 1 年 之后还是去打零工,1 年之后可能就彻底管不了他了
  • 初衷是希望能受自己影响学点东西 但他对电脑类的没兴趣儿

_________________________________________________________________

老哥们新年好,我是 Scrollie (一款长截图 app )的开发者,App 刚上线。

Scrollie 主要做一件事:
把 iPhone 录屏/多张截图,快速整理成一张干净长图。

这次在 V2EX 送 50 个「终身会员」兑换码( App 内购项目)

参与方式:在本帖回复邮箱( base64 或 原邮箱都行)

兑换方式( iOS / App 内购终身会员):

  1. 打开 App Store
  2. 右上角头像 -> 兑换充值卡或代码
  3. 输入兑换码
  4. 回到 Scrollie ,若未自动生效:设置页 -> 恢复购买

注意:兑换码有有效期,具体时间以邮件内为准

如果你用下来觉得顺手,欢迎在 App Store 留个真实评价;
不评价也完全没关系,先用起来最重要。

没有人会因为自己会开车而炫耀,
今后,写代码也是如此,不值一提。

花一天时间指挥 codex 写了一个安卓程序,而我从来没有写过安卓程序。

我一点也没有感觉自己厉害,因为我知道谁都会写,就像谁都会开车一样。

apk 大小大概 20m ,如果你想看看一天时间第一个 app 长什么样,发送邮件至 [email protected]

相信大家都看了最近机器人火热的话题,我觉得机器人续航还是有问题。只是应用还没到来,没有人提。

固定场所还好,直接连电线。外面就让他自己背个电源?

用 Qwen-Image 免费生成高质量线条风卡通图 —— 硅基流动体验分享

最近我在体验 硅基流动(SiliconFlow) 的 Qwen-Image 模型,真的有点惊喜。
它生成黑白线条风格卡通图的效果非常干净、简洁,而且提示词极其简单。

尤其适合:

  • 做工具站配图
  • 做博客插画
  • 做产品 UI 占位图
  • 生成素材做二次设计
  • 做 AI 卡通风格账号内容

最关键的是 —— 现在注册就送 2000 万 Token 额度,基本可以免费用很久。

👉 注册地址:
https://cloud.siliconflow.cn/


一句提示词直接出图

我实际测试使用的提示词只有这一句:

生成卡通的小动物登月的卡通图片黑白的简笔风格,卡通小动物模仿阿波罗登月的,图片上不要有任何文字

不需要复杂结构、不需要权重、不需要英文提示词。

生成效果特点:

  • 黑白线条干净
  • 简笔卡通风格明显
  • 构图清晰
  • 没有多余背景干扰
  • 画面无文字(可直接商用设计使用)

它会生成一个小动物模仿阿波罗登月的场景,比如:

  • 小兔子插旗
  • 小狗穿宇航服
  • 月球地表线条化表现
  • 卡通化宇宙背景

非常适合做:

  • 技术博客封面
  • AI 工具站插图
  • 科普文章配图
  • 产品营销素材

为什么我推荐用硅基流动的 Qwen-Image?

1️⃣ 免费额度非常大

注册直接送 2000 万 Token

对于图片生成来说,这个额度非常够用:

  • 日常玩图
  • 批量生成素材
  • 测试不同风格
  • 做网站内容

基本短期内完全不用花钱。


2️⃣ 接口调用方便

硅基流动是做模型托管的平台,支持:

  • API 调用
  • 在线 Playground
  • 多模型切换

不只是 Qwen-Image,还可以:

  • 跑 Qwen 大模型
  • 跑 DeepSeek
  • 跑各种开源模型

对做开发的人来说非常友好。


3️⃣ 线条风格表现很好

很多模型生成“简笔黑白线条”会:

  • 线条发灰
  • 风格不统一
  • 出现奇怪阴影
  • 出现多余文字

Qwen-Image 在这方面表现很稳:

  • 线条清晰
  • 对“不要文字”的理解准确
  • 卡通风格一致
  • 构图不乱

对于做工具站 UI 插图来说,真的很好用。


使用步骤非常简单

  1. 打开注册链接
    https://cloud.siliconflow.cn/i/i05xEFBt
  2. 注册账号(几分钟搞定)
  3. 体验中心选择图片生成,选择Qwen-image
  4. 输入提示词
  5. 生成图片

就这么简单。


适合哪些人?

  • 做 AI 工具站的开发者
  • 做内容创作的博主
  • 做 SaaS 产品的创业者
  • 做插画练习的设计师
  • 想低成本玩 AI 画图的人

如果你只是想:

“我要一个黑白线条风的小动物登月插图”

那它几乎就是直接出结果,不用折腾。


总结

硅基流动的 Qwen-Image:

  • ✅ 黑白线条风效果好
  • ✅ 提示词简单
  • ✅ 免费额度大(2000 万 Token)
  • ✅ 开发友好
  • ✅ 上手简单

如果你也想低成本玩 AI 画图,可以直接注册试试:

https://cloud.siliconflow.cn/


如果你觉得AI只能写代码,那你只用了它10%的能力。\
真正的高手,已经在用AI自动生成网站、自动部署项目、自动生成配图。\
而实现这一切的核心,就是:MCP

一、MCP是什么?为什么它这么重要

MCP,全称:

Model Context Protocol(模型上下文协议)

你可以理解为:

MCP = AI连接现实世界的接口

没有MCP,AI只能:

  • 写代码
  • 回答问题

有了MCP,AI可以:

  • 操作浏览器
  • 部署网站
  • 读取设计稿
  • 查询最新文档
  • 生成图片
  • 操作GitHub

AI从"聊天机器人",变成"真正开发者"。


二、为什么MCP是AI开发的关键

传统开发流程:

写代码
调试
部署
修改

AI + MCP流程:

描述需求
↓
AI生成代码
↓
AI生成图片
↓
AI部署上线
↓
AI完成项目

开发效率直接提升数倍。


三、推荐使用的MCP(核心)

这是我实际长期使用后筛选出来的。


1. Figma MCP

作用:

直接读取Figma设计稿,自动生成网站。

支持:

  • HTML
  • React
  • Next.js

效果:

设计稿 → 自动变网站

无需手写前端。


2. Context7 MCP

作用:

查询最新官方文档。

解决AI最大问题:

知识过期

例如:

  • 最新Python版本
  • 最新Next.js语法

AI可以实时获取。


3. Replicate MCP

作用:

自动生成图片。

可以生成:

  • 网站配图
  • 产品图
  • Banner图

无需设计师。


4. Vercel MCP

作用:

自动部署网站。

支持:

  • Next.js
  • React
  • Node.js

AI可直接发布网站上线。


5. Chrome DevTools MCP

作用:

AI直接控制浏览器。

可以:

  • 打开网页
  • 点击按钮
  • 调试页面

实现自动测试。


6. GitHub MCP

作用:

AI直接操作GitHub。

可以:

  • 创建仓库
  • 提交代码
  • 修改项目

实现自动开发流程。


7. 自定义 MCP

作用:

开发属于自己的AI工具。

支持:

  • Python
  • Node.js

扩展无限可能。


四、真实演示案例

生成一个网站

AI自动完成:

  • 创建前端页面
  • 生成网站图片
  • 完成页面结构
  • 部署网站上线

整个过程:

几乎无需人工干预。


五、MCP为什么会成为未来标准

因为它解决了AI的核心限制:

让AI可以:

  • 使用工具
  • 操作系统
  • 操作浏览器
  • 操作数据库
  • 操作部署平台

AI从"建议者"变成"执行者"


六、MCP带来的真正改变

过去开发:

人写代码

未来开发:

人描述需求
↓
AI完成开发

MCP就是关键基础设施。


七、总结

一句话总结:

MCP让AI第一次真正具备开发能力

它让AI可以:

  • 写代码
  • 生成图片
  • 部署网站
  • 操作浏览器
  • 管理项目

开发正式进入:

AI自动化时代。

本文由mdnice多平台发布

这是我春节期间借助 codex ,消耗了将近 2 亿 token 写的一个本地化部署回测平台。
暂时先支持 A 股日线的回测和研究。
出发点主要是:在本地实现策略回测和研究,完全在本地运行,不依赖第三方平台,保障策略隐私安全

系统截图


一、项目地址

https://github.com/bloom8262/backquant

二、项目亮点

  • 完整的量化回测平台:包括回测工作台和研究工作台两个主要功能。
  • 技术栈:后端是 Flask+RQAlpha ,前端是 Vue ,提供良好的用户体验。
  • 支持 A 股市场数据:内置 RQAlpha 的日线数据( 2005 年–2026 年)。
  • 部署友好:推荐使用 Docker 一键部署,包含依赖和数据下载。
  • 集成 Jupyter Lab:方便做策略研究、数据分析和可视化笔记。


目前项目刚起步,随着我自己的深度使用,会逐渐迭代~
如果你也想在本地进行量化研究和回测,或者学习 Python 量化策略,欢迎 star ,提 issue 一起完善~

项目地址:https://github.com/bloom8262/backquant

项目去年年中重构到现在大概收到了 200 CNY 左右的赞助?从收到第一份开始就觉得出乎意料,压根没想过会有这么多朋友用哈哈哈🤣

第一次收到打赏的时候 还是非常激动的,感觉比 收到第一份工资的时候 还要有成就感一些 ✌️

年底老婆说想带儿子女儿去东北玩, 我说人太多我不去, 我之前刷抖音, 看三星堆很神奇, 想去看看

我就大年初一开车出发了, 走沪蓉高速, 后来开到一半, 在服务区充电的时候, 想预约第二天的三星堆门票,

结果发现一直到 2.24 都无法预约, 连 ctrip 的高价 900 多的一日游都表示无预约, 只好作罢,

既然开到一半了, 就去湖南张家界吧. 先买了第二天天门山的门票, 就是翼装飞行钻山洞的那个山.

晚上到酒店, 第二天睡到 9:00, 起来吃个早饭, 就出发 , 我买的速通票, 上山索道免排队,

到了景区, 风景是真的好, 人也是真的都多, 天门洞的楼梯我是一级一级爬上去的, 中途心跳 160 多, 歇了 2 次,

过了山洞, 就有自动扶梯上山了, 好几段, 刷刷手机, 很快就到了, 到了山顶, 顺着东线绕一圈, 一两个小时,

回头下电梯的时候, 已经排了上万人了, 就是你看见电梯口, 走到队伍尾巴, 可能还要走 1-2km,

这期间, 几乎都是被挤着走的,走 2 步, 停 5 分钟, 这样, 幸亏带着耳机刷手机, 16:30 排队, 一直到 18:30 才出景区,

虽然人多, 但是张家界毕竟是成熟的景区, 很多应对方案, 包括临时停车场, 包括接驳车, 总体在春节期间, 还是相当不错了.

第二天去了武陵源景区, 就是阿凡达山, 网上做了详细攻略, 把之前买的索道和电梯票都退了, 直接开车去北门进景区,

大门直接就到半山腰了, 做接驳车就到山顶了, 可以不坐电梯和索道了.

6:30 就到景区了, 做了第一班车, 到景区的时候, 是和工作人员一趟车, 一个上午, 就把杨家界, 袁家界, 天子山核心景区都看了,

的确是漂亮, 壮观, 非常值得.下午就返程, 1000 多公里, 夜里凌晨就到家了.

老婆孩子自己没订到东北的机酒, 去昆明了.我一直睡到早上 9:00.

体会:
1.年纪大了, 特种兵旅游, 还是有些吃力. 特别是天门山 999 级台阶, 高估自己了, 一开始太快, 导致心跳 160, 后来降速, 才缓过来.

2.辅助驾驶跑高速真舒服, 这次来回 2000 多公里, 磕嗑瓜子, 听听播客,很轻松.

3.服务区充电, 很多服务区都有不止一个品牌充电站, 春节期间, 一般来说还是够用的。就是速度比不上超充, 特别是国网的还限功率, 一两年前功率 100 多 kw, 后来是 92kw, 现在基本上是 80kw. 反正充一次, 跑 300 多 km, 凑合吧.

4.现在年纪大了, 越来越烦过年了, 不想留在家跑亲戚, 但是你在家, 不跑也不行, 不如就出去旅游吧, 反正一年也就只有这个时间能旅游, 涨价就涨价吧.

今日速览

  1. Gemini 3.1 Pro:专治复杂任务,推理能力再进化。
  2. Google Pomelli:产品照一键升级,营销效果拉满。
  3. Architect by Lyzr:像搭积木一样,构建透明可控的 AI 系统。
  4. Claudebin:导出 Claude 终端会话,分享协作更轻松。
  5. Arcmark:开源书签侧边栏,浏览器窗口随叫随到。
  6. keychains.dev:AI 安全调用 API,零凭证暴露风险。
  7. Guideless:几分钟搞定 AI 解说视频,字幕配音全自动。
  8. NotchPrompt:MacBook 刘海藏提词器,视频会议眼神不飘。
  9. Repaint:跟 AI 聊聊天,定制网站快速生成。
  10. Merge:苹果手表配安卓手机,健康数据通知两不误。


1. Gemini 3.1 Pro

这款 AI 模型专为硬核任务而生,当简单答案不够用时,它就能派上用场。基于 Gemini 3 系列,它在核心推理上更上一层楼,帮你搞定那些烧脑的复杂问题。

  • 智能处理复杂任务,告别简单答案
  • 核心推理能力显著提升
  • 提供更强大、更智能的基础模型
  • 适用于高级问题解决场景

热度:🔺436

Gemini 3.1 Pro

访问官网 Product Hunt 详情


2. Google Pomelli

想让产品照片瞬间变专业?这款工具能帮你从一张普通图片开始,轻松打造高质量、个性化的营销素材。

  • 一键将产品照片转为专业影像
  • 支持从零创建和编辑产品图像
  • 通过描述或上传参考图快速定制
  • 提升营销效果,节省拍摄成本

热度:🔺359

Google Pomelli

访问官网 Product Hunt 详情


3. Architect by Lyzr

想象一下,把 N8N 和 Lovable 结合起来会怎样?这款工具就能帮你构建多智能体 AI 系统,让每个决策和流程都清晰可见,告别黑箱操作。

  • 构建强大的多智能体 AI 系统
  • 在编码前可视化控制决策和集成
  • 流程透明,无需猜测
  • 灵感来自 N8N 和 Lovable 的结合

热度:🔺322

Architect by Lyzr

访问官网 Product Hunt 详情


4. Claudebin

Claude Code 的终端会话数据存在本地,但不易分享和复用。这款工具让你一键导出会话,捕获完整对话和操作记录,方便协作和文档嵌入。

  • 导出 Claude Code 终端会话为可恢复链接
  • 捕获消息对话、文件读写、Bash 命令等
  • 提供结构化、可导航的查看器
  • 支持在 PR、文档中嵌入或本地继续会话

热度:🔺225

Claudebin

访问官网 Product Hunt 详情


5. Arcmark

受 Arc 浏览器侧边栏启发,这款原生 macOS 书签管理器能附加到任何浏览器窗口,开源免费,数据优先本地存储。

  • 作为侧边栏附加到任何浏览器窗口
  • 原生 macOS 应用,开源且免费
  • 本地优先存储,保护隐私
  • 设计灵感来自 Arc 浏览器侧边栏

热度:🔺200

Arcmark

访问官网 Product Hunt 详情


6. keychains.dev

AI 代理调用 API 时,硬编码凭证容易暴露风险。这款工具提供安全代理服务,用模板变量替换凭证,服务器端注入,实现零暴露。

  • 为 AI 代理提供安全凭证代理服务
  • 使用模板变量(如 {{GITHUB_TOKEN}})替换硬编码凭证
  • 服务器端注入真实凭证,防止提示注入攻击
  • 支持一键权限批准和撤销,提供完整审计记录
  • 兼容超过 11,000 个 API 提供商

热度:🔺193

keychains.dev

访问官网 Product Hunt 详情


7. Guideless

厌倦了臃肿的引导工具?这款软件专注用户体验,能快速制作 AI 解说的视频指南,自动生成字幕,提供多语言配音,成品高端易分享。

  • 几分钟内制作 AI 解说的软件视频指南
  • 自动生成字幕,增加 AI 优化
  • 提供多种自然流畅的多语言 AI 配音
  • 输出符合品牌形象的高质量指南
  • 支持轻松分享、嵌入或导出为 MP4

热度:🔺159

Guideless

访问官网 Product Hunt 详情


8. NotchPrompt

视频会议时低头看笔记太尴尬?这款工具将稿件环绕在 MacBook 摄像头缺口周围,让你保持完美眼神交流,屏幕共享时还完全隐形。

  • 将提词器文本环绕在 MacBook 刘海周围
  • 保持眼神交流,提升演讲效果
  • 屏幕共享时 100% 隐形,观众看不到文本
  • 基于原生 Swift 和 SwiftUI,支持自动滚动和快捷键
  • 完全免费且开源

热度:🔺142

NotchPrompt

访问官网 Product Hunt 详情


9. Repaint

想建网站但不懂代码?跟这个 AI 助手聊聊天,它就能收集信息、找设计参考,几分钟内帮你生成一个定制网站。

  • 通过与 AI 聊天创建定制网站
  • 对话收集信息,寻找设计参考
  • 几分钟内生成完整网站
  • 简化网站建设流程,无需编码

热度:🔺112

Repaint

访问官网 Product Hunt 详情


10. Merge

终于,苹果手表能和安卓手机配对了!这款工具解锁健康数据同步,在手腕上接收通知、回复信息,打破设备壁垒。

  • 将 Apple Watch 与任何 Android 手机配对使用
  • 解锁苹果手表的先进健康数据,同步到 Health Connect 应用
  • 在手腕上接收安卓通知,回复信息,控制媒体播放
  • 实现跨平台设备互通,扩展使用场景

热度:🔺108

Merge

访问官网 Product Hunt 详情