Supermind 同花顺官方量化平台实现本地交易api功能 实盘用的代码重构后分享 不适合个人,比较贵

# -*- coding: utf-8 -*-
"""
简化和重构后的同花顺交易相关数据处理脚本

主要功能:
1. 定期从 Supermind API 获取指定账户的资产和持仓信息,并存入 Redis。
2. 监听 Redis 中的交易信号列表,并将新信号写入本地文件后上传。

依赖库:
- redis_api (假设是本地封装的 Redis 操作库)
- supermind (包含 api 和 mod.tradeapi.api)
- ts_api (假设是本地封装的 Tushare 或类似数据接口)
- pandas
- os
- time
- threading

假设存在一个名为 `disp` 的辅助函数,用于获取格式化的中文日期/时间字符串。
假设 `redis_api`, `ts_api` 已正确配置和实现。
"""

import os
import time
import threading
import pandas as pd
from redis_api import redis_api  # 假设的 Redis 操作库
from supermind.api import get_api_usage, download_file, upload_file # Supermind 基础 API
from supermind.mod.tradeapi.api import TradeAPI, TradeCredit # Supermind 交易 API
from ts_api import ts_api # 假设的 Tushare 封装

# --- 全局初始化与配置 ---

# 检查 Supermind API 使用情况
try:
    get_api_usage()
except Exception as e:
    print(f"检查 Supermind API 使用情况失败: {e}")

# 初始化 Redis 连接 (假设 dbG=2 用于特定数据库)
try:
    redisD = redis_api(dbG=2)
    print("Redis 连接成功 (dbG=2)")
except Exception as e:
    print(f"初始化 Redis 连接失败: {e}")
    # 可能需要退出或进行错误处理
    exit()

# 初始化 Tushare API (用于获取交易日历)
try:
    ts = ts_api()
    # 获取2023年至今的交易日期,假设 disp 函数存在且能格式化
    # 注意:原始代码中 disp(strTime='日期_') 的具体格式未知,这里假设为 'YYYYMMDD'
    # dateD = ts.get_date('20230101', disp(strTime='日期_'))
    # 为了代码能独立运行,我们先用 Tushare 的标准方法获取,后续可能需要调整 disp
    dateD = ts.get_trade_cal(start_date='20230101', end_date=time.strftime('%Y%m%d'), is_open=1)
    dateD = dateD[['cal_date']].rename(columns={'cal_date': 'date'}) # 提取交易日期列并重命名
    print("交易日历获取成功")
except Exception as e:
    print(f"初始化 Tushare API 或获取交易日历失败: {e}")
    # 如果交易日历是核心功能,可能需要退出
    dateD = pd.DataFrame({'date': []}) # 提供空 DataFrame 以免后续代码出错


def get_date_d1d2(trade_dates_df):
    """
    获取当前日期和上一个交易日日期。

    Args:
        trade_dates_df (pd.DataFrame): 包含 'date' 列的交易日历 DataFrame (格式 YYYYMMDD)。

    Returns:
        tuple: (d1, d2),d1 是当天或之前的最后一个交易日,d2 是 d1 之前的交易日。
               如果找不到足够的日期,可能会返回相同日期。
    """
    try:
        # 假设 disp 函数返回 'YYYYMMDD' 格式
        dateNow = time.strftime('%Y%m%d') # 使用当前日期代替 disp
        # 筛选出不晚于今天的交易日
        valid_dates = trade_dates_df[trade_dates_df['date'] <= dateNow]['date'].values
        if len(valid_dates) >= 2:
            d1 = valid_dates[-1]
            d2 = valid_dates[-2]
        elif len(valid_dates) == 1:
            d1 = valid_dates[-1]
            d2 = valid_dates[-1] # 如果只有一个,d2 等于 d1
        else:
            # 没有找到合适的交易日,返回今天作为备选
            d1 = dateNow
            d2 = dateNow
            print("警告: 未能在交易日历中找到今天或之前的交易日。")
        return d1, d2
    except Exception as e:
        print(f"获取 d1, d2 日期时出错: {e}")
        # 返回当前日期作为备选
        today = time.strftime('%Y%m%d')
        return today, today

# 获取当前和上一交易日
d1, d2 = get_date_d1d2(dateD)
print(f"当前交易日 (d1): {d1}, 上一交易日 (d2): {d2}")


