07_02.表格合并及实例

此页面展示了四个城市的天气预报信息,包括北京、上海、广州和西昌的日夜天气情况,如温度、天气状况及风力等。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
	<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
	<title>Document</title>
	<style type="text/css">
body {
	margin: 0;
}
img {
	border: 0;
}
table {
	border-collapse: collapse;
}
th, td {
	padding: 0;
}
.wrap {
	width: 385px;
	height: 272px;
}
.wrap .tit {
	width: 383px;
	height: 26px;
	background: #f0f5f9;
	border: solid 1px #dfe7ea;
	border-bottom: none;
	vertical-align: top;
	line-height: 26px;
	font-weight: bold;
}
.wrap .tit .left {
	font-size: 12px;
	color: #004599;
	float: left;
	margin-left: 10px;
	display: inline;
}
.wrap .tit .right {
	font-size: 12px;
	color: #004599;
	float: right;
	margin-right: 11px;
	display: inline;
}
.wrap .tab {
	width: 385px;
	height: 245px;
}
.wrap .tab td {
	border: solid 1px #e2e7eb;
	background: #f6fbff;
	font-size: 12px;
	text-align: center;
}
.wrap .tab .night td {
	height: 30px;
}
.wrap .tab .night td span {
	color: #3a9be0;
}
.wrap .tab .day td {
	height: 29px;
}
.wrap .tab img {
	vertical-align: top;
}
</style>
	</head>
	<body>
    <div class="wrap">
      <div class="tit"><span class="left">我关注的城市天气</span><span class="right">定制</span></div>
      <table class="tab">
        <tbody>
          <tr class="night">
            <td rowspan="2" width="60"><span>北京</span></td>
            <td width="60">25日夜晚</td>
            <td width="36"><img src="img/表格/夜晴.png"</td>
            <td width="63">低温19℃</td>
            <td width="78">晴</td>
            <td width="81">微风</td>
          </tr>
          <tr class="day">
            <td>26日白天 </td>
            <td><img src="img/表格/白晴.png"</td>
            <td>高温33℃</td>
            <td>晴</td>
            <td>微风</td>
          </tr>
          <tr class="night">
            <td rowspan="2"><span>上海</span></td>
            <td>25日夜晚</td>
            <td><img src="img/表格/夜云.png"</td>
            <td>低温25℃</td>
            <td>多云</td>
            <td>微风</td>
          </tr>
          <tr class="day">
            <td>26日白天 </td>
            <td><img src="img/表格/白云.png"</td>
            <td>高温31℃</td>
            <td>多云</td>
            <td>东北风3~4级</td>
          </tr>
          <tr class="night">
            <td rowspan="2"><span>广州</span></td>
            <td>25日夜晚</td>
            <td><img src="img/表格/夜晴.png"</td>
            <td>低温25℃</td>
            <td>晴</td>
            <td>微风</td>
          </tr>
          <tr class="day">
            <td>26日白天 </td>
            <td><img src="img/表格/白晴.png"</td>
            <td>高温35℃</td>
            <td>晴</td>
            <td>微风</td>
          </tr>
          <tr class="night">
            <td rowspan="2"><span>西昌</span></td>
            <td>25日夜晚</td>
            <td><img src="img/表格/夜雨.png"</td>
            <td>低温19℃</td>
            <td>阵雨</td>
            <td>旋转风微风</td>
          </tr>
          <tr class="day">
            <td>26日白天 </td>
            <td><img src="img/表格/白晴.png"</td>
            <td>高温27℃</td>
            <td>多云</td>
            <td>旋转风微风</td>
          </tr>
        </tbody>
      </table>
    </div>
</body>
</html>

