feat(workspace): xlsx在线查看/编辑接入(2026-09-18用户要求)
- office_read.dspy: 按扩展名分流——xlsx/xlsm调univer-office的xlsx-to-workbookdata 返回workbookData;docx原链路不变(顺带f-string改拼接合规) - office_save.dspy: workbookData/documentData双字段分流,xlsx调workbook-data-to-xlsx回写 - workspace_view/open.dspy: office_exts扩为['.docx','.xlsx','.xlsm'], xlsx与docx同享在线查看(mode=view只读)+在线编辑+下载按钮 - 配套: univer-office仓11d83bc(IWorkbookData双向转换器+sheets插件+44断言往返自测)
This commit is contained in:
parent
0438a9c4b5
commit
964f475067
@ -39,22 +39,37 @@ if not real_full.startswith(real_ws + os.sep):
|
||||
if not os.path.isfile(full_path):
|
||||
return {"error": "文件不存在", "markdown": ""}
|
||||
|
||||
# 读 docx bytes
|
||||
with open(full_path, 'rb') as f:
|
||||
docx_bytes = f.read()
|
||||
# 按扩展名分流:xlsx → IWorkbookData(表格),其余(docx)→ IDocumentData(文档)
|
||||
# (2026-09-18 xlsx 在线查看/编辑接入)
|
||||
_is_sheet = file_id.lower().endswith(('.xlsx', '.xlsm'))
|
||||
|
||||
# 调 univer-office 转 IDocumentData(格式保真,跳过 markdown)
|
||||
# 读文件 bytes
|
||||
with open(full_path, 'rb') as f:
|
||||
file_bytes = f.read()
|
||||
|
||||
# 调 univer-office 转换(格式保真,跳过 markdown)
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=60)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/docx-to-docdata',
|
||||
data=docx_bytes,
|
||||
headers={'Content-Type': 'application/octet-stream'},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return {"error": f"转换失败 HTTP {resp.status}", "documentData": None}
|
||||
doc_data = await resp.json()
|
||||
return {"documentData": doc_data}
|
||||
if _is_sheet:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/xlsx-to-workbookdata',
|
||||
data=file_bytes,
|
||||
headers={'Content-Type': 'application/octet-stream'},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return {"error": "转换失败 HTTP " + str(resp.status), "workbookData": None}
|
||||
workbook_data = await resp.json()
|
||||
return {"workbookData": workbook_data}
|
||||
else:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/docx-to-docdata',
|
||||
data=file_bytes,
|
||||
headers={'Content-Type': 'application/octet-stream'},
|
||||
) as resp:
|
||||
if resp.status != 200:
|
||||
return {"error": "转换失败 HTTP " + str(resp.status), "documentData": None}
|
||||
doc_data = await resp.json()
|
||||
return {"documentData": doc_data}
|
||||
except Exception as e:
|
||||
return {"error": str(e), "documentData": None}
|
||||
return {"error": str(e), "documentData": None, "workbookData": None}
|
||||
|
||||
@ -5,6 +5,8 @@ import aiohttp
|
||||
|
||||
file_id = (params_kw or {}).get('file', '').strip()
|
||||
docdata_str = (params_kw or {}).get('documentData', '') or ''
|
||||
# xlsx 保存:前端传 workbookData 字段(2026-09-18 xlsx 在线编辑接入)
|
||||
workbookdata_str = (params_kw or {}).get('workbookData', '') or ''
|
||||
|
||||
uid = await get_user()
|
||||
if not uid:
|
||||
@ -30,13 +32,16 @@ async with DBPools().sqlorContext(dbname) as sor:
|
||||
if not file_id or not space_dir:
|
||||
return {"success": False, "error": "未指定文件或无工作空间"}
|
||||
|
||||
if not docdata_str:
|
||||
# 按扩展名分流:xlsx 用 workbookData 字段,docx 用 documentData 字段
|
||||
_is_sheet = file_id.lower().endswith(('.xlsx', '.xlsm'))
|
||||
_payload_str = workbookdata_str if _is_sheet else docdata_str
|
||||
if not _payload_str:
|
||||
return {"success": False, "error": "缺少文档数据"}
|
||||
|
||||
try:
|
||||
documentData = _json.loads(docdata_str)
|
||||
_payload = _json.loads(_payload_str)
|
||||
except Exception as e:
|
||||
return {"success": False, "error": f"文档数据解析失败: {e}"}
|
||||
return {"success": False, "error": "文档数据解析失败: " + str(e)}
|
||||
|
||||
full_path = resolve_workspace_path(project_dir, space_dir, file_id)
|
||||
|
||||
@ -52,24 +57,28 @@ if not os.path.isfile(full_path):
|
||||
|
||||
title = os.path.basename(full_path)
|
||||
|
||||
# 调 univer-office 生成 docx(IDocumentData -> docx,保留格式)
|
||||
# 调 univer-office 生成 office 文件(按扩展名分流,保留格式)
|
||||
# xlsx: IWorkbookData -> xlsx;docx: IDocumentData -> docx
|
||||
try:
|
||||
timeout = aiohttp.ClientTimeout(total=120)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.post(
|
||||
'http://127.0.0.1:19091/convert/doc-data-to-docx',
|
||||
json={'documentData': documentData, 'title': title},
|
||||
) as resp:
|
||||
if _is_sheet:
|
||||
_url = 'http://127.0.0.1:19091/convert/workbook-data-to-xlsx'
|
||||
_req_json = {'workbookData': _payload}
|
||||
else:
|
||||
_url = 'http://127.0.0.1:19091/convert/doc-data-to-docx'
|
||||
_req_json = {'documentData': _payload, 'title': title}
|
||||
async with session.post(_url, json=_req_json) as resp:
|
||||
if resp.status != 200:
|
||||
return {"success": False, "error": f"导出失败 HTTP {resp.status}"}
|
||||
docx_bytes = await resp.read()
|
||||
return {"success": False, "error": "导出失败 HTTP " + str(resp.status)}
|
||||
out_bytes = await resp.read()
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
# 写回工作空间
|
||||
try:
|
||||
with open(full_path, 'wb') as f:
|
||||
f.write(docx_bytes)
|
||||
return {"success": True, "bytes": len(docx_bytes)}
|
||||
f.write(out_bytes)
|
||||
return {"success": True, "bytes": len(out_bytes)}
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
@ -54,7 +54,7 @@ text_exts = ['.md', '.py', '.js', '.html', '.css', '.json', '.txt', '.xml', '.ya
|
||||
video_exts = ['.mp4', '.m3u8', '.mpd', '.webm', '.mov', '.avi', '.mkv']
|
||||
audio_exts = ['.mp3', '.wav', '.aac', '.flac', '.m4a', '.ogg']
|
||||
image_exts = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.bmp', '.ico']
|
||||
office_exts = ['.docx'] # 在线编辑(univer-office)。xlsx/ppt 后续接入 Univer sheet/slide 插件
|
||||
office_exts = ['.docx', '.xlsx', '.xlsm'] # 在线查看/编辑(univer-office)。ppt 后续接入 Univer slide 插件
|
||||
|
||||
# 二级 URL 双透传 session_id + pipeline_id(2026-09-17 根因同 workspace_view/upload):
|
||||
# 通用助手(pipeline_id=_generic、无 session_id)下漏拼 pipeline_id 会让下游端点
|
||||
|
||||
@ -139,9 +139,9 @@ if ext in image_exts:
|
||||
}]
|
||||
}
|
||||
|
||||
# office 文档(docx)→ univer-office 在线查看(mode=view 只读,不显示保存按钮)+ 下载按钮
|
||||
# (2026-09-18 用户要求:查看和编辑都在线,另提供下载按钮)
|
||||
office_exts = ['.docx']
|
||||
# office 文档(docx/xlsx)→ univer-office 在线查看(mode=view 只读,不显示保存按钮)+ 下载按钮
|
||||
# (2026-09-18 用户要求:查看和编辑都在线,另提供下载按钮;同日 xlsx 接入)
|
||||
office_exts = ['.docx', '.xlsx', '.xlsm']
|
||||
if ext in office_exts:
|
||||
univer_url = entire_url("/univer-office/") + "?file=" + quote(file_id) + "&mode=view" + _fq_s
|
||||
download_url_v = file_url + "&download=1"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user