# --- 定义数据列名 ---
# 这些列表定义了从不同来源读取或写入数据时 DataFrame 的列名
# 账户资产信息列名
ASSET_COLS = ['时间', '净资产', '总资产', '可用资金']
# 持仓信息列名
POSITION_COLS = ['时间', '证券代码', '证券数量', '可卖数量', '成本价', '当前价']
# 委托/订单信息列名 (此脚本中未使用,但保留定义以备将来使用)
# ORDER_COLS = ['时间','证券代码','证券名称','委托编号','方向','委托时间','状态','委托数量','委托价格', '成交数量','成交价格']


# --- 账户配置 ---
# 需要监控的账户 ID 列表
# 注意:区分普通账户和信用账户,因为它们使用不同的 API 类
NORMAL_ACCOUNTS = ['56555', '69069316', '69085414', '101345718', '101702950', '69085393', '62638225']
CREDIT_ACCOUNTS = ['4144'] # 假设这是信用账户

# --- Supermind Trade API 初始化 ---
trade_api_instances = {}
try:
    for account_id in NORMAL_ACCOUNTS:
        trade_api_instances[account_id] = TradeAPI(account_id)
        print(f"普通账户 TradeAPI 初始化成功: {account_id}")
    for account_id in CREDIT_ACCOUNTS:
        trade_api_instances[account_id] = TradeCredit(account_id) # 信用账户使用 TradeCredit
        print(f"信用账户 TradeCredit 初始化成功: {account_id}")
except Exception as e:
    print(f"初始化 Supermind Trade API 实例时出错: {e}")
    # 根据需要决定是否继续

