This commit is contained in:
Leo
2026-01-15 21:49:38 +08:00
parent c837917be3
commit 2ce45e5ccc
4 changed files with 171 additions and 7 deletions

View File

@@ -494,5 +494,77 @@ public class WPS365Controller extends BaseController {
return AjaxResult.error("批量更新单元格数据失败: " + e.getMessage());
}
}
/**
* 读取AirSheet工作表数据
*/
@GetMapping("/readAirSheetCells")
public AjaxResult readAirSheetCells(@RequestParam String userId,
@RequestParam String worksheetId,
@RequestParam(required = false) String range) {
try {
WPS365TokenInfo tokenInfo = wps365OAuthServiceImpl.getTokenByUserId(userId);
if (tokenInfo == null) {
return AjaxResult.error("用户未授权,请先完成授权");
}
// 检查Token是否有效
if (tokenInfo.isExpired() && tokenInfo.getRefreshToken() != null) {
try {
tokenInfo = wps365OAuthService.refreshAccessToken(tokenInfo.getRefreshToken());
wps365OAuthService.saveToken(userId, tokenInfo);
} catch (Exception e) {
log.error("刷新Token失败", e);
return AjaxResult.error("Token已过期且刷新失败请重新授权");
}
}
JSONObject result = wps365ApiService.readAirSheetCells(tokenInfo.getAccessToken(), worksheetId, range);
return AjaxResult.success("读取AirSheet数据成功", result);
} catch (Exception e) {
log.error("读取AirSheet数据失败 - worksheetId: {}, range: {}", worksheetId, range, e);
return AjaxResult.error("读取AirSheet数据失败: " + e.getMessage());
}
}
/**
* 更新AirSheet工作表数据
*/
@PostMapping("/updateAirSheetCells")
public AjaxResult updateAirSheetCells(@RequestBody Map<String, Object> params) {
try {
String userId = (String) params.get("userId");
String worksheetId = (String) params.get("worksheetId");
String range = (String) params.get("range");
@SuppressWarnings("unchecked")
List<List<Object>> values = (List<List<Object>>) params.get("values");
if (userId == null || worksheetId == null) {
return AjaxResult.error("userId和worksheetId不能为空");
}
WPS365TokenInfo tokenInfo = wps365OAuthServiceImpl.getTokenByUserId(userId);
if (tokenInfo == null) {
return AjaxResult.error("用户未授权,请先完成授权");
}
// 检查Token是否有效
if (tokenInfo.isExpired() && tokenInfo.getRefreshToken() != null) {
try {
tokenInfo = wps365OAuthService.refreshAccessToken(tokenInfo.getRefreshToken());
wps365OAuthService.saveToken(userId, tokenInfo);
} catch (Exception e) {
log.error("刷新Token失败", e);
return AjaxResult.error("Token已过期且刷新失败请重新授权");
}
}
JSONObject result = wps365ApiService.updateAirSheetCells(tokenInfo.getAccessToken(), worksheetId, range, values);
return AjaxResult.success("更新AirSheet数据成功", result);
} catch (Exception e) {
log.error("更新AirSheet数据失败", e);
return AjaxResult.error("更新AirSheet数据失败: " + e.getMessage());
}
}
}

View File

@@ -90,5 +90,26 @@ public interface IWPS365ApiService {
* @return 更新结果
*/
JSONObject batchUpdateCells(String accessToken, String fileToken, int sheetIdx, List<Map<String, Object>> updates);
/**
* 读取AirSheet工作表数据
*
* @param accessToken 访问令牌
* @param worksheetId 工作表ID文件ID
* @param range 单元格范围A1:B10可选
* @return 单元格数据
*/
JSONObject readAirSheetCells(String accessToken, String worksheetId, String range);
/**
* 更新AirSheet工作表数据
*
* @param accessToken 访问令牌
* @param worksheetId 工作表ID文件ID
* @param range 单元格范围A1:B2
* @param values 单元格值(二维数组,第一维是行,第二维是列)
* @return 更新结果
*/
JSONObject updateAirSheetCells(String accessToken, String worksheetId, String range, List<List<Object>> values);
}

View File