def _parse_table(self, tbl: CT_Tbl, parent: t.ProvidesStoryPart, label: str = "body", block: DocumentBlockObject = None) -> TableObject: """ 解析docx中的CT_Tbl表格对象,组织成通用结构的表格对象TableObject :param tbl: CT_Tbl对象 :param parent: 表格对象的父容器 :param self._tbl_idx: 表格在文档顺序中的索引(只计表格) :return: TableObject对象 """ # 表格码信息 if self._tbl_idx is not None: tbl_page_info = self._table_info.get(self._tbl_idx) else: tbl_page_info = None # 基于代理Table对象 解析数据 proxy_table = Table(tbl, parent) # 通用表格对象 tbl_obj = TableObject() tbl_obj.label = label # 标识眉、脚、主体 # if tbl_page_info and tbl_page_info.get('position'): # tbl_obj.position = tbl_page_info.get('position') # 真正的数索引 true_row_idx = -1 # 解析表格数据 for r_idx, row in enumerate(proxy_table.rows): # 当前列表 cur_row_cnt = [] r_cells = list(row.cells) for c_idx, cell in enumerate(r_cells): # 解析单元格 cell_obj = self._parse_cell(r_idx, c_idx, cell, proxy_table, label=label) if (cell.tables and r_idx < len(tbl.tr_lst) and c_idx < len(tbl.tr_lst[r_idx].tc_lst) and tbl.tr_lst[r_idx].tc_lst[c_idx].tbl_lst): for inner_tbl in tbl.tr_lst[r_idx].tc_lst[c_idx].tbl_lst: self._tbl_idx += 1 add_tbl_obj = self._parse_table(inner_tbl, self._origin_object) # 判断是否为空表格 if self.is_empty_table(add_tbl_obj): self._tbl_idx -= 1 continue add_tbl_obj.index = self._tbl_idx block.add_table(add_tbl_obj) self._elements_by_order.append(add_tbl_obj) # 当前单元格临时存入列表 cur_row_cnt.append(cell_obj) # if tbl_page_info: # index = r_idx * tbl_page_info.get("cols") + c_idx # if len(tbl_page_info.get('cell_positions')) > index and tbl_page_info.get('cell_positions')[index]: # cell_obj.position = tbl_page_info.get('cell_positions')[index] # 初始化单元格的合并范围 cell_obj.merged_ranges_2 = [None, None, None, None] # 处理单元格的横向合并 col_span = cell.grid_span if col_span > 1: # 有列合并 cell_obj.merged_ranges_2[1] = c_idx cell_obj.merged_ranges_2[3] = c_idx + col_span - 1 # 创建对象 row_obj = RowObject() # cur_row_cnt_bool = [True if c_obj.content else False for c_obj in cur_row_cnt] # if any(cur_row_cnt_bool): true_row_idx += 1 row_obj.row_index = true_row_idx row_obj.label = label # 获取对象的码 if tbl_page_info is not None: tbl_columns_with_pywin32 = tbl_page_info.get("cols") tgt_index = true_row_idx * tbl_columns_with_pywin32 try: for i in range(tgt_index, tgt_index + tbl_columns_with_pywin32): cur_row_page_id = str(tbl_page_info.get("cell_page_num")[i]) if cur_row_page_id != 'None': break # cur_autostring_id = str(tbl_page_info.get("cell_String_num")[tgt_index]) except IndexError as e: # logger.error(f"parse table_{tbl_idx} cell({r_idx}, {c_idx}) page num failed.") cur_row_page_id = "" row_obj.layout.page_id = cur_row_page_id # row_obj.layout.autostring_id = cur_autostring_id row_obj.cells.extend(cur_row_cnt) for c_obj in cur_row_cnt: c_obj.layout.parent_ref = row_obj # 单元格的码取当前码 c_obj.layout.page_id = row_obj.layout.page_id c_obj.row_index = row_obj.row_index for content_obj in c_obj.content: if isinstance(content_obj, TextObject): content_obj.layout.page_id = row_obj.layout.page_id elif isinstance(content_obj, (PictureObject, GraphicObject)): if not content_obj.layout.page_id: content_obj.layout.page_id = row_obj.layout.page_id if tbl_page_info is not None: cur_autostring_id = tbl_page_info.get("cell_String_num") # 单元格对象追加到 for c_obj in cur_row_cnt: if cur_autostring_id and any(x is not None for x in cur_autostring_id): cell_tbl_columns_with_pywin32 = tbl_page_info.get("cols") # 检查 row_obj.row_index, cell_tbl_columns_with_pywin32 和 c_obj.col_index 是否为空 # if not row_obj.row_index or not cell_tbl_columns_with_pywin32 or not c_obj.col_index: # continue cell_tgt_index = int(row_obj.row_index) * int(cell_tbl_columns_with_pywin32) + int( c_obj.col_index) if len(cur_autostring_id) <= cell_tgt_index: continue if cur_autostring_id[cell_tgt_index]: c_obj.auto_number = True if not c_obj.text: c_obj.text = str(cur_autostring_id[cell_tgt_index]) text_obj = TextObject() text_obj.text = str(cur_autostring_id[cell_tgt_index]) run_obj = RunObject() run_obj.text = str(cur_autostring_id[cell_tgt_index]) text_obj.runs.append(run_obj) c_obj.content.append(text_obj) else: rebuild_text = '' cur_auto_string_text_list = deepcopy(cur_autostring_id[cell_tgt_index]) for item in c_obj.content: if isinstance(item, TextObject) and item.text: if item.text == '\n': rebuild_text += item.text else: for cur_autostring in cur_auto_string_text_list: if item.text in cur_autostring: item.text = cur_autostring rebuild_text += item.text cur_auto_string_text_list.remove(cur_autostring) break else: rebuild_text += item.text c_obj.text = rebuild_text # 过滤掉空对象 # if self.is_empty_row(row_obj): # continue # 数据追加到表格 row_obj.layout.parent_ref = tbl_obj tbl_obj.rows.append(row_obj) # 表格对齐 self.table_row_align(tbl_obj) # 解析单元格的合并区域 self.parse_merge_region(proxy_table, tbl_obj, tbl) # 解析表格的边框 self.parse_tbl_borders(tbl, tbl_obj) # 解析表格的layout self.parse_tbl_layout(tbl_obj) # 解析表格的样式 style self.parse_tbl_style(proxy_table, tbl_obj) return tbl_obj 把表格解析部分也重新树立一下 包括参数说明和WORKFLOW
最新发布
10-29
<think>我们正在处理一个Word文档中的表格解析函数。该函数名为`_parse_table`,接受一个`CT_Tbl`对象(代表Word文档中的一个表格)和其他参数,返回一个通用的`TableObject`对象。 接下来,我们将详细解释该函数,包括参数、流程和关键步骤。 函数签名: def _parse_table(self, tbl: CT_Tbl, parent: t.ProvidesStoryPart, label: str = "body", block: DocumentBlockObject = None) -> TableObject: 参数说明: - tbl: 要解析的表格,为`CT_Tbl`对象(来自python-docx库的内部表示)。 - parent: 表格的父容器,通常是文档的一部分(如正文、眉、脚等)。 - label: 标识表格所在的位置,如"body"(正文)、"header"(眉)、"footer"(脚)。 - block: 文档块对象,用于存储解析后的元素(如嵌套表格)。 返回值:解析后的通用表格对象`TableObject`。 函数流程(WORKFLOW)如下: 1. **初始化阶段**: - 获取当前表格码信息(通过之前从COM接口获取的表格元数据)。 - 创建一个代理Table对象(`proxy_table`)来帮助解析。 - 初始化通用的表格对象`tbl_obj`,并设置其标签(label)。 2. **遍历表格**: - 使用`proxy_table.rows`获取表格的所有。 - 初始化一个变量`true_row_idx`来记录实际的索引(因为可能会跳过空)。 3. **遍历中的单元格**: - 对于每一,遍历其所有的单元格(`row.cells`)。 - 对每个单元格调用`_parse_cell`方法进解析,得到单元格对象`cell_obj`。 - 如果当前单元格内嵌套有表格(通过检查`cell.tables`和XML结构),则递归解析嵌套表格,并将解析得到的表格对象添加到文档块(`block`)中。 4. **处理单元格合并**: - 记录单元格的列合并(`grid_span`),设置合并范围(`merged_ranges_2`属性)。 5. **创建对象**: - 将当前解析得到的所有单元格对象存储到对象(`RowObject`)中。 - 设置对象的索引、标签和码信息(从之前获取的表格元数据中提取)。 - 将中所有单元格的码设置为对象的码(即同一中的单元格在同一)。 6. **处理自动编号**: - 如果表格元数据中提供了单元格的自动编号信息(`cell_String_num`),则将自动编号内容添加到单元格对象中。如果单元格原本有内容,则尝试将自动编号与原有内容匹配并替换;如果原本没有内容,则直接添加自动编号内容。 7. **添加表格**: - 将对象添加到表格对象(`tbl_obj`)的`rows`列表中。 8. **后处理**: - 表格对齐(`table_row_align`方法): 确保每的单元格数量一致,可能填充空单元格。 - 解析单元格的合并区域(`parse_merge_region`方法): 处理合并合并。 - 解析表格边框(`parse_tbl_borders`方法): 从原始表格对象中提取边框样式。 - 解析表格布局(`parse_tbl_layout`方法): 设置表格的布局属性(如宽度、对齐等)。 - 解析表格样式(`parse_tbl_style`方法): 应用表格样式。 9. 返回表格对象`tbl_obj`。 下面我们用伪代码和关键代码片段来展示整个流程: 注意:由于原函数较长,我们将重点展示流程框架和关键步骤。 伪代码: def _parse_table(...): 1. 初始化表格信息(码等) 2. 创建代理表格对象 3. 初始化返回的表格对象(tbl_obj) 4. 遍历每一(r_idx, row in enumerate(proxy_table.rows)): 初始化当前的单元格列表(cur_row_cnt) 遍历当前的每个单元格(c_idx, cell in enumerate(row.cells)): 解析单元格 -> cell_obj 检查单元格内是否有嵌套表格,如果有则递归解析 处理单元格的列合并(grid_span) 将单元格对象加入当前列表 创建对象(row_obj) 设置对象的属性(索引、码等) 将当前列表中的所有单元格加入对象 处理自动编号(如果存在) 将对象加入表格对象 5. 后处理(对齐、合并区域、边框、布局、样式) 6. 返回表格对象 关键代码片段说明: 1. 初始化表格码信息: if self._tbl_idx is not None: tbl_page_info = self._table_info.get(self._tbl_idx) else: tbl_page_info = None 2. 创建代理表格对象: proxy_table = Table(tbl, parent) 3. 初始化索引: true_row_idx = -1 4. 遍历和单元格: for r_idx, row in enumerate(proxy_table.rows): cur_row_cnt = [] r_cells = list(row.cells) for c_idx, cell in enumerate(r_cells): # 解析单元格 cell_obj = self._parse_cell(r_idx, c_idx, cell, proxy_table, label=label) # 检查嵌套表格并递归解析 if (cell.tables ...): # 条件较长,主要是检查嵌套表格 for inner_tbl in ...: self._tbl_idx += 1 add_tbl_obj = self._parse_table(inner_tbl, ...) # 添加到block block.add_table(add_tbl_obj) # 处理列合并 col_span = cell.grid_span if col_span > 1: cell_obj.merged_ranges_2[1] = c_idx cell_obj.merged_ranges_2[3] = c_idx + col_span - 1 cur_row_cnt.append(cell_obj) # 创建对象并设置属性 true_row_idx += 1 row_obj = RowObject() row_obj.row_index = true_row_idx row_obj.label = label # ... 设置码等 # 将单元格加入对象 row_obj.cells.extend(cur_row_cnt) # 处理自动编号(根据tbl_page_info中的cell_String_num) # 此处代码较长,主要是将自动编号内容与单元格原有内容进整合 # 将对象加入表格 tbl_obj.rows.append(row_obj) 5. 后处理: self.table_row_align(tbl_obj) # 对齐(补充空单元格使每单元格数一致) self.parse_merge_region(proxy_table, tbl_obj, tbl) # 解析合并区域(处理合并) self.parse_tbl_borders(tbl, tbl_obj) # 解析边框 self.parse_tbl_layout(tbl_obj) # 解析布局 self.parse_tbl_style(proxy_table, tbl_obj) # 解析样式 注意:在解析过程中,递归处理嵌套表格是关键点之一。每遇到一个嵌套表格,就递增表格索引(`self._tbl_idx`),然后递归调用`_parse_table`进解析,并将解析后的表格对象添加到文档块中。 此外,该函数还处理了单元格的自动编号(如果存在),这通常来自于Word表格中的自动编号字段。通过之前从COM接口获取的`cell_String_num`列表,将自动编号内容整合到单元格的内容中。 最后,我们绘制一个流程图(WORKFLOW)来更直观地展示整个解析过程: </think>### 表格解析详细说明 #### 方法签名 ```python def _parse_table( self, tbl: CT_Tbl, parent: t.ProvidesStoryPart, label: str = "body", block: DocumentBlockObject = None ) -> TableObject: ``` #### 参数说明 1. **`tbl: CT_Tbl`** - Word文档中的表格对象(来自`python-docx`库) - 包含表格结构、单元格内容和表格样式信息 2. **`parent: t.ProvidesStoryPart`** - 表格的父容器对象(文档、眉或脚) - 用于确定表格在文档中的位置和上下文 3. **`label: str`** - 标识表格位置:`"body"`(正文)、`"header"`(眉)、`"footer"`(脚) - 默认值为`"body"` 4. **`block: DocumentBlockObject`** - 文档块对象,用于存储解析结果 - 可选参数,当处理嵌套表格时使用 #### 返回值 - `TableObject`:结构化表格对象,包含、单元格及关联信息 --- ### 表格解析WORKFLOW ```mermaid graph TD A[开始解析表格] --> B[获取表格元数据] B --> C[创建代理表格对象] C --> D[初始化表格对象] D --> E[遍历表格] E --> F[遍历中的单元格] F --> G{单元格是否嵌套表格?} G -->|是| H[递归解析嵌套表格] G -->|否| I[解析单元格内容] I --> J[处理单元格合并] J --> K[添加单元格到] H --> K K --> L[创建对象] L --> M[设置属性] M --> N[添加表格] N --> O{还有更多?} O -->|是| E O -->|否| P[表格后处理] P --> Q[返回表格对象] ``` #### 详细解析流程 ##### 1. 初始化阶段 ```python # 获取表格元数据(码、位置等) if self._tbl_idx is not None: tbl_page_info = self._table_info.get(self._tbl_idx) else: tbl_page_info = None # 创建代理表格对象(python-docx的Table实例) proxy_table = Table(tbl, parent) # 初始化通用表格对象 tbl_obj = TableObject() tbl_obj.label = label # 设置位置标签 true_row_idx = -1 # 实际索引计数器 ``` ##### 2. 遍历处理 ```python for r_idx, row in enumerate(proxy_table.rows): cur_row_cnt = [] # 当前的单元格列表 row_cells = list(row.cells) # 获取中所有单元格 # 单元格遍历 for c_idx, cell in enumerate(row_cells): # 解析单元格内容 cell_obj = self._parse_cell(r_idx, c_idx, cell, proxy_table, label=label) # 处理嵌套表格(递归调用) if self._has_nested_table(cell, tbl, r_idx, c_idx): for inner_tbl in self._get_nested_tables(tbl, r_idx, c_idx): self._tbl_idx += 1 # 表格索引递增 nested_table = self._parse_table(inner_tbl, self._origin_object) # 跳过空表格 if not self.is_empty_table(nested_table): block.add_table(nested_table) self._elements_by_order.append(nested_table) # 添加到当前 cur_row_cnt.append(cell_obj) # 处理单元格合并(列合并) self._handle_cell_span(cell, cell_obj, c_idx) # 创建对象 if self._should_add_row(cur_row_cnt): true_row_idx += 1 row_obj = RowObject() row_obj.row_index = true_row_idx row_obj.label = label # 设置属性 self._set_row_properties(row_obj, tbl_page_info, true_row_idx) # 添加单元格到 row_obj.cells.extend(cur_row_cnt) # 设置单元格关联属性 for cell_obj in row_obj.cells: cell_obj.layout.parent_ref = row_obj cell_obj.layout.page_id = row_obj.layout.page_id cell_obj.row_index = row_obj.row_index # 设置内容对象关联 for content in cell_obj.content: if isinstance(content, (TextObject, PictureObject, GraphicObject)): content.layout.page_id = row_obj.layout.page_id # 添加到表格 row_obj.layout.parent_ref = tbl_obj tbl_obj.rows.append(row_obj) ``` ##### 3. 处理自动编号 ```python # 处理单元格自动编号(如列表编号) if tbl_page_info and tbl_page_info.get("cell_String_num"): cur_autostring_id = tbl_page_info.get("cell_String_num") cell_tbl_columns = tbl_page_info.get("cols") for row_obj in tbl_obj.rows: for cell_obj in row_obj.cells: if cell_tbl_columns and cell_obj.col_index is not None: cell_tgt_index = row_obj.row_index * cell_tbl_columns + cell_obj.col_index if cell_tgt_index < len(cur_autostring_id) and cur_autostring_id[cell_tgt_index]: self._apply_auto_number(cell_obj, cur_autostring_id[cell_tgt_index]) ``` ##### 4. 后处理阶段 ```python # 表格对齐(确保每单元格数量一致) self.table_row_align(tbl_obj) # 解析合并区域(处理合并) self.parse_merge_region(proxy_table, tbl_obj, tbl) # 解析表格边框 self.parse_tbl_borders(tbl, tbl_obj) # 解析表格布局 self.parse_tbl_layout(tbl_obj) # 解析表格样式 self.parse_tbl_style(proxy_table, tbl_obj) return tbl_obj ``` --- ### 关键功能实现 #### 1. 嵌套表格处理 ```python def _has_nested_table(self, cell, tbl, r_idx, c_idx): """检查单元格是否包含嵌套表格""" return ( cell.tables and r_idx < len(tbl.tr_lst) and c_idx < len(tbl.tr_lst[r_idx].tc_lst) and tbl.tr_lst[r_idx].tc_lst[c_idx].tbl_lst ) def _get_nested_tables(self, tbl, r_idx, c_idx): """获取嵌套表格列表""" return tbl.tr_lst[r_idx].tc_lst[c_idx].tbl_lst ``` #### 2. 单元格合并处理 ```python def _handle_cell_span(self, cell, cell_obj, c_idx): """处理单元格合并""" col_span = cell.grid_span # 列合并处理(横向合并) if col_span > 1: cell_obj.merged_ranges_2 = [None, c_idx, None, c_idx + col_span - 1] # 合并处理(在parse_merge_region中实现) # 需要后续处理,因为需要表格完整数据 ``` #### 3. 自动编号处理 ```python def _apply_auto_number(self, cell_obj, auto_string): """应用自动编号到单元格""" cell_obj.auto_number = True if not cell_obj.text: # 单元格无内容 text_obj = TextObject(text=str(auto_string)) run_obj = RunObject(text=str(auto_string)) text_obj.runs.append(run_obj) cell_obj.content.append(text_obj) cell_obj.text = str(auto_string) else: # 单元格已有内容 # 尝试匹配原有内容中的编号 rebuild_text = '' auto_string_list = list(filter(None, auto_string.split('\n'))) for content in cell_obj.content: if isinstance(content, TextObject): if content.text == '\n': rebuild_text += content.text else: found = False for auto_str in auto_string_list: if content.text in auto_str: content.text = auto_str rebuild_text += content.text auto_string_list.remove(auto_str) found = True break if not found: rebuild_text += content.text cell_obj.text = rebuild_text ``` #### 4. 表格对齐 ```python def table_row_align(self, table_obj): """确保每单元格数量一致(处理合并)""" max_cols = max(len(row.cells) for row in table_obj.rows) for row in table_obj.rows: while len(row.cells) < max_cols: empty_cell = CellObject() empty_cell.content = [TextObject(text="")] row.cells.append(empty_cell) ``` --- ### 补充工具方法 #### 1.表格检测 ```python def is_empty_table(self, table_obj): """检测表格是否为空""" for row in table_obj.rows: for cell in row.cells: if cell.text.strip() or any(isinstance(c, (PictureObject, GraphicObject)) for c in cell.content): return False return True ``` #### 2.检测 ```python def is_empty_row(self, row_obj): """检测是否为空""" for cell in row_obj.cells: if cell.text.strip() or any(isinstance(c, (PictureObject, GraphicObject)) for c in cell.content): return False return True ``` #### 3. 合并区域解析 ```python def parse_merge_region(self, proxy_table, table_obj, tbl_element): """解析单元格合并区域(合并)""" # 实现细节依赖于具体文档结构 # 需要分析<tr>中的<vMerge>等属性 # 伪代码: for r_idx, row in enumerate(proxy_table.rows): for c_idx, cell in enumerate(row.cells): if cell._tc.vMerge == "restart": # 查找合并结束位置 ... elif cell._tc.vMerge == "continue": # 标记为上一个单元格的合并部分 ... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值