# --- 核心类定义 ---
class ThsTraderHelper:
    """
    同花顺智能交易辅助类,用于管理账户数据获取和交易信号处理。
    """
    def __init__(self, trade_apis, redis_conn, today_date):
        """
        初始化辅助类。

        Args:
            trade_apis (dict): 包含账户ID到TradeAPI/TradeCredit实例的字典。
            redis_conn: Redis 连接实例。
            today_date (str): 当天日期 (YYYYMMDD),用于 Redis key。
        """
        self.trade_apis = trade_apis
        self.redisD = redis_conn
        self.d1 = today_date # 保存当天日期,用于 Redis hset
        self.dataG = {}  # 用于存储运行时状态,如信号列表长度
        self.posGA = {}  # 用于缓存账户的持仓信息,减少不必要的 Redis写入
        self.accounts_to_monitor = list(trade_apis.keys()) # 获取所有需要监控的账户ID
        # 标记是否首次运行持仓检查,用于首次强制写入 Redis
        self.first_pos_check = {acc_id: True for acc_id in self.accounts_to_monitor}

    def _get_current_time_str(self):
        """获取当前格式化的日期时间字符串 (模拟 disp 函数)"""
        # 假设 disp(strTime='日期时间') 返回 'YYYY-MM-DD HH:MM:SS'
        return time.strftime('%Y-%m-%d %H:%M:%S')

    def _get_current_date_str(self):
        """获取当前格式化的日期字符串 (模拟 disp 函数)"""
        # 假设 disp(strTime='日期_') 返回 'YYYYMMDD'
        return time.strftime('%Y%m%d')


    def fetch_and_store_account_data(self):
        """
        定期获取并存储所有监控账户的资产和持仓数据到 Redis。
        """
        last_check_time = time.time()
        print("启动账户数据获取线程...")

        while True:
            now = time.time()
            # 每 5 分钟强制更新一次持仓,或者首次运行时更新
            force_pos_update = (now - last_check_time) > 300 # 300秒 = 5分钟

            if force_pos_update:
                last_check_time = now
                print(f"{self._get_current_time_str()} - 触发持仓强制更新检查")

            for account_id in self.accounts_to_monitor:
                try:
                    if account_id not in self.trade_apis:
                        print(f"警告: 账户 {account_id} 没有对应的 Trade API 实例,跳过。")
                        continue

                    api = self.trade_apis[account_id]

                    # 1. 获取资产信息
                    portfolio_data = api.portfolio
                    # 兼容不同 API 可能返回的字段名 ('net_assets' 或 'total_value')
                    net_assets = portfolio_data.get('net_assets', portfolio_data.get('total_value', 0))
                    available_cash = portfolio_data.get('available_cash', 0)

                    # 格式化数据
                    asset_info = [[
                        self._get_current_time_str(),
                        round(net_assets / 10000, 2), # 单位:万元
                        round(net_assets / 10000, 2), # 总资产用净资产代替(根据原代码逻辑)
                        round(available_cash / 10000, 2) # 单位:万元
                    ]]
                    df_asset = pd.DataFrame(asset_info, columns=ASSET_COLS)

                    # 存储到 Redis
                    redis_key_asset = f'asset_{account_id}'
                    redis_key_asset_hist = f'asset_his_{account_id}'
                    asset_dict_str = str(df_asset.to_dict(orient="records"))
                    self.redisD.set(redis_key_asset, asset_dict_str)
                    # 使用 hset 存储当日历史记录,键是日期 d1
                    self.redisD.hset(redis_key_asset_hist, self.d1, asset_dict_str)
                    # print(f"账户 {account_id} 资产信息已更新到 Redis") # 调试信息,可注释掉

                    # 2. 获取持仓信息 (仅在需要时或强制更新时)
                    should_update_pos = force_pos_update or self.first_pos_check[account_id]

                    if should_update_pos:
                        positions = api.positions
                        pos_list = []
                        for symbol, pos_details in positions.items():
                            # 确保持仓数量大于0
                            if pos_details.get('amount', 0) > 0:
                                pos_list.append({
                                    '时间': self._get_current_time_str(),
                                    '证券代码': pos_details.get('symbol', symbol),
                                    '证券数量': pos_details.get('amount', 0),
                                    '可卖数量': pos_details.get('available_amount', 0),
                                    '成本价': pos_details.get('cost_basis', 0.0),
                                    '当前价': pos_details.get('last_price', 0.0)
                                })

                        df_pos = pd.DataFrame(pos_list, columns=POSITION_COLS) if pos_list else pd.DataFrame(columns=POSITION_COLS)

                        # 比较当前持仓与缓存,仅在变化时或首次检查时写入 Redis
                        pos_summary_str = str(df_pos[['证券代码', '证券数量']].values.tolist())
                        cached_pos = self.posGA.get(account_id)

                        if self.first_pos_check[account_id] or cached_pos != pos_summary_str:
                            redis_key_pos = f'pos_{account_id}'
                            self.redisD.set(redis_key_pos, str(df_pos.to_dict(orient="records")))
                            self.posGA[account_id] = pos_summary_str # 更新缓存
                            if not self.first_pos_check[account_id]:
                                print(f"{self._get_current_time_str()} - 账户 {account_id} 持仓发生变化,已更新到 Redis。")
                            else:
                                print(f"{self._get_current_time_str()} - 账户 {account_id} 首次持仓信息已写入 Redis。")
                            self.first_pos_check[account_id] = False # 不再是首次检查
                        # else:
                            # print(f"账户 {account_id} 持仓无变化,跳过 Redis 写入。") # 调试信息

                except Exception as ex:
                    print(f"{self._get_current_time_str()} - 处理账户 {account_id} 数据时出错: {ex}")

            # 短暂休眠,避免过于频繁的 API 请求
            time.sleep(5) # 轮询间隔调整为 5 秒

    def _write_signal_to_file_and_upload(self, order_data, mode='a', separator='\n'):
        """
        将单个订单信号写入本地文件,然后上传。

        Args:
            order_data (list or str): 订单数据。
            mode (str): 文件写入模式 ('a' for append, 'w' for write).
            separator (str): 行分隔符。
        """
        signal_file = './ths_data/sig.txt' # 本地信号文件路径
        os.makedirs(os.path.dirname(signal_file), exist_ok=True) # 确保目录存在

        try:
            # 格式化信号数据为字符串
            if isinstance(order_data, list):
                # 移除列表的中括号,元素间用逗号分隔
                content_to_write = ", ".join(map(str, order_data))
            else:
                content_to_write = str(order_data)

            # 写入文件
            with open(signal_file, mode=mode, encoding='utf-8') as f:
                if mode == 'a' and os.path.getsize(signal_file) > 0: # 追加模式且文件非空时加分隔符
                    f.write(separator)
                f.write(content_to_write)
            # print(f"信号已写入本地文件: {signal_file}") # 调试信息

            # 上传文件到 Supermind (假设 path='' 表示上传到默认路径)
            upload_file(signal_file, path='')
            # print(f"信号文件已上传: {signal_file}") # 调试信息

        except Exception as e:
            print(f"{self._get_current_time_str()} - 写入或上传信号文件 {signal_file} 时出错: {e}")

    def monitor_and_process_redis_signals(self):
        """
        监听 Redis 列表中的新交易信号,并将其处理(写入文件并上传)。
        """
        redis_signal_key = 'sig' + self._get_current_date_str() # Redis key: sigYYYYMMDD
        print(f"启动 Redis 信号监听线程 (Key: {redis_signal_key})...")

        # 初始化上次处理的列表长度
        try:
            last_list_count = self.redisD.llen(redis_signal_key)
            self.dataG['list_count'] = last_list_count
            print(f"初始 Redis 列表 '{redis_signal_key}' 长度: {last_list_count}")

            # 首次运行时,写入一个虚拟信号(如果需要初始化文件)
            if last_list_count == 0:
                 # 根据原代码逻辑,可能需要在启动时清空并写入一个标记性内容
                 dummy_signal = ['初始化标记', '000000.SZ', 0, 0, 0, 0, self._get_current_time_str()]
                 print("Redis 列表为空,写入初始标记信号到本地文件...")
                 # 使用 'w' 模式覆盖旧文件(如果有的话)
                 self._write_signal_to_file_and_upload(dummy_signal, mode='w', separator='')
            else:
                 # 如果列表非空,确保本地文件存在且内容与云端同步(这里简化为仅上传一次最新信号)
                 # 这里可以优化为下载云端sig.txt与本地比较,或假设本地总是需要被云端覆盖
                 # 为了简化,我们只在检测到新信号时追加
                 pass


        except Exception as e:
            print(f"初始化 Redis 信号监听时出错 (Key: {redis_signal_key}): {e}")
            self.dataG['list_count'] = 0 # 出错时设为0

        while True:
            try:
                current_list_count = self.redisD.llen(redis_signal_key)
                last_processed_count = self.dataG.get('list_count', 0)

                if current_list_count > last_processed_count:
                    print(f"{self._get_current_time_str()} - 检测到 Redis 列表 '{redis_signal_key}' 中有 {current_list_count - last_processed_count} 条新信号。")
                    # 获取新增的信号 (从上次数目之后到列表末尾)
                    new_signals_raw = self.redisD.lrange(redis_signal_key, last_processed_count, -1)
                    new_signals = [s.decode('utf-8') for s in new_signals_raw] # 解码

                    # 处理并上传每一条新信号
                    for signal_str in new_signals:
                        print(f"  处理新信号: {signal_str}")
                        # 假设信号是字符串形式的列表或元组,尝试 eval 解析
                        # !!! 注意:eval 非常危险,如果来源不可信,应使用更安全的方法如 json.loads !!!
                        try:
                            # 假设信号字符串可以直接被 eval 解析成列表
                            order_data = eval(signal_str)
                            # 将解析后的信号追加写入文件并上传
                            self._write_signal_to_file_and_upload(order_data, mode='a', separator='\n')
                        except Exception as parse_ex:
                            print(f"  解析信号 '{signal_str}' 时出错: {parse_ex}. 跳过此信号。")

                    # 更新已处理的列表长度
                    self.dataG['list_count'] = current_list_count

            except Exception as ex:
                print(f"{self._get_current_time_str()} - 监听 Redis 信号 (Key: {redis_signal_key}) 时发生异常: {ex}")

            # 每隔几秒检查一次
            time.sleep(5) # 信号检查间隔

    def start_all_threads(self):
        """启动所有后台任务线程。"""
        print("准备启动后台线程...")
        # 创建并启动账户数据获取线程
        thread1 = threading.Thread(target=self.fetch_and_store_account_data, args=(), daemon=True)
        thread1.start()
        print("账户数据获取线程已启动。")

        # 创建并启动 Redis 信号监听线程
        thread2 = threading.Thread(target=self.monitor_and_process_redis_signals, args=(), daemon=True)
        thread2.start()
        print("Redis 信号监听线程已启动。")

        print("所有后台线程已启动。主线程将等待 (或执行其他任务)。")
        # 让主线程保持运行,以便 daemon 线程可以继续工作
        while True:
            time.sleep(60) # 主线程可以休眠或执行其他监控任务


