Compare commits

...

2 Commits

Author SHA1 Message Date
Leo
9483ebf1f5 1 2026-01-06 18:51:38 +08:00
Leo
440df7d538 1 2026-01-06 18:50:24 +08:00
2 changed files with 115 additions and 108 deletions

View File

@@ -75,6 +75,13 @@
<logger name="com.ruoyi" level="info" /> <logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 --> <!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" /> <logger name="org.springframework" level="warn" />
<!-- MyBatis SQL日志级别控制 - 关闭SQL打印 -->
<logger name="org.apache.ibatis" level="warn" />
<logger name="java.sql" level="warn" />
<logger name="java.sql.Connection" level="warn" />
<logger name="java.sql.Statement" level="warn" />
<logger name="java.sql.PreparedStatement" level="warn" />
<logger name="java.sql.ResultSet" level="warn" />
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console" />

View File

@@ -17,32 +17,32 @@ import java.util.List;
/** /**
* 腾讯文档服务实现类 * 腾讯文档服务实现类
* *
* @author system * @author system
*/ */
@Service @Service
public class TencentDocServiceImpl implements ITencentDocService { public class TencentDocServiceImpl implements ITencentDocService {
private static final Logger log = LoggerFactory.getLogger(TencentDocServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(TencentDocServiceImpl.class);
@Autowired @Autowired
private TencentDocConfig tencentDocConfig; private TencentDocConfig tencentDocConfig;
@Autowired @Autowired
private com.ruoyi.common.core.redis.RedisCache redisCache; private com.ruoyi.common.core.redis.RedisCache redisCache;
@Override @Override
public String getAuthUrl() { public String getAuthUrl() {
if (tencentDocConfig == null) { if (tencentDocConfig == null) {
throw new RuntimeException("腾讯文档配置未加载请检查TencentDocConfig是否正确注入"); throw new RuntimeException("腾讯文档配置未加载请检查TencentDocConfig是否正确注入");
} }
String appId = tencentDocConfig.getAppId(); String appId = tencentDocConfig.getAppId();
String redirectUri = tencentDocConfig.getRedirectUri(); String redirectUri = tencentDocConfig.getRedirectUri();
String oauthUrl = tencentDocConfig.getOauthUrl(); String oauthUrl = tencentDocConfig.getOauthUrl();
log.debug("获取授权URL - appId: {}, redirectUri: {}, oauthUrl: {}", appId, redirectUri, oauthUrl); log.debug("获取授权URL - appId: {}, redirectUri: {}, oauthUrl: {}", appId, redirectUri, oauthUrl);
// 验证配置参数 // 验证配置参数
if (appId == null || appId.trim().isEmpty()) { if (appId == null || appId.trim().isEmpty()) {
throw new RuntimeException("腾讯文档应用ID未配置请检查application-dev.yml中的tencent.doc.app-id配置"); throw new RuntimeException("腾讯文档应用ID未配置请检查application-dev.yml中的tencent.doc.app-id配置");
@@ -54,7 +54,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
oauthUrl = "https://docs.qq.com/oauth/v2/authorize"; // 使用默认值 oauthUrl = "https://docs.qq.com/oauth/v2/authorize"; // 使用默认值
log.warn("OAuth URL未配置使用默认值: {}", oauthUrl); log.warn("OAuth URL未配置使用默认值: {}", oauthUrl);
} }
// 构建授权URL根据腾讯文档官方文档https://docs.qq.com/open/document/app/oauth2/authorize.html // 构建授权URL根据腾讯文档官方文档https://docs.qq.com/open/document/app/oauth2/authorize.html
StringBuilder authUrl = new StringBuilder(); StringBuilder authUrl = new StringBuilder();
authUrl.append(oauthUrl); authUrl.append(oauthUrl);
@@ -72,16 +72,16 @@ public class TencentDocServiceImpl implements ITencentDocService {
} }
authUrl.append("&response_type=code"); authUrl.append("&response_type=code");
authUrl.append("&scope=all"); // 根据官方文档scope固定为all authUrl.append("&scope=all"); // 根据官方文档scope固定为all
// 添加state参数用于防CSRF攻击可选但建议带上 // 添加state参数用于防CSRF攻击可选但建议带上
String state = java.util.UUID.randomUUID().toString(); String state = java.util.UUID.randomUUID().toString();
authUrl.append("&state=").append(state); authUrl.append("&state=").append(state);
String result = authUrl.toString(); String result = authUrl.toString();
log.info("生成授权URL: {}", result); log.info("生成授权URL: {}", result);
return result; return result;
} }
@Override @Override
public JSONObject getAccessTokenByCode(String code) { public JSONObject getAccessTokenByCode(String code) {
try { try {
@@ -97,7 +97,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("获取访问令牌失败: " + e.getMessage(), e); throw new RuntimeException("获取访问令牌失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject refreshAccessToken(String refreshToken) { public JSONObject refreshAccessToken(String refreshToken) {
try { try {
@@ -112,14 +112,14 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("刷新访问令牌失败: " + e.getMessage(), e); throw new RuntimeException("刷新访问令牌失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject uploadLogisticsToSheet(String accessToken, String fileId, String sheetId, List<JDOrder> orders) { public JSONObject uploadLogisticsToSheet(String accessToken, String fileId, String sheetId, List<JDOrder> orders) {
try { try {
if (orders == null || orders.isEmpty()) { if (orders == null || orders.isEmpty()) {
throw new IllegalArgumentException("订单列表不能为空"); throw new IllegalArgumentException("订单列表不能为空");
} }
// 获取用户信息包含Open-Id // 获取用户信息包含Open-Id
// 官方响应格式:{ "ret": 0, "msg": "Succeed", "data": { "openID": "xxx", ... } } // 官方响应格式:{ "ret": 0, "msg": "Succeed", "data": { "openID": "xxx", ... } }
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken); JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
@@ -131,11 +131,11 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效"); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效");
} }
// 构建要写入的数据(二维数组格式) // 构建要写入的数据(二维数组格式)
JSONArray values = new JSONArray(); JSONArray values = new JSONArray();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (JDOrder order : orders) { for (JDOrder order : orders) {
JSONArray row = new JSONArray(); JSONArray row = new JSONArray();
// 根据表格列顺序添加数据 // 根据表格列顺序添加数据
@@ -150,18 +150,18 @@ public class TencentDocServiceImpl implements ITencentDocService {
row.add(order.getPaymentAmount() != null ? order.getPaymentAmount().toString() : ""); row.add(order.getPaymentAmount() != null ? order.getPaymentAmount().toString() : "");
row.add(order.getRebateAmount() != null ? order.getRebateAmount().toString() : ""); row.add(order.getRebateAmount() != null ? order.getRebateAmount().toString() : "");
row.add(order.getStatus() != null ? order.getStatus() : ""); row.add(order.getStatus() != null ? order.getStatus() : "");
values.add(row); values.add(row);
} }
// 追加数据到表格 // 追加数据到表格
return TencentDocApiUtil.appendSheetData( return TencentDocApiUtil.appendSheetData(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),
openId, openId,
fileId, fileId,
sheetId, sheetId,
values, values,
tencentDocConfig.getApiBaseUrl() tencentDocConfig.getApiBaseUrl()
); );
} catch (Exception e) { } catch (Exception e) {
@@ -169,38 +169,38 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("上传物流信息失败: " + e.getMessage(), e); throw new RuntimeException("上传物流信息失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject appendLogisticsToSheet(String accessToken, String fileId, String sheetId, Integer startRow, JDOrder order) { public JSONObject appendLogisticsToSheet(String accessToken, String fileId, String sheetId, Integer startRow, JDOrder order) {
try { try {
if (order == null) { if (order == null) {
throw new IllegalArgumentException("订单信息不能为空"); throw new IllegalArgumentException("订单信息不能为空");
} }
log.info("录单自动写入腾讯文档 - fileId: {}, sheetId: {}, startRow: {}, 订单单号: {}", log.info("录单自动写入腾讯文档 - fileId: {}, sheetId: {}, startRow: {}, 订单单号: {}",
fileId, sheetId, startRow, order.getThirdPartyOrderNo()); fileId, sheetId, startRow, order.getThirdPartyOrderNo());
// 1. 读取表头从Redis或配置获取headerRow // 1. 读取表头从Redis或配置获取headerRow
final String CONFIG_KEY_PREFIX = "tencent:doc:auto:config:"; final String CONFIG_KEY_PREFIX = "tencent:doc:auto:config:";
Integer headerRowNum = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "headerRow"); Integer headerRowNum = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "headerRow");
if (headerRowNum == null) { if (headerRowNum == null) {
headerRowNum = tencentDocConfig.getHeaderRow(); headerRowNum = tencentDocConfig.getHeaderRow();
} }
String headerRange = String.format("A%d:Z%d", headerRowNum, headerRowNum); String headerRange = String.format("A%d:Z%d", headerRowNum, headerRowNum);
JSONObject headerData = readSheetData(accessToken, fileId, sheetId, headerRange); JSONObject headerData = readSheetData(accessToken, fileId, sheetId, headerRange);
if (headerData == null || !headerData.containsKey("values")) { if (headerData == null || !headerData.containsKey("values")) {
throw new RuntimeException("无法读取表头数据"); throw new RuntimeException("无法读取表头数据");
} }
JSONArray headerValues = headerData.getJSONArray("values"); JSONArray headerValues = headerData.getJSONArray("values");
if (headerValues == null || headerValues.isEmpty()) { if (headerValues == null || headerValues.isEmpty()) {
throw new RuntimeException("表头数据为空"); throw new RuntimeException("表头数据为空");
} }
JSONArray headerCells = headerValues.getJSONArray(0); JSONArray headerCells = headerValues.getJSONArray(0);
// 2. 识别列位置(根据表头) // 2. 识别列位置(根据表头)
Integer dateColumn = null; Integer dateColumn = null;
Integer companyColumn = null; Integer companyColumn = null;
@@ -214,7 +214,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
Integer remarkColumn = null; Integer remarkColumn = null;
Integer arrangedColumn = null; // 是否安排列 Integer arrangedColumn = null; // 是否安排列
Integer logisticsColumn = null; Integer logisticsColumn = null;
for (int i = 0; i < headerCells.size(); i++) { for (int i = 0; i < headerCells.size(); i++) {
String cellText = headerCells.getString(i); String cellText = headerCells.getString(i);
if (cellText != null) { if (cellText != null) {
@@ -232,24 +232,24 @@ public class TencentDocServiceImpl implements ITencentDocService {
else if (cellText.contains("物流")) logisticsColumn = i; else if (cellText.contains("物流")) logisticsColumn = i;
} }
} }
if (orderNoColumn == null) { if (orderNoColumn == null) {
throw new RuntimeException("未找到'单号'列,请检查表头配置"); throw new RuntimeException("未找到'单号'列,请检查表头配置");
} }
log.info("表头识别完成 - 单号列: {}, 物流列: {}", orderNoColumn, logisticsColumn); log.info("表头识别完成 - 单号列: {}, 物流列: {}", orderNoColumn, logisticsColumn);
// 3. 读取数据区域,查找第一个空行(单号列为空) // 3. 读取数据区域,查找第一个空行(单号列为空)
String dataRange = String.format("A%d:Z%d", startRow, startRow + 999); String dataRange = String.format("A%d:Z%d", startRow, startRow + 999);
JSONObject sheetData = readSheetData(accessToken, fileId, sheetId, dataRange); JSONObject sheetData = readSheetData(accessToken, fileId, sheetId, dataRange);
if (sheetData == null || !sheetData.containsKey("values")) { if (sheetData == null || !sheetData.containsKey("values")) {
throw new RuntimeException("无法读取数据区域"); throw new RuntimeException("无法读取数据区域");
} }
JSONArray dataRows = sheetData.getJSONArray("values"); JSONArray dataRows = sheetData.getJSONArray("values");
int targetRow = -1; int targetRow = -1;
// 查找第一个单号列为空的行 // 查找第一个单号列为空的行
if (dataRows == null || dataRows.isEmpty()) { if (dataRows == null || dataRows.isEmpty()) {
// 数据区域完全为空使用startRow // 数据区域完全为空使用startRow
@@ -267,22 +267,22 @@ public class TencentDocServiceImpl implements ITencentDocService {
break; break;
} }
} }
// 如果没找到空行,追加到数据区域末尾 // 如果没找到空行,追加到数据区域末尾
if (targetRow == -1) { if (targetRow == -1) {
targetRow = startRow + dataRows.size(); targetRow = startRow + dataRows.size();
} }
} }
log.info("找到空行位置:第 {} 行", targetRow); log.info("找到空行位置:第 {} 行", targetRow);
// 4. 构建要写入的数据(按表头列顺序) // 4. 构建要写入的数据(按表头列顺序)
SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd"); SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
String today = dateFormat.format(new java.util.Date()); String today = dateFormat.format(new java.util.Date());
JSONArray requests = new JSONArray(); JSONArray requests = new JSONArray();
int rowIndex = targetRow - 1; // 转为0索引 int rowIndex = targetRow - 1; // 转为0索引
// 写入各列数据 // 写入各列数据
if (dateColumn != null) { if (dateColumn != null) {
requests.add(buildUpdateRequest(sheetId, rowIndex, dateColumn, today, false)); requests.add(buildUpdateRequest(sheetId, rowIndex, dateColumn, today, false));
@@ -298,13 +298,13 @@ public class TencentDocServiceImpl implements ITencentDocService {
} }
// 数量列 - JDOrder 没有 quantity 字段,暂时跳过 // 数量列 - JDOrder 没有 quantity 字段,暂时跳过
// if (quantityColumn != null) { ... } // if (quantityColumn != null) { ... }
if (nameColumn != null && order.getBuyer() != null) { if (nameColumn != null && order.getBuyer() != null) {
requests.add(buildUpdateRequest(sheetId, rowIndex, nameColumn, order.getBuyer(), false)); requests.add(buildUpdateRequest(sheetId, rowIndex, nameColumn, order.getBuyer(), false));
} }
// 电话列 - JDOrder 没有 phone 字段,暂时跳过 // 电话列 - JDOrder 没有 phone 字段,暂时跳过
// if (phoneColumn != null) { ... } // if (phoneColumn != null) { ... }
if (addressColumn != null && order.getAddress() != null) { if (addressColumn != null && order.getAddress() != null) {
requests.add(buildUpdateRequest(sheetId, rowIndex, addressColumn, order.getAddress(), false)); requests.add(buildUpdateRequest(sheetId, rowIndex, addressColumn, order.getAddress(), false));
} }
@@ -322,49 +322,49 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (logisticsColumn != null && order.getLogisticsLink() != null && !order.getLogisticsLink().isEmpty()) { if (logisticsColumn != null && order.getLogisticsLink() != null && !order.getLogisticsLink().isEmpty()) {
requests.add(buildUpdateRequest(sheetId, rowIndex, logisticsColumn, order.getLogisticsLink(), true)); // 超链接 requests.add(buildUpdateRequest(sheetId, rowIndex, logisticsColumn, order.getLogisticsLink(), true)); // 超链接
} }
// 5. 使用 batchUpdate 写入 // 5. 使用 batchUpdate 写入
if (requests.isEmpty()) { if (requests.isEmpty()) {
throw new RuntimeException("没有数据可以写入"); throw new RuntimeException("没有数据可以写入");
} }
JSONObject batchUpdateBody = new JSONObject(); JSONObject batchUpdateBody = new JSONObject();
batchUpdateBody.put("requests", requests); batchUpdateBody.put("requests", requests);
JSONObject result = batchUpdate(accessToken, fileId, batchUpdateBody); JSONObject result = batchUpdate(accessToken, fileId, batchUpdateBody);
log.info("✓ 订单成功写入腾讯文档 - 行: {}, 单号: {}", targetRow, order.getThirdPartyOrderNo()); log.info("✓ 订单成功写入腾讯文档 - 行: {}, 单号: {}", targetRow, order.getThirdPartyOrderNo());
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
response.put("row", targetRow); response.put("row", targetRow);
response.put("orderNo", order.getThirdPartyOrderNo()); response.put("orderNo", order.getThirdPartyOrderNo());
response.put("success", true); response.put("success", true);
return response; return response;
} catch (Exception e) { } catch (Exception e) {
log.error("追加物流信息到表格失败", e); log.error("追加物流信息到表格失败", e);
throw new RuntimeException("追加物流信息失败: " + e.getMessage(), e); throw new RuntimeException("追加物流信息失败: " + e.getMessage(), e);
} }
} }
/** /**
* 构建单元格更新请求 * 构建单元格更新请求
*/ */
private JSONObject buildUpdateRequest(String sheetId, int rowIndex, int columnIndex, String value, boolean isLink) { private JSONObject buildUpdateRequest(String sheetId, int rowIndex, int columnIndex, String value, boolean isLink) {
JSONObject updateRangeRequest = new JSONObject(); JSONObject updateRangeRequest = new JSONObject();
updateRangeRequest.put("sheetId", sheetId); updateRangeRequest.put("sheetId", sheetId);
JSONObject gridData = new JSONObject(); JSONObject gridData = new JSONObject();
gridData.put("startRow", rowIndex); gridData.put("startRow", rowIndex);
gridData.put("startColumn", columnIndex); gridData.put("startColumn", columnIndex);
JSONArray rows = new JSONArray(); JSONArray rows = new JSONArray();
JSONObject rowData = new JSONObject(); JSONObject rowData = new JSONObject();
JSONArray cellValues = new JSONArray(); JSONArray cellValues = new JSONArray();
JSONObject cellData = new JSONObject(); JSONObject cellData = new JSONObject();
JSONObject cellValue = new JSONObject(); JSONObject cellValue = new JSONObject();
if (isLink) { if (isLink) {
JSONObject link = new JSONObject(); JSONObject link = new JSONObject();
link.put("url", value); link.put("url", value);
@@ -373,64 +373,64 @@ public class TencentDocServiceImpl implements ITencentDocService {
} else { } else {
cellValue.put("text", value); cellValue.put("text", value);
} }
cellData.put("cellValue", cellValue); cellData.put("cellValue", cellValue);
cellValues.add(cellData); cellValues.add(cellData);
rowData.put("values", cellValues); rowData.put("values", cellValues);
rows.add(rowData); rows.add(rowData);
gridData.put("rows", rows); gridData.put("rows", rows);
updateRangeRequest.put("gridData", gridData); updateRangeRequest.put("gridData", gridData);
JSONObject request = new JSONObject(); JSONObject request = new JSONObject();
request.put("updateRangeRequest", updateRangeRequest); request.put("updateRangeRequest", updateRangeRequest);
return request; return request;
} }
@Override @Override
public JSONObject readSheetData(String accessToken, String fileId, String sheetId, String range) { public JSONObject readSheetData(String accessToken, String fileId, String sheetId, String range) {
try { try {
log.info("Service层 - 开始读取表格数据: fileId={}, sheetId={}, range={}", fileId, sheetId, range); log.info("Service层 - 开始读取表格数据: fileId={}, sheetId={}, range={}", fileId, sheetId, range);
// 获取用户信息包含Open-Id // 获取用户信息包含Open-Id
// 官方响应格式:{ "ret": 0, "msg": "Succeed", "data": { "openID": "xxx", ... } } // 官方响应格式:{ "ret": 0, "msg": "Succeed", "data": { "openID": "xxx", ... } }
log.debug("正在获取用户信息..."); log.debug("正在获取用户信息...");
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken); JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
log.debug("用户信息响应: {}", userInfo != null ? userInfo.toJSONString() : "null"); log.debug("用户信息响应: {}", userInfo != null ? userInfo.toJSONString() : "null");
if (userInfo == null) { if (userInfo == null) {
throw new RuntimeException("getUserInfo 返回 nullAccess Token 可能无效"); throw new RuntimeException("getUserInfo 返回 nullAccess Token 可能无效");
} }
JSONObject data = userInfo.getJSONObject("data"); JSONObject data = userInfo.getJSONObject("data");
if (data == null) { if (data == null) {
log.error("用户信息响应中没有 data 字段,完整响应: {}", userInfo.toJSONString()); log.error("用户信息响应中没有 data 字段,完整响应: {}", userInfo.toJSONString());
throw new RuntimeException("无法获取用户数据请检查Access Token是否有效。响应: " + userInfo.toJSONString()); throw new RuntimeException("无法获取用户数据请检查Access Token是否有效。响应: " + userInfo.toJSONString());
} }
String openId = data.getString("openID"); // 注意:官方返回的字段名是 openID大写ID String openId = data.getString("openID"); // 注意:官方返回的字段名是 openID大写ID
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
log.error("data 对象中没有 openID 字段data内容: {}", data.toJSONString()); log.error("data 对象中没有 openID 字段data内容: {}", data.toJSONString());
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效。data: " + data.toJSONString()); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效。data: " + data.toJSONString());
} }
log.info("成功获取 Open ID: {}", openId); log.info("成功获取 Open ID: {}", openId);
log.info("准备调用API - appId: {}, apiBaseUrl: {}", tencentDocConfig.getAppId(), tencentDocConfig.getApiBaseUrl()); log.info("准备调用API - appId: {}, apiBaseUrl: {}", tencentDocConfig.getAppId(), tencentDocConfig.getApiBaseUrl());
JSONObject result = TencentDocApiUtil.readSheetData( JSONObject result = TencentDocApiUtil.readSheetData(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),
openId, openId,
fileId, fileId,
sheetId, sheetId,
range, range,
tencentDocConfig.getApiBaseUrl() tencentDocConfig.getApiBaseUrl()
); );
log.info("API调用成功原始返回结果: {}", result != null ? result.toJSONString() : "null"); //log.info("API调用成功原始返回结果: {}", result != null ? result.toJSONString() : "null");
// 检查API响应中的错误码 // 检查API响应中的错误码
// 根据官方文档,成功响应包含 ret=0错误响应包含 code!=0 // 根据官方文档,成功响应包含 ret=0错误响应包含 code!=0
// 参考https://docs.qq.com/open/document/app/openapi/v3/sheet/get/get_range.html // 参考https://docs.qq.com/open/document/app/openapi/v3/sheet/get/get_range.html
@@ -454,27 +454,27 @@ public class TencentDocServiceImpl implements ITencentDocService {
} }
} }
} }
// 解析数据为统一的简单格式 // 解析数据为统一的简单格式
JSONArray parsedValues = TencentDocDataParser.parseToSimpleArray(result); JSONArray parsedValues = TencentDocDataParser.parseToSimpleArray(result);
log.info("解析后的数据行数: {}", parsedValues != null ? parsedValues.size() : 0); log.info("解析后的数据行数: {}", parsedValues != null ? parsedValues.size() : 0);
if (parsedValues != null && !parsedValues.isEmpty()) { if (parsedValues != null && !parsedValues.isEmpty()) {
TencentDocDataParser.printDataStructure(result, 3); TencentDocDataParser.printDataStructure(result, 3);
} }
// 返回包含简化格式的响应 // 返回包含简化格式的响应
JSONObject response = new JSONObject(); JSONObject response = new JSONObject();
response.put("values", parsedValues); response.put("values", parsedValues);
response.put("_原始数据", result); // 保留原始数据供调试 response.put("_原始数据", result); // 保留原始数据供调试
return response; return response;
} catch (Exception e) { } catch (Exception e) {
log.error("读取表格数据失败 - fileId: {}, sheetId: {}, range: {}", fileId, sheetId, range, e); log.error("读取表格数据失败 - fileId: {}, sheetId: {}, range: {}", fileId, sheetId, range, e);
throw new RuntimeException("读取表格数据失败: " + e.getMessage(), e); throw new RuntimeException("读取表格数据失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject writeSheetData(String accessToken, String fileId, String sheetId, String range, Object values) { public JSONObject writeSheetData(String accessToken, String fileId, String sheetId, String range, Object values) {
try { try {
@@ -489,15 +489,15 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效"); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效");
} }
return TencentDocApiUtil.writeSheetData( return TencentDocApiUtil.writeSheetData(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),
openId, openId,
fileId, fileId,
sheetId, sheetId,
range, range,
values, values,
tencentDocConfig.getApiBaseUrl() tencentDocConfig.getApiBaseUrl()
); );
} catch (Exception e) { } catch (Exception e) {
@@ -505,7 +505,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("写入表格数据失败: " + e.getMessage(), e); throw new RuntimeException("写入表格数据失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject getFileInfo(String accessToken, String fileId) { public JSONObject getFileInfo(String accessToken, String fileId) {
try { try {
@@ -520,12 +520,12 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效"); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效");
} }
return TencentDocApiUtil.getFileInfo( return TencentDocApiUtil.getFileInfo(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),
openId, openId,
fileId, fileId,
tencentDocConfig.getApiBaseUrl() tencentDocConfig.getApiBaseUrl()
); );
} catch (Exception e) { } catch (Exception e) {
@@ -533,7 +533,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("获取文件信息失败: " + e.getMessage(), e); throw new RuntimeException("获取文件信息失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject getSheetList(String accessToken, String fileId) { public JSONObject getSheetList(String accessToken, String fileId) {
try { try {
@@ -548,12 +548,12 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效"); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效");
} }
return TencentDocApiUtil.getSheetList( return TencentDocApiUtil.getSheetList(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),
openId, openId,
fileId, fileId,
tencentDocConfig.getApiBaseUrl() tencentDocConfig.getApiBaseUrl()
); );
} catch (Exception e) { } catch (Exception e) {
@@ -561,7 +561,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("获取工作表列表失败: " + e.getMessage(), e); throw new RuntimeException("获取工作表列表失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject getUserInfo(String accessToken) { public JSONObject getUserInfo(String accessToken) {
try { try {
@@ -571,7 +571,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
throw new RuntimeException("获取用户信息失败: " + e.getMessage(), e); throw new RuntimeException("获取用户信息失败: " + e.getMessage(), e);
} }
} }
@Override @Override
public JSONObject batchUpdate(String accessToken, String fileId, JSONObject requestBody) { public JSONObject batchUpdate(String accessToken, String fileId, JSONObject requestBody) {
try { try {
@@ -585,7 +585,7 @@ public class TencentDocServiceImpl implements ITencentDocService {
if (openId == null || openId.isEmpty()) { if (openId == null || openId.isEmpty()) {
throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效"); throw new RuntimeException("无法获取Open-Id请检查Access Token是否有效");
} }
return TencentDocApiUtil.batchUpdate( return TencentDocApiUtil.batchUpdate(
accessToken, accessToken,
tencentDocConfig.getAppId(), tencentDocConfig.getAppId(),