1
This commit is contained in:
@@ -174,58 +174,211 @@ public class TencentDocServiceImpl implements ITencentDocService {
|
|||||||
throw new IllegalArgumentException("订单信息不能为空");
|
throw new IllegalArgumentException("订单信息不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// startRow 参数用于标识从第几行开始是数据行(预留给未来的搜索匹配功能)
|
log.info("录单自动写入腾讯文档 - fileId: {}, sheetId: {}, startRow: {}, 订单单号: {}",
|
||||||
// 当前使用 append 方式追加数据,暂不使用 startRow
|
fileId, sheetId, startRow, order.getThirdPartyOrderNo());
|
||||||
log.debug("追加订单到腾讯文档 - fileId: {}, sheetId: {}, startRow配置: {}, 订单: {}",
|
|
||||||
fileId, sheetId, startRow, order.getRemark());
|
|
||||||
|
|
||||||
// 获取用户信息(包含Open-Id)
|
// 1. 读取表头(从Redis或配置获取headerRow)
|
||||||
// 官方响应格式:{ "ret": 0, "msg": "Succeed", "data": { "openID": "xxx", ... } }
|
final String CONFIG_KEY_PREFIX = "tencent:doc:auto:config:";
|
||||||
JSONObject userInfo = TencentDocApiUtil.getUserInfo(accessToken);
|
Integer headerRowNum = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "headerRow");
|
||||||
JSONObject data = userInfo.getJSONObject("data");
|
if (headerRowNum == null) {
|
||||||
if (data == null) {
|
headerRowNum = tencentDocConfig.getHeaderRow();
|
||||||
throw new RuntimeException("无法获取用户数据,请检查Access Token是否有效");
|
|
||||||
}
|
|
||||||
String openId = data.getString("openID"); // 注意:官方返回的字段名是 openID(大写ID)
|
|
||||||
if (openId == null || openId.isEmpty()) {
|
|
||||||
throw new RuntimeException("无法获取Open-Id,请检查Access Token是否有效");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建单行数据
|
String headerRange = String.format("A%d:Z%d", headerRowNum, headerRowNum);
|
||||||
JSONArray values = new JSONArray();
|
JSONObject headerData = readSheetData(accessToken, fileId, sheetId, headerRange);
|
||||||
JSONArray row = new JSONArray();
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
// 根据表格列顺序添加数据
|
if (headerData == null || !headerData.containsKey("values")) {
|
||||||
row.add(order.getRemark() != null ? order.getRemark() : "");
|
throw new RuntimeException("无法读取表头数据");
|
||||||
row.add(order.getOrderId() != null ? order.getOrderId() : "");
|
}
|
||||||
row.add(order.getOrderTime() != null ? sdf.format(order.getOrderTime()) : "");
|
|
||||||
row.add(order.getModelNumber() != null ? order.getModelNumber() : "");
|
|
||||||
row.add(order.getAddress() != null ? order.getAddress() : "");
|
|
||||||
row.add(order.getLogisticsLink() != null ? order.getLogisticsLink() : "");
|
|
||||||
row.add(order.getBuyer() != null ? order.getBuyer() : "");
|
|
||||||
row.add(order.getPaymentAmount() != null ? order.getPaymentAmount().toString() : "");
|
|
||||||
row.add(order.getRebateAmount() != null ? order.getRebateAmount().toString() : "");
|
|
||||||
row.add(order.getStatus() != null ? order.getStatus() : "");
|
|
||||||
|
|
||||||
values.add(row);
|
JSONArray headerValues = headerData.getJSONArray("values");
|
||||||
|
if (headerValues == null || headerValues.isEmpty()) {
|
||||||
|
throw new RuntimeException("表头数据为空");
|
||||||
|
}
|
||||||
|
|
||||||
// 追加数据到表格
|
JSONArray headerCells = headerValues.getJSONArray(0);
|
||||||
return TencentDocApiUtil.appendSheetData(
|
|
||||||
accessToken,
|
// 2. 识别列位置(根据表头)
|
||||||
tencentDocConfig.getAppId(),
|
Integer dateColumn = null;
|
||||||
openId,
|
Integer companyColumn = null;
|
||||||
fileId,
|
Integer orderNoColumn = null;
|
||||||
sheetId,
|
Integer modelColumn = null;
|
||||||
values,
|
Integer quantityColumn = null;
|
||||||
tencentDocConfig.getApiBaseUrl()
|
Integer nameColumn = null;
|
||||||
);
|
Integer phoneColumn = null;
|
||||||
|
Integer addressColumn = null;
|
||||||
|
Integer priceColumn = null;
|
||||||
|
Integer remarkColumn = null;
|
||||||
|
Integer logisticsColumn = null;
|
||||||
|
|
||||||
|
for (int i = 0; i < headerCells.size(); i++) {
|
||||||
|
String cellText = headerCells.getString(i);
|
||||||
|
if (cellText != null) {
|
||||||
|
if (cellText.contains("日期")) dateColumn = i;
|
||||||
|
else if (cellText.contains("公司")) companyColumn = i;
|
||||||
|
else if (cellText.contains("单号")) orderNoColumn = i;
|
||||||
|
else if (cellText.contains("型号")) modelColumn = i;
|
||||||
|
else if (cellText.contains("数量")) quantityColumn = i;
|
||||||
|
else if (cellText.contains("姓名")) nameColumn = i;
|
||||||
|
else if (cellText.contains("电话")) phoneColumn = i;
|
||||||
|
else if (cellText.contains("地址")) addressColumn = i;
|
||||||
|
else if (cellText.contains("价格")) priceColumn = i;
|
||||||
|
else if (cellText.contains("备注")) remarkColumn = i;
|
||||||
|
else if (cellText.contains("物流")) logisticsColumn = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderNoColumn == null) {
|
||||||
|
throw new RuntimeException("未找到'单号'列,请检查表头配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("表头识别完成 - 单号列: {}, 物流列: {}", orderNoColumn, logisticsColumn);
|
||||||
|
|
||||||
|
// 3. 读取数据区域,查找第一个空行(单号列为空)
|
||||||
|
String dataRange = String.format("A%d:Z%d", startRow, startRow + 999);
|
||||||
|
JSONObject sheetData = readSheetData(accessToken, fileId, sheetId, dataRange);
|
||||||
|
|
||||||
|
if (sheetData == null || !sheetData.containsKey("values")) {
|
||||||
|
throw new RuntimeException("无法读取数据区域");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONArray dataRows = sheetData.getJSONArray("values");
|
||||||
|
int targetRow = -1;
|
||||||
|
|
||||||
|
// 查找第一个单号列为空的行
|
||||||
|
if (dataRows == null || dataRows.isEmpty()) {
|
||||||
|
// 数据区域完全为空,使用startRow
|
||||||
|
targetRow = startRow;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < dataRows.size(); i++) {
|
||||||
|
JSONArray row = dataRows.getJSONArray(i);
|
||||||
|
if (row == null || row.size() <= orderNoColumn) {
|
||||||
|
targetRow = startRow + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String orderNo = row.getString(orderNoColumn);
|
||||||
|
if (orderNo == null || orderNo.trim().isEmpty()) {
|
||||||
|
targetRow = startRow + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没找到空行,追加到数据区域末尾
|
||||||
|
if (targetRow == -1) {
|
||||||
|
targetRow = startRow + dataRows.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("找到空行位置:第 {} 行", targetRow);
|
||||||
|
|
||||||
|
// 4. 构建要写入的数据(按表头列顺序)
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd");
|
||||||
|
String today = dateFormat.format(new java.util.Date());
|
||||||
|
|
||||||
|
JSONArray requests = new JSONArray();
|
||||||
|
int rowIndex = targetRow - 1; // 转为0索引
|
||||||
|
|
||||||
|
// 写入各列数据
|
||||||
|
if (dateColumn != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, dateColumn, today, false));
|
||||||
|
}
|
||||||
|
if (companyColumn != null && order.getDistributionMark() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, companyColumn, order.getDistributionMark(), false));
|
||||||
|
}
|
||||||
|
if (orderNoColumn != null && order.getThirdPartyOrderNo() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, orderNoColumn, order.getThirdPartyOrderNo(), false));
|
||||||
|
}
|
||||||
|
if (modelColumn != null && order.getModelNumber() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, modelColumn, order.getModelNumber(), false));
|
||||||
|
}
|
||||||
|
if (quantityColumn != null && order.getQuantity() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, quantityColumn, order.getQuantity().toString(), false));
|
||||||
|
}
|
||||||
|
if (nameColumn != null && order.getBuyer() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, nameColumn, order.getBuyer(), false));
|
||||||
|
}
|
||||||
|
if (phoneColumn != null && order.getPhone() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, phoneColumn, order.getPhone(), false));
|
||||||
|
}
|
||||||
|
if (addressColumn != null && order.getAddress() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, addressColumn, order.getAddress(), false));
|
||||||
|
}
|
||||||
|
if (priceColumn != null && order.getPaymentAmount() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, priceColumn, order.getPaymentAmount().toString(), false));
|
||||||
|
}
|
||||||
|
if (remarkColumn != null && order.getRemark() != null) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, remarkColumn, order.getRemark(), false));
|
||||||
|
}
|
||||||
|
if (logisticsColumn != null && order.getLogisticsLink() != null && !order.getLogisticsLink().isEmpty()) {
|
||||||
|
requests.add(buildUpdateRequest(sheetId, rowIndex, logisticsColumn, order.getLogisticsLink(), true)); // 超链接
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 使用 batchUpdate 写入
|
||||||
|
if (requests.isEmpty()) {
|
||||||
|
throw new RuntimeException("没有数据可以写入");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject batchUpdateBody = new JSONObject();
|
||||||
|
batchUpdateBody.put("requests", requests);
|
||||||
|
|
||||||
|
JSONObject result = batchUpdate(accessToken, fileId, batchUpdateBody);
|
||||||
|
|
||||||
|
log.info("✓ 订单成功写入腾讯文档 - 行: {}, 单号: {}", targetRow, order.getThirdPartyOrderNo());
|
||||||
|
|
||||||
|
JSONObject response = new JSONObject();
|
||||||
|
response.put("row", targetRow);
|
||||||
|
response.put("orderNo", order.getThirdPartyOrderNo());
|
||||||
|
response.put("success", true);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
JSONObject updateRangeRequest = new JSONObject();
|
||||||
|
updateRangeRequest.put("sheetId", sheetId);
|
||||||
|
|
||||||
|
JSONObject gridData = new JSONObject();
|
||||||
|
gridData.put("startRow", rowIndex);
|
||||||
|
gridData.put("startColumn", columnIndex);
|
||||||
|
|
||||||
|
JSONArray rows = new JSONArray();
|
||||||
|
JSONObject rowData = new JSONObject();
|
||||||
|
JSONArray cellValues = new JSONArray();
|
||||||
|
|
||||||
|
JSONObject cellData = new JSONObject();
|
||||||
|
JSONObject cellValue = new JSONObject();
|
||||||
|
|
||||||
|
if (isLink) {
|
||||||
|
JSONObject link = new JSONObject();
|
||||||
|
link.put("url", value);
|
||||||
|
link.put("text", value);
|
||||||
|
cellValue.put("link", link);
|
||||||
|
} else {
|
||||||
|
cellValue.put("text", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
cellData.put("cellValue", cellValue);
|
||||||
|
cellValues.add(cellData);
|
||||||
|
|
||||||
|
rowData.put("values", cellValues);
|
||||||
|
rows.add(rowData);
|
||||||
|
gridData.put("rows", rows);
|
||||||
|
|
||||||
|
updateRangeRequest.put("gridData", gridData);
|
||||||
|
|
||||||
|
JSONObject request = new JSONObject();
|
||||||
|
request.put("updateRangeRequest", updateRangeRequest);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user