# --- 主程序入口 ---
if __name__ == '__main__':
    print("程序开始执行...")

    # 实例化核心类
    helper = ThsTraderHelper(
        trade_apis=trade_api_instances,
        redis_conn=redisD,
        today_date=d1 # 传入当天日期
    )

    # 启动所有后台服务
    helper.start_all_threads()

    # 主线程可以阻塞在这里,或者执行其他前台任务
    # 由于线程是 daemon=True,主线程退出时它们也会退出
    # 如果希望主线程等待子线程(虽然这里不需要),可以使用 thread.join()
    print("主程序初始化完成,后台任务运行中...")
    # 在实际应用中,这里可能是一个无限循环或者等待某个退出信号
    # time.sleep(3600) # 例如,运行一小时后退出

代码解释与重构说明:

  1. 依赖清理:

    • 移除了 spider_api 的导入和使用,因为它在原代码中被 ts_api 覆盖且未使用。
    • 移除了 numpy 的直接导入,因为 pandas 内部会处理 numpy,除非特定版本兼容性需要,否则直接导入非必需。
    • 保留了 os, time, threading, pandas 以及自定义的 redis_api, supermind, ts_api
  2. 全局变量与配置:

    • API 初始化 (get_api_usage, redisD, ts) 放在脚本开头,并增加了简单的 try-except 块来提示初始化成功或失败。
    • 交易日历获取 (get_date_d1d2) 被保留,用于获取 d1 (当天或最近交易日) 和 d2 (上一交易日)。d1 主要用于 Redis 的 hset 键。增加了错误处理。
    • 账户列表 (NORMAL_ACCOUNTS, CREDIT_ACCOUNTS) 被明确定义在配置区,而不是依赖于下载文件,使代码更清晰、独立。
    • TradeAPITradeCredit 的实例化基于上述明确的账户列表,存储在 trade_api_instances 字典中,供后续使用。移除了原代码中冗余和令人困惑的 trade_api 初始化逻辑。
    • 列名常量 (ASSET_COLS, POSITION_COLS) 被定义,提高了可读性。
  3. 类结构 (ThsTraderHelper):

    • 将核心逻辑封装在 ThsTraderHelper 类中,提高了代码的组织性。
    • __init__ 方法接收必要的依赖(API实例、Redis连接、日期)并初始化内部状态(dataG, posGA)。
    • posGA (持仓缓存) 和 first_pos_check (首次检查标记) 被移到 __init__ 中作为实例属性,更符合面向对象的设计。
    • 移除了原代码中未使用的 is_time 方法和被注释掉的 下载客户端数据run 方法。核心功能由 fetch_and_store_account_data 替代。
  4. 账户数据获取 (fetch_and_store_account_data):

    • 此方法取代了原代码中注释掉的 下载客户端数据run 和部分 获取客户端数据run 的逻辑。
    • 它直接使用 trade_api_instances 中的 Supermind API 对象 (api.portfolio, api.positions) 来获取实时数据,而不是依赖下载/读取本地文件。这更直接高效。
    • 对所有配置的账户进行迭代处理。
    • 资产处理: 获取资产信息,进行单位转换(万元),格式化为 DataFrame,然后存入 Redis 的 set (最新值) 和 hset (当日历史值)。
    • 持仓处理:
      • 增加了 force_pos_update 逻辑(每5分钟)和 first_pos_check 标记,以确保持仓定期刷新或在首次运行时写入 Redis。
      • 获取持仓信息,过滤掉数量为0的持仓。
      • 将当前持仓的关键信息(代码、数量)与 posGA 缓存进行比较。
      • 仅在持仓发生变化或需要强制更新时,才将完整的持仓 DataFrame 存入 Redis (set) 并更新 posGA 缓存。这大大减少了不必要的 Redis 写入操作。
    • 增加了更详细的日志输出(打印消息)和错误处理。
    • 轮询间隔设为 5 秒,可以根据实际需求调整。
  5. 信号处理 (_write_signal_to_file_and_upload, monitor_and_process_redis_signals):

    • _write_signal_to_file_and_upload: 封装了将信号写入本地 sig.txt 文件并上传到 Supermind 的逻辑。增加了目录检查 (os.makedirs) 和文件写入模式处理(追加时加换行符)。
    • monitor_and_process_redis_signals:
      • 此方法取代了原代码的 读取信号下单run
      • 监听 Redis 中特定格式的列表 (sigYYYYMMDD)。
      • 使用 llenlrange 高效地获取新增的信号,避免重复处理。
      • 警告: 仍然使用 eval() 来解析从 Redis 获取的信号字符串。这存在安全风险,如果信号来源不可控,强烈建议改用更安全的数据交换格式(如 JSON)和解析方法 (json.loads)。
      • 对每个新信号,调用 _write_signal_to_file_and_upload 进行处理。
      • 增加了初始化逻辑:检查列表是否为空,如果是,则写入一个初始标记到文件(覆盖模式)。
      • 包括了错误处理和日志记录。
      • 轮询间隔设为 5 秒。
  6. 线程管理 (start_all_threads):

    • 提供一个方法来启动两个核心功能的后台线程:账户数据获取和信号监听。
    • 线程被设置为 daemon=True,这意味着当主线程退出时,这些后台线程会自动终止。
    • 主线程中使用 while True: time.sleep(60) 来保持运行,允许后台线程工作。在实际部署中,这部分可能需要更复杂的生命周期管理。
  7. 主程序 (if __name__ == '__main__':):

    • 清晰地展示了如何实例化 ThsTraderHelper 类并启动其服务。
  8. 辅助函数 (disp):

    • 原代码依赖一个未提供的 disp 函数。重构后的代码用标准的 time.strftime 替代了 disp 来获取日期和时间字符串,并假设了其输出格式。如果 disp 有特殊功能(如获取交易时间),则需要将其实现或替换为相应逻辑。

