from flask import Flask, request, jsonify, Response,send_file,abort
import os
import json
import re
from datetime import datetime
app = Flask(__name__)
# 配置上传文件夹
UPLOAD_FOLDER = 'uploads'
if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
from pptx import Presentation
from pptx.util import Inches,Pt
from pptx.enum.text import PP_ALIGN,PP_PARAGRAPH_ALIGNMENT
from pptx.enum.dml import MSO_THEME_COLOR
from lxml import etree
import uuid
def generate_random_key():
"""生成一个 UUID 密钥"""
return str(uuid.uuid4())
# 获取当前时间
def getCurrentDate():
# 获取当前日期和时间
current_time = datetime.now()
# 格式化输出
formatted_time = current_time.strftime("%Y-%m-%d")
return formatted_time
# 导出PPT
def excelToPPT(data):
# 创建一个新的PPT
prs = Presentation()
slide_width = prs.slide_width # 返回EMU单位
slide_height = prs.slide_height
font_list = ["latin", "ea", "cs"]
# 设置主题字体
for item in data:
order = item['order']
title_name = item['title']
patentNo = item.get('appNo','') or item.get('publicNo','')
appDate = item.get('appDate','')
publicDate = item.get('publicDate','')
appPerson = item.get('appPerson','')
files = item.get('files',[])
technical_problem = item.get('technical_problem','')
technical_means = item.get('technical_means','')
technical_efficacy = item.get('technical_efficacy','')
application_field_classification = item.get('application_field_classification','')
# 添加一个幻灯片
slide_layout = prs.slide_layouts[5] # 使用一个空白布局
slide = prs.slides.add_slide(slide_layout)
# 添加标题
title = slide.shapes.title
title.height = Pt(40)
title.width = slide_width
title.text = f"{order}、{title_name}-{patentNo}"
# 设置标题字体
title_frame = title.text_frame
title_paragraph = title_frame.paragraphs[0]
title_paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.LEFT
title_run = title_paragraph.runs[0]
# 设置标题字体属性
title_run.font.name = '微软雅黑'
title_run.font.size = Pt(20)
title_run.font.bold = True
r_element = title_run._r
rPr = r_element.find('.//a:rPr', namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
if rPr is not None:
for tag in font_list:
# 获取或创建 ea 节点
node = rPr.find(f'.//a:{tag}', namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
if node is None:
# 如果 ea 节点不存在,创建一个新的 ea 节点
node = etree.Element('{http://schemas.openxmlformats.org/drawingml/2006/main}'+tag)
rPr.append(node)
node.set('typeface', '微软雅黑') # 你可以替换为你想要的字体名称
# 更新 _r 属性
title_run._r = r_element
# 添加图片 (替换为实际图片路径)
if len(files)>0:
left = Inches(0.5)
top = Inches(1.3)
width = Inches(4.5)
height = Inches(3)
num = 1
for image in files:
if num == 1:
slide.shapes.add_picture(image, left, top, width, height)
else:
left_second_image = Inches(5 * (num - 1))
slide.shapes.add_picture(image, left_second_image, top, width, height)
num += 1
# 添加文本框
left_text = Inches(0.5)
top_text = Inches(4.5)
width_text = slide_width - Inches(0.5).emu
height_text = Inches(2)
text_box = slide.shapes.add_textbox(left_text, top_text, width_text, height_text)
text_frame = text_box.text_frame
# 关键配置:启用自动换行
text_frame.word_wrap = True
text_frame.auto_size = None
paragraph_list = [
{
'field':'申请人',
'content':appPerson
},
{
'field':'申请日',
'content':appDate
},
{
'field':'公开公告日',
'content':publicDate
},
{
'field':'解决问题',
'content':technical_problem
},
{
'field':'技术手段',
'content':technical_means
},
{
'field':'技术效果',
'content':technical_efficacy
},
{
'field':'应用领域',
'content':application_field_classification.replace('|','、')
}
]
for item in paragraph_list:
paragraph = text_frame.add_paragraph()
paragraph.text = f"{item['field']}:"
run = paragraph.runs[0]
run.font.bold = True
run = paragraph.add_run()
run.text = item['content']
for run_item in paragraph.runs:
run_item.font.size = Pt(15)
run_item.font.name = '微软雅黑'
r_element = run_item._r
rPr = r_element.find('.//a:rPr', namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
if rPr is not None:
for tag in font_list:
# 获取或创建 ea 节点
node = rPr.find(f'.//a:{tag}', namespaces={'a': 'http://schemas.openxmlformats.org/drawingml/2006/main'})
if node is None:
# 如果 ea 节点不存在,创建一个新的 ea 节点
node = etree.Element('{http://schemas.openxmlformats.org/drawingml/2006/main}'+tag)
rPr.append(node)
node.set('typeface', '微软雅黑') # 你可以替换为你想要的字体名称
# 更新 _r 属性
run_item._r = r_element
paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.LEFT
# 保存PPT
uuid = generate_random_key()
formatted_time = getCurrentDate()
file_name = f"result/{formatted_time}_{uuid}.pptx"
prs.save(file_name)
return file_name
# 读取Excel文件
from openpyxl import load_workbook
def read_excel_file(file_path):
try:
# 读取Excel文件
# df = pd.read_excel(file_path)
wb = load_workbook(file_path)
sheet = wb[wb.sheetnames[0]]
df = []
for row in sheet.iter_rows(values_only=True):
df.append(row)
# 获取所有图片
images = {}
for img in sheet._images:
# 图片位置信息
anchor = img.anchor
# 图片数据
if hasattr(img, '_data'):
img_data = img._data() if callable(img._data) else img._data
elif hasattr(img, 'image'):
from io import BytesIO
img.image.save(BytesIO(), format='png')
img_data = BytesIO().getvalue()
else:
continue
images[(anchor._from.row, anchor._from.col)] = img_data
# 返回数据框
return df,images
except Exception as e:
print(f"读取Excel文件时出错: {e}")
return None
# 格式化excel数据
def getExcelData(excel_data,field_obj={}):
fieldList = excel_data[0]
data = []
for index,item in enumerate(excel_data):
if index == 0:
continue
obj = {}
for fieldIndex,field in enumerate(fieldList):
if field in field_obj:
obj[field_obj[field]] = item[fieldIndex]
# else:
# obj[field] = item[fieldIndex]
data.append(obj)
return data
# 读取excel文件
def read_excel(file_path,current_filename,field_obj):
#1.读取文件拿到信息
excel_data,images = read_excel_file(file_path)
data = getExcelData(excel_data,field_obj)
uuid = generate_random_key()
# 打印数据
for i, row in enumerate(data):
# 检查该行是否有图片
for (r, c), img_data in images.items():
if r == i+1:
# 可以保存图片
with open(f'image/{uuid}_row_{i+1}_col_{c+1}.png', 'wb') as f:
f.write(img_data)
if 'files' not in row:
row['files'] = []
row['files'].append(f'image/{uuid}_row_{i+1}_col_{c+1}.png')
return data
# 根据excel导出PPT接口
@app.route(f'/api/exportPPT', methods=['POST'])
def exportPPT():
# 检查请求中是否有文件
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
filename = ''
# 检查是否选择了文件
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
if file:
current_filename = file.filename
# filename = f'uploads\{current_filename}'
# if os.path.exists(filename):
# pass
# else:
# 安全地获取文件名
filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
# 确保不会覆盖现有文件
counter = 1
while os.path.exists(filename):
name, ext = os.path.splitext(file.filename)
filename = os.path.join(app.config['UPLOAD_FOLDER'], f"{name}_{counter}{ext}")
counter += 1
# 保存文件
file.save(filename)
# 文件存在时直接处理
file_path = ''
# 1. 获取文件内容
field_obj = {
'公开(公告)号':'publicNo',
'摘要附图':'image',
'序号':'order',
'标题':'title',
'申请号':'appNo',
'申请日':'appDate',
'当前申请(专利权)人':'appPerson',
'公开(公告)日':'publicDate',
'技术手段':'technical_means',
'技术功效':'technical_efficacy',
'应用领域分类':'application_field_classification',
'技术问题':'technical_problem',
}
excel_data = read_excel(filename,current_filename,field_obj)
if excel_data:
# 2. 生成并导出PPT
file_path = excelToPPT(excel_data)
else:
return jsonify({'error': 'No file part'}), 400
return jsonify(file_path) ,200
#下载文件
@app.route(f'/api/download',methods=['GET'])
async def download():
get_params = request.args
filename = get_params.get('filePath')
file_path = os.path.join(os.getcwd(), '', filename)
if not os.path.exists(file_path):
abort(404) # 返回 404 错误
try:
# 返回文件给用户下载
return send_file(file_path, as_attachment=True)
except Exception as e:
# 处理可能的异常(例如文件权限问题)
return str(e), 500
# 根据excel导出xmind接口
@app.route(f'/api/exportXmind', methods=['POST'])
def exportXmind():
# 检查请求中是否有文件
if 'file' not in request.files:
return jsonify({'error': 'No file part'}), 400
file = request.files['file']
filename = ''
# 检查是否选择了文件
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
if file:
current_filename = file.filename
# filename = f'uploads\{current_filename}'
# if os.path.exists(filename):
# pass
# else:
# 安全地获取文件名
filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
# 确保不会覆盖现有文件
counter = 1
while os.path.exists(filename):
name, ext = os.path.splitext(file.filename)
filename = os.path.join(app.config['UPLOAD_FOLDER'], f"{name}_{counter}{ext}")
counter += 1
# 保存文件
file.save(filename)
# 文件存在时直接处理
file_path = ''
# 分类节点
classify_nodes = [
{
'name':'AI智能化',
'path':'AI智能化',
'parent_name':'',
'order':1
},
{
'name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_name':'AI智能化',
'parent_order':1,
'order':2
},
{
'name':'功能控制',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)\功能控制',
'parent_name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_order':2,
'order':3
},
{
'name':'语音控制',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)\语音控制',
'parent_name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_order':2,
'order':4
},
{
'name':'手势识别',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)\手势识别',
'parent_name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_order':2,
'order':5
},
{
'name':'佩戴检测',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)\佩戴检测',
'parent_name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_order':2,
'order':6
},
{
'name':'其它',
'path':'AI智能化\多模态交互、传感器处理(例如佩戴检测、语音识别)\其它',
'parent_name':'多模态交互、传感器处理(例如佩戴检测、语音识别)',
'parent_order':2,
'order':7
},
{
'name':'音频信号处理',
'path':'AI智能化\音频信号处理',
'parent_name':'AI智能化',
'parent_order':1,
'order':8
},
{
'name':'音质',
'path':'AI智能化\音频信号处理\音质',
'parent_name':'音频信号处理',
'parent_order':8,
'order':9
},
{
'name':'空间音频',
'path':'AI智能化\音频信号处理\空间音频',
'parent_name':'音频信号处理',
'parent_order':8,
'order':10
},
{
'name':'降噪',
'path':'AI智能化\音频信号处理\降噪',
'parent_name':'音频信号处理',
'parent_order':8,
'order':11
},
{
'name':'高清编码',
'path':'AI智能化\音频信号处理\高清编码',
'parent_name':'音频信号处理',
'parent_order':8,
'order':12
},
{
'name':'其它',
'path':'AI智能化\音频信号处理\其它',
'parent_name':'音频信号处理',
'parent_order':8,
'order':13
},
{
'name':'大模型简化',
'path':'AI智能化\大模型简化',
'parent_name':'AI智能化',
'parent_order':1,
'order':14
},
{
'name':'智能化应用',
'path':'AI智能化\智能化应用',
'parent_name':'AI智能化',
'parent_order':1,
'order':15
},
{
'name':'翻译',
'path':'AI智能化\智能化应用\翻译',
'parent_name':'智能化应用',
'parent_order':15,
'order':16
},
{
'name':'会议纪要',
'path':'AI智能化\智能化应用\会议纪要',
'parent_name':'智能化应用',
'parent_order':15,
'order':17
},
{
'name':'其它',
'path':'AI智能化\智能化应用\其它',
'parent_name':'智能化应用',
'parent_order':15,
'order':18
},
{
'name':'运动/健康信号处理',
'path':'运动/健康信号处理',
'parent_name':'',
'order':19
},
{
'name':'传感器元件',
'path':'运动/健康信号处理\传感器元件',
'parent_name':'运动/健康信号处理',
'parent_order':19,
'order':20
},
{
'name':'健康状态识别与分析',
'path':'运动/健康信号处理\健康状态识别与分析',
'parent_name':'运动/健康信号处理',
'parent_order':19,
'order':21
},
{
'name':'无线技术',
'path':'无线技术',
'parent_name':'',
'order':22
},
{
'name':'蓝牙/WiFi协议、连接',
'path':'无线技术\蓝牙/WiFi协议、连接',
'parent_name':'无线技术',
'parent_order':22,
'order':23
},
{
'name':'低延迟',
'path':'无线技术\蓝牙/WiFi协议、连接\低延迟',
'parent_name':'蓝牙/WiFi协议、连接',
'parent_order':23,
'order':24
},
{
'name':'其它',
'path':'无线技术\蓝牙/WiFi协议、连接\其它',
'parent_name':'蓝牙/WiFi协议、连接',
'parent_order':23,
'order':25
},
{
'name':'信号传输质量',
'path':'无线技术\信号传输质量',
'parent_name':'无线技术',
'parent_order':22,
'order':26
},
{
'name':'高可靠性',
'path':'无线技术\信号传输质量\高可靠性',
'parent_name':'信号传输质量',
'parent_order':26,
'order':27
},
{
'name':'其它',
'path':'无线技术\信号传输质量\其它',
'parent_name':'信号传输质量',
'parent_order':26,
'order':28
},
{
'name':'天线',
'path':'无线技术\天线',
'parent_name':'无线技术',
'parent_order':22,
'order':29
},
{
'name':'结构/材料/工艺',
'path':'结构/材料/工艺',
'parent_name':'',
'order':30
},
{
'name':'MIC/扬声器',
'path':'结构/材料/工艺\MIC/扬声器',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':31
},
{
'name':'舒适度',
'path':'结构/材料/工艺\舒适度',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':32
},
{
'name':'封装',
'path':'结构/材料/工艺\封装',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':33
},
{
'name':'电池',
'path':'结构/材料/工艺\电池',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':34
},
{
'name':'可调节结构/可拆卸结构/气囊结构',
'path':'结构/材料/工艺\可调节结构/可拆卸结构/气囊结构',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':35
},
{
'name':'传感器件与产品耦合的材料/结构',
'path':'结构/材料/工艺\传感器件与产品耦合的材料/结构',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':36
},
{
'name':'耳机特殊形态',
'path':'结构/材料/工艺\耳机特殊形态',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':37
},
{
'name':'其它',
'path':'结构/材料/工艺\其它',
'parent_name':'结构/材料/工艺',
'parent_order':30,
'order':38
},
{
'name':'其它',
'path':'其它',
'parent_name':'',
'order':39
}
]
# 1. 获取文件内容
field_obj = {
'公开(公告)号':'publicNo',
'摘要附图':'image',
'序号':'order',
'标题':'title',
'申请号':'appNo',
'申请日':'appDate',
'当前申请(专利权)人':'appPerson',
'公开(公告)日':'publicDate',
'分类':'classify',
'法律状态/事件':'status',
'工作空间注释':'annotation'
}
excel_data = read_excel(filename,current_filename,field_obj)
if excel_data:
# 2. 获取待导出的数据结构
exportXmindData = getExportXmindData(excel_data,classify_nodes)
# 3. 生成并导出xmind
file_path = excelToXmind(exportXmindData)
else:
return jsonify({'error': 'No file part'}), 400
return jsonify(file_path) ,200
# 获取待导出的数据结构
def getExportXmindData(excel_data,classify_nodes):
for item in excel_data:
if 'classify' in item and item['classify']:
item['classify_list'] = item['classify'].split('>')
# 将专利添加到分类节点中去
for node_item in classify_nodes:
path = node_item['path']
for item in excel_data:
if 'classify_list' in item and item['classify_list']:
classify_list = item['classify_list']
if path in classify_list:
if 'patents' not in node_item:
node_item['patents'] = []
node_item['patents'].append(item)
node_dict = {node['order']: node for node in classify_nodes}
tree = []
# 生成树级结构
for node in classify_nodes:
if node['parent_name'] == '':
# 如果没有父节点,说明是根节点
tree.append(node)
else:
# 否则,找到父节点并添加当前节点为子节点
parent = node_dict.get(node['parent_order'])
if parent:
if 'children' not in parent:
parent['children'] = []
parent['children'].append(node)
return tree
import shutil
# 复制模板文件
def copy_file_with_relative_path(relative_source_path, destination_path):
try:
# 获取当前工作目录
current_dir = os.getcwd()
# 构建完整的源文件路径
full_source_path = os.path.join(current_dir, relative_source_path)
# 检查源文件是否存在
if not os.path.exists(full_source_path):
raise FileNotFoundError(f"源文件不存在:{full_source_path}")
# 使用 shutil.copy2 复制文件,同时保留元数据
shutil.copy2(full_source_path, destination_path)
print(f"文件已成功复制到:{destination_path}")
except Exception as e:
print(f"复制文件时发生错误:{e}")
# 导出xmind
def excelToXmind(tree):
# 1. 创建空白xmind文件
uuid = generate_random_key()
formatted_time = getCurrentDate()
file_name = f"result/{formatted_time}_{uuid}.xmind"
create_xmind_with_images(file_name,tree)
return file_name
import os
import zipfile
import xml.etree.ElementTree as ET
from xml.dom import minidom
def create_xmind_with_images(output_file,data):
"""创建包含三级节点和图片的 XMind 文件"""
# 临时工作目录
temp_dir = "xmind_temp"
# 清理并创建目录结构
if os.path.exists(temp_dir):
shutil.rmtree(temp_dir)
os.makedirs(os.path.join(temp_dir, "content"))
os.makedirs(os.path.join(temp_dir, "META-INF"))
os.makedirs(os.path.join(temp_dir, "resources"))
os.makedirs(os.path.join(temp_dir, "Thumbnails"))
create_metadata_json(temp_dir)
# 1. 创建 content.xml 文件
images_list = create_content_xml(temp_dir,data)
# 2. 创建 manifest.xml 文件
create_manifest_xml(temp_dir,images_list)
# 3. 添加示例图片到 resources 目录 (实际使用中替换为你的图片)
create_sample_images(temp_dir,images_list)
# 4. 打包成 XMind 文件
with zipfile.ZipFile(output_file, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, _, files in os.walk(temp_dir):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, temp_dir)
zipf.write(file_path, arcname)
# 5. 清理临时文件
shutil.rmtree(temp_dir)
print(f"XMind 文件已创建: {output_file}")
return output_file
def create_metadata_json(temp_dir):
"""创建 XMind 2022 的 metadata.json"""
metadata_content = '''{
"activeSheetId": "sheet1",
"creator": {
"name": "XMind Python Generator",
"version": "1.0"
},
"fileStructure": {
"markerIds": [],
"numberingFormat": null,
"theme": "Default",
"version": "2.0"
},
"modifiedBy": "XMind Python Generator"
}'''
# 写入文件
metadata_path = os.path.join(temp_dir, "metadata.json")
with open(metadata_path, 'w', encoding='utf-8') as f:
f.write(metadata_content)
def add_topic_recursive(parent_element, node_data, ns,num,images_list):
"""
递归添加主题节点
参数:
parent_element: 父XML元素
node_data: 当前节点数据
ns: XML命名空间
"""
node_name = ''
classify_name = node_data.get('name','')
if not classify_name:#不是分类节点,是专利
patentNo = node_data.get('appNo','') or node_data.get('publicNo','')
title = node_data.get('title','')
status = node_data.get('status','')
annotation = node_data.get('annotation','')
node_name = node_name + patentNo
if title:
node_name = node_name + f'({title})'
node_name = node_name + status + '\n'
node_name = node_name + annotation
else:
node_name = classify_name
# 创建当前主题节点
topic = ET.SubElement(parent_element, "topic", id=f"topic{num}_{generate_random_key()}")
ET.SubElement(topic, "title").text = node_name
# 添加图片(如果存在)
if 'files' in node_data:
for file in node_data['files']:
file_index = file.rfind('/')
file_name = file[file_index+1:]
images_list.append(file_name)
image_elem = ET.SubElement(topic, "image", src=f"resources/{file_name}", align="center")
image_elem.set("width", "200")
image_elem.set("height", "150")
break
# 如果有子节点,递归添加
if "children" in node_data and node_data["children"]:
num += 1
children_container = ET.SubElement(topic, "children")
topics_container = ET.SubElement(children_container, "topics", type="attached")
for child in node_data["children"]:
add_topic_recursive(topics_container, child, ns,num,images_list)
# 如果有子节点,递归添加
if "patents" in node_data and node_data["patents"]:
num += 1
children_container = ET.SubElement(topic, "children")
topics_container = ET.SubElement(children_container, "topics", type="attached")
for child in node_data["patents"]:
add_topic_recursive(topics_container, child, ns,num,images_list)
def create_content_xml(temp_dir,data):
"""创建 content.xml 文件"""
# XML 命名空间
ns = "urn:xmind:xmap:xmlns:content:2.0"
# 创建根元素
xmap_content = ET.Element("xmap-content", xmlns=ns, version="2.0")
# 创建工作表
sheet = ET.SubElement(xmap_content, "sheet", id="sheet1")
# 创建主题
topic = ET.SubElement(sheet, "topic", id="root", timestamp="0",structure="org.xmind.ui.logic.right")
ET.SubElement(topic, "title").text = "**厂商**品类的专利布局"
structure = ET.SubElement(topic, "structure")
structure.set("type", "str")
structure.text = "org.xmind.ui.logic.right"
# 添加子节点容器
children_container = ET.SubElement(topic, "children")
topics_container = ET.SubElement(children_container, "topics", type="attached")
images_list = []
# 递归添加子节点
for child in data:
add_topic_recursive(topics_container, child, ns,1,images_list)
# 美化XML输出
xml_str = ET.tostring(xmap_content, encoding='utf-8')
pretty_xml = minidom.parseString(xml_str).toprettyxml(indent=" ")
pretty_xml = pretty_xml.replace('', '')
# 写入文件
content_path = os.path.join(temp_dir, "content.xml")
with open(content_path, 'w', encoding='utf-8') as f:
f.write(pretty_xml)
return images_list
def create_topic(parent, title, topic_id):
"""创建主题节点"""
topic = ET.SubElement(parent, "topic", id=topic_id)
ET.SubElement(topic, "title").text = title
return topic
def create_manifest_xml(temp_dir,images_list):
"""创建 manifest.xml 文件"""
str = ''
if images_list:
for file in images_list:
str = str + f'' + '\n'
manifest_content = f'''
{str}
'''
manifest_path = os.path.join(temp_dir, "META-INF", "manifest.xml")
with open(manifest_path, 'w', encoding='utf-8') as f:
f.write(manifest_content)
return True
def create_sample_images(temp_dir,images_list):
"""创建示例图片(实际使用中应替换为你的图片)"""
# 创建两个示例图片(实际项目中应使用真实图片)
resources_dir = os.path.join(temp_dir, "resources")
if images_list:
for file in images_list:
shutil.copy(f"image/{file}", os.path.join(resources_dir, file))
return True
from xmindparser import xmind_to_xml
def etxe1():
xml = xmind_to_xml('result/2025-06-26_2906a7b1-baf4-4b09-b668-b80c3a8264cb.xmind')
print(xml)
if __name__ == '__main__':
# etxe1()
app.run(debug=True, host='0.0.0.0', port=2500)