@@ -47,7 +47,9 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
@Override
public JSONObject getFileList(String accessToken, Map<String, Object> params) {
try {
StringBuilder url = new StringBuilder(wps365Config.getApiBaseUrl() + "/files");
// WPS365文件列表API路径可能是 /yundoc/files 而不是 /files
// 根据WPS365 API文档文件相关API通常在 /yundoc 路径下
StringBuilder url = new StringBuilder(wps365Config.getApiBaseUrl() + "/yundoc/files");
// 添加查询参数
if (params != null && !params.isEmpty()) {
@@ -57,14 +59,22 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
if (!first) {
url.append("&");
}
// URL编码参数值
try {
String key = entry.getKey();
String value = entry.getValue() != null ? entry.getValue().toString() : "";
url.append(key).append("=").append(java.net.URLEncoder.encode(value, "UTF-8"));
} catch (java.io.UnsupportedEncodingException e) {
url.append(entry.getKey()).append("=").append(entry.getValue());
}
first = false;
}
}
log.debug("调用文件列表API: {}", url.toString());
return WPS365ApiUtil.httpRequest("GET", url.toString(), accessToken, null);
} catch (Exception e) {
log.error("获取文件列表失败", e);
log.error("获取文件列表失败 - url: {}", wps365Config.getApiBaseUrl() + "/yundoc/files", e);
throw new RuntimeException("获取文件列表失败: " + e.getMessage(), e);
}
}
@@ -72,10 +82,13 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
@Override
public JSONObject getFileInfo(String accessToken, String fileToken) {
try {
String url = wps365Config.getApiBaseUrl() + "/files/" + fileToken;
// WPS365文件信息API路径/yundoc/files/{fileToken}
String url = wps365Config.getApiBaseUrl() + "/yundoc/files/" + fileToken;
log.debug("调用文件信息API: {}", url);
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
} catch (Exception e) {
log.error("获取文件信息失败 - fileToken: {}", fileToken, e);
log.error("获取文件信息失败 - fileToken: {}, url: {}", fileToken,
wps365Config.getApiBaseUrl() + "/yundoc/files/" + fileToken, e);
throw new RuntimeException("获取文件信息失败: " + e.getMessage(), e);
}
}
@@ -203,5 +216,60 @@ public class WPS365ApiServiceImpl implements IWPS365ApiService {
throw new RuntimeException("批量更新单元格数据失败: " + e.getMessage(), e);
}
}
@Override
public JSONObject readAirSheetCells(String accessToken, String worksheetId, String range) {
try {
// WPS365 AirSheet API: GET /api/v1/openapi/airsheet/worksheets/{worksheetId}
// 根据文档https://open.wps.cn/documents/app-integration-dev/wps365/server/airsheet/worksheets/VbHZwButmh
String url = wps365Config.getApiBaseUrl() + "/openapi/airsheet/worksheets/" + worksheetId;
if (range != null && !range.trim().isEmpty()) {
url += "?range=" + java.net.URLEncoder.encode(range, "UTF-8");
}
log.debug("读取AirSheet数据 - url: {}, range: {}", url, range);
return WPS365ApiUtil.httpRequest("GET", url, accessToken, null);
} catch (Exception e) {
log.error("读取AirSheet数据失败 - worksheetId: {}, range: {}", worksheetId, range, e);
throw new RuntimeException("读取AirSheet数据失败: " + e.getMessage(), e);
}
}
@Override
public JSONObject updateAirSheetCells(String accessToken, String worksheetId, String range, List<List<Object>> values) {
try {
// WPS365 AirSheet API: PUT /api/v1/openapi/airsheet/worksheets/{worksheetId}
String url = wps365Config.getApiBaseUrl() + "/openapi/airsheet/worksheets/" + worksheetId;
// 构建请求体
JSONObject requestBody = new JSONObject();
if (range != null && !range.trim().isEmpty()) {
requestBody.put("range", range);
}
// 构建values数组
JSONArray valuesArray = new JSONArray();
if (values != null) {
for (List<Object> row : values) {
JSONArray rowArray = new JSONArray();
if (row != null) {
for (Object cell : row) {
rowArray.add(cell);
}
}
valuesArray.add(rowArray);
}
}
requestBody.put("values", valuesArray);
String bodyStr = requestBody.toJSONString();
log.debug("更新AirSheet数据 - url: {}, range: {}, values: {}", url, range, bodyStr);
return WPS365ApiUtil.httpRequest("PUT", url, accessToken, bodyStr);
} catch (Exception e) {
log.error("更新AirSheet数据失败 - worksheetId: {}, range: {}", worksheetId, range, e);
throw new RuntimeException("更新AirSheet数据失败: " + e.getMessage(), e);
}
}
}

View File

@@ -261,10 +261,13 @@ public class WPS365ApiUtil {
}
String responseStr = response.toString();
log.debug("HTTP响应: statusCode={}, response={}", statusCode, responseStr);
log.info("HTTP响应: statusCode={}, url={}, response={}", statusCode, url, responseStr);
if (statusCode < 200 || statusCode >= 300) {
throw new RuntimeException("HTTP请求失败: statusCode=" + statusCode + ", response=" + responseStr);
String errorMsg = String.format("HTTP请求失败: statusCode=%d, url=%s, response=%s",
statusCode, url, responseStr);
log.error(errorMsg);
throw new RuntimeException(errorMsg);
}
if (responseStr == null || responseStr.trim().isEmpty()) {