总结:

重构后的代码更加结构化、模块化,易于理解和维护。它消除了冗余代码,明确了配置,并直接使用 API 获取数据,提高了效率和实时性。同时,通过缓存比较减少了不必要的 Redis 写入。错误处理和日志记录也得到了加强。主要的潜在问题是 eval() 的使用,应考虑替换为更安全的替代方案。

### 配置和使用 Dify ChatFlow 企业知识库 Dify 是一种强大的工具,用于构建基于 AI 的聊天机器人解决方案,特别是针对企业的知识管理需求。以下是关于如何设置和使用 Dify ChatFlow 企业知识库的相关说明。 #### 安装与初始化 为了启动并运行 Dify ChatFlow,首先需要安装必要的依赖项以及完成环境配置。这通常涉及以下几个方面: - **Ollama 集成**:如果计划利用本地模型部署功能,则需先按照指南安装 Ollama 并确保其正常工作[^1]。 ```bash pip install dify-cli dify init ``` 上述命令会引导用户通过 CLI 工具来初始化项目结构,并自动下载所需的默认资源文件。 #### 创建知识库 创建一个新的知识库可以通过图形界面或者 API 接口实现。对于初学者来说,推荐从 GUI 开始操作更为直观简便。 - 登录到官方提供的控制面板后点击新建按钮即可开启向导流程; - 导入已有文档资料作为初始数据源支持 PDF Word Excel等多种格式转换处理; #### 自定义对话逻辑 (Chat Flow) 除了单纯的知识检索外还可以进一步增强交互体验比如加入条件分支判断等复杂场景模拟真客服交流过程。 开发者能够借助 YAML 文件描述整个交谈路径图谱其中节点代表同阶段状态而边则表示可能发生的转移事件例如提问类型匹配成功与否等等情况下的下一步动作指引规则设定如下所示例子展示了一个简单的产品咨询解答模板设计思路: ```yaml version: 'v1' nodes: start: type: input message: "您好,请问有什么可以帮您的吗?" next: check_product_question check_product_question: type: condition conditions: - when: "{{ user_input.contains('产品') }}" then: provide_product_info - otherwise: default_response provide_product_info: type: output message: "我们目前主要销售以下几类商品..." end: true default_response: type: output message: "抱歉我没有理解清楚您的意思,请重新表述一下问题好吗?" next: start ``` 此段脚本定义了一套基本框架当检测到来自用户的输入包含特定关键词时给予相应的反馈否则返回通用提示语句循环往复直至满足结束条件为止。 #### 测试优化调整参数表现效果评估指标选取标准等方面的内容由于篇幅所限这里再详述感兴趣的朋友可查阅官方文档获取更多细节信息参考资料链接地址列表见下方备注部分最后附上几个值得思考探讨的方向供参考学习之用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值