1
This commit is contained in:
301
doc/操作日志功能-快速上手.md
Normal file
301
doc/操作日志功能-快速上手.md
Normal file
@@ -0,0 +1,301 @@
|
||||
# 操作日志查看功能 - 快速上手指南
|
||||
|
||||
## 🚀 快速部署
|
||||
|
||||
### 1️⃣ 重新编译前端
|
||||
|
||||
```bash
|
||||
cd d:\code\ruoyi-vue
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
或者开发模式:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### 2️⃣ 重新编译后端(如果还没编译)
|
||||
|
||||
```bash
|
||||
cd d:\code\RuoYi-Vue-master\ruoyi-java
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
### 3️⃣ 重启服务
|
||||
|
||||
重启前端和后端服务。
|
||||
|
||||
### 4️⃣ 清除浏览器缓存
|
||||
|
||||
按 `Ctrl + F5` 强制刷新页面。
|
||||
|
||||
---
|
||||
|
||||
## 📍 如何打开日志页面
|
||||
|
||||
### 方法:从配置对话框打开
|
||||
|
||||
1. 打开**订单列表**页面
|
||||
|
||||
2. 点击顶部的 **"H-TF自动写入配置"** 按钮(绿色)
|
||||
|
||||
3. 在弹出的配置对话框底部,找到 **"查看操作日志"** 按钮(蓝色,带文档图标)
|
||||
|
||||
4. 点击后即可查看操作日志
|
||||
|
||||
---
|
||||
|
||||
## 📊 功能演示
|
||||
|
||||
### 界面布局
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 腾讯文档操作日志 [X] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 搜索框: [订单号] [操作类型▼] [操作状态▼] [搜索] [重置] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │
|
||||
│ │ 成功 │ │ 跳过 │ │ 失败 │ │ 总计 │ │
|
||||
│ │ 150 │ │ 500 │ │ 10 │ │ 660 │ │
|
||||
│ └───────┘ └───────┘ └───────┘ └───────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 序号 | 操作类型 | 订单号 | 行号 | 物流链接 | 状态 | 时间 │
|
||||
│ ────┼──────────┼────────┼──────┼──────────┼──────┼──────── │
|
||||
│ 1 | 批量同步 | JY123 | 2575 | https... | 成功 | 22:03:30 │
|
||||
│ 2 | 批量同步 | JY124 | 2576 | https... | 跳过 | 22:03:31 │
|
||||
│ 3 | 批量同步 | JY125 | 2577 | https... | 失败 | 22:03:32 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 总计 660 条 [10▼] [<] [1] [2] [3] ... [66] [>] │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ [关闭] [刷新] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 使用场景
|
||||
|
||||
### 场景1:查看今天的同步情况
|
||||
|
||||
1. 打开日志页面
|
||||
2. 查看顶部统计卡片
|
||||
3. 成功数 = 今天成功同步的订单数
|
||||
4. 跳过数 = 今天跳过的订单数(如已有数据)
|
||||
5. 失败数 = 今天失败的订单数
|
||||
|
||||
### 场景2:查找为什么某个订单没有同步
|
||||
|
||||
1. 在"订单号"输入框输入订单号,例如:`JY202511061595`
|
||||
2. 点击"搜索"
|
||||
3. 查看该订单的操作记录:
|
||||
- **成功** ✅ - 已经同步
|
||||
- **跳过** ⚠️ - 被跳过(查看原因)
|
||||
- **失败** ❌ - 同步失败(查看错误信息)
|
||||
- **无记录** - 没有尝试同步该订单
|
||||
|
||||
### 场景3:查看所有失败的订单
|
||||
|
||||
1. 在"操作状态"下拉框选择"失败"
|
||||
2. 点击"搜索"
|
||||
3. 查看所有失败记录的"错误信息"列
|
||||
4. 根据错误信息进行处理:
|
||||
- "未找到订单" → 检查订单是否存在
|
||||
- "订单物流链接为空" → 补充物流信息
|
||||
- "API调用失败" → 检查网络或API
|
||||
|
||||
### 场景4:检查某个订单是否重复推送
|
||||
|
||||
1. 在"订单号"输入框输入订单号
|
||||
2. 点击"搜索"
|
||||
3. 查看记录数量:
|
||||
- 只有1条"成功"记录 ✅ - 正常
|
||||
- 有多条"成功"记录 ❌ - 可能重复推送
|
||||
- 有"跳过"记录 ✅ - 防重机制生效
|
||||
|
||||
---
|
||||
|
||||
## 💡 快速技巧
|
||||
|
||||
### 技巧1:快速刷新
|
||||
|
||||
点击底部的 **"刷新"** 按钮即可重新加载最新数据。
|
||||
|
||||
### 技巧2:查看物流链接
|
||||
|
||||
点击"物流链接"列的链接,会在新标签页打开物流链接。
|
||||
|
||||
### 技巧3:分页查看
|
||||
|
||||
- 默认每页显示20条
|
||||
- 可以选择10/20/50/100条每页
|
||||
- 使用页码快速跳转
|
||||
|
||||
### 技巧4:重置筛选
|
||||
|
||||
点击 **"重置"** 按钮清除所有搜索条件,显示所有日志。
|
||||
|
||||
---
|
||||
|
||||
## 🎯 数据解读
|
||||
|
||||
### 操作类型
|
||||
|
||||
- **批量同步**:通过"批量同步物流"按钮触发的同步
|
||||
- **单个写入**:单个订单的写入操作(如果有)
|
||||
|
||||
### 操作状态
|
||||
|
||||
- **成功** (绿色):
|
||||
- 物流链接已写入腾讯文档
|
||||
- 订单推送状态已更新为"已推送"
|
||||
- 操作完全成功
|
||||
|
||||
- **跳过** (橙色):
|
||||
- 订单已推送(数据库标记为已推送)
|
||||
- 腾讯文档中该行已有物流链接
|
||||
- 分布式锁获取失败(其他请求正在处理)
|
||||
- 这是**正常现象**,防止重复推送
|
||||
|
||||
- **失败** (红色):
|
||||
- 未找到订单
|
||||
- 订单物流链接为空
|
||||
- 腾讯文档API调用失败
|
||||
- 其他异常
|
||||
- 需要**人工处理**
|
||||
|
||||
### 统计数字含义
|
||||
|
||||
假设统计卡片显示:
|
||||
```
|
||||
成功: 150 跳过: 500 失败: 10 总计: 660
|
||||
```
|
||||
|
||||
解读:
|
||||
- 今天尝试同步了660个订单
|
||||
- 成功同步150个(22.7%)
|
||||
- 跳过500个(75.8%)- 这些订单可能已经同步过了
|
||||
- 失败10个(1.5%)- 需要检查这些订单
|
||||
|
||||
**正常情况下:**
|
||||
- 首次同步:成功比例较高(60-80%)
|
||||
- 二次同步:跳过比例较高(80-95%)
|
||||
- 失败比例:应该很低(<5%)
|
||||
|
||||
---
|
||||
|
||||
## 🔧 故障排查
|
||||
|
||||
### 问题1:看不到日志
|
||||
|
||||
**检查步骤:**
|
||||
1. 是否已经执行过批量同步?
|
||||
2. 后端是否正常运行?
|
||||
3. 数据库表 `tencent_doc_operation_log` 是否有数据?
|
||||
|
||||
**验证SQL:**
|
||||
```sql
|
||||
SELECT COUNT(*) FROM tencent_doc_operation_log;
|
||||
```
|
||||
|
||||
### 问题2:日志不完整
|
||||
|
||||
**可能原因:**
|
||||
- 后端日志记录失败
|
||||
- 数据库连接异常
|
||||
|
||||
**检查方法:**
|
||||
查看后端日志中是否有 "记录操作日志失败" 的错误。
|
||||
|
||||
### 问题3:"查看操作日志"按钮点击无反应
|
||||
|
||||
**解决方法:**
|
||||
1. 按 F12 打开浏览器控制台
|
||||
2. 查看是否有JavaScript错误
|
||||
3. 清除浏览器缓存后重试
|
||||
4. 确保前端已重新编译
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据库直接查询(备用方案)
|
||||
|
||||
如果前端页面有问题,可以直接查询数据库:
|
||||
|
||||
### 查看最近50条日志
|
||||
```sql
|
||||
SELECT
|
||||
id,
|
||||
operation_type AS 操作类型,
|
||||
order_no AS 订单号,
|
||||
target_row AS 目标行,
|
||||
operation_status AS 状态,
|
||||
error_message AS 错误信息,
|
||||
operator AS 操作人,
|
||||
create_time AS 时间
|
||||
FROM tencent_doc_operation_log
|
||||
WHERE file_id = 'DTUFydU9FTkRLbEN6' -- 替换为您的fileId
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 50;
|
||||
```
|
||||
|
||||
### 查看今天的统计
|
||||
```sql
|
||||
SELECT
|
||||
operation_status AS 状态,
|
||||
COUNT(*) AS 数量
|
||||
FROM tencent_doc_operation_log
|
||||
WHERE file_id = 'DTUFydU9FTkRLbEN6'
|
||||
AND DATE(create_time) = CURDATE()
|
||||
GROUP BY operation_status;
|
||||
```
|
||||
|
||||
### 查找某个订单的记录
|
||||
```sql
|
||||
SELECT *
|
||||
FROM tencent_doc_operation_log
|
||||
WHERE order_no = 'JY202511061595'
|
||||
ORDER BY create_time DESC;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 使用效果
|
||||
|
||||
使用日志查看功能后,您可以:
|
||||
|
||||
✅ **实时监控**:随时查看同步状态
|
||||
✅ **快速定位**:找出问题订单
|
||||
✅ **追溯历史**:查看操作记录
|
||||
✅ **错误诊断**:分析失败原因
|
||||
✅ **效率统计**:评估同步效率
|
||||
|
||||
---
|
||||
|
||||
## 📱 界面按钮位置
|
||||
|
||||
```
|
||||
订单列表页面
|
||||
↓
|
||||
顶部操作栏
|
||||
↓
|
||||
[搜索] [重置] [导出] [H-TF自动写入配置] [批量同步物流]
|
||||
↓
|
||||
配置对话框
|
||||
↓
|
||||
底部操作按钮
|
||||
↓
|
||||
[查看操作日志] [测试配置] [清除配置] [取消] [保存配置]
|
||||
↓
|
||||
日志查看页面 ✨
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**完成!** 🎊
|
||||
|
||||
如有问题,请查看:
|
||||
- `操作日志查看功能说明.md` - 完整功能文档
|
||||
- `如何查看同步进度和操作日志.md` - 技术细节
|
||||
|
||||
祝使用愉快! 😊
|
||||
|
||||
251
doc/操作日志查看功能说明.md
Normal file
251
doc/操作日志查看功能说明.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# 腾讯文档操作日志查看功能说明
|
||||
|
||||
## 📊 功能概览
|
||||
|
||||
新增了一个**操作日志查看页面**,可以方便地查看所有腾讯文档的同步操作记录,包括成功、失败、跳过的记录。
|
||||
|
||||
## 🎯 功能特性
|
||||
|
||||
### 1. **可视化统计卡片**
|
||||
- ✅ 成功数量(绿色)
|
||||
- ⚠️ 跳过数量(橙色)
|
||||
- ❌ 失败数量(红色)
|
||||
- 📊 总计数量(蓝色)
|
||||
|
||||
### 2. **强大的搜索功能**
|
||||
- 按订单号搜索
|
||||
- 按操作类型筛选(批量同步/单个写入)
|
||||
- 按操作状态筛选(成功/失败/跳过)
|
||||
|
||||
### 3. **详细的日志展示**
|
||||
- 操作类型(带标签)
|
||||
- 订单号
|
||||
- 目标行号
|
||||
- 物流链接(可点击)
|
||||
- 操作状态(带标签)
|
||||
- 错误信息
|
||||
- 操作人
|
||||
- 操作时间
|
||||
|
||||
### 4. **分页功能**
|
||||
- 支持10/20/50/100条每页
|
||||
- 总计显示
|
||||
- 页码跳转
|
||||
|
||||
## 📍 如何使用
|
||||
|
||||
### 方法1:从配置页面打开(推荐)
|
||||
|
||||
1. 打开订单列表页面
|
||||
2. 点击 **"H-TF自动写入配置"** 按钮
|
||||
3. 在配置对话框底部,点击 **"查看操作日志"** 按钮(蓝色)
|
||||
4. 即可查看当前文档的所有操作日志
|
||||
|
||||
### 方法2:直接在列表页面添加按钮(可选)
|
||||
|
||||
如果需要,也可以在订单列表页面添加一个独立的"查看日志"按钮。
|
||||
|
||||
## 🔍 日志搜索示例
|
||||
|
||||
### 示例1:查看某个订单的操作记录
|
||||
|
||||
1. 在"订单号"输入框输入:`JY202511061595`
|
||||
2. 点击"搜索"
|
||||
3. 查看该订单的所有操作历史
|
||||
|
||||
### 示例2:查看今天失败的操作
|
||||
|
||||
1. 在"操作状态"下拉框选择:`失败`
|
||||
2. 点击"搜索"
|
||||
3. 查看所有失败的记录和错误信息
|
||||
|
||||
### 示例3:查看批量同步的记录
|
||||
|
||||
1. 在"操作类型"下拉框选择:`批量同步`
|
||||
2. 点击"搜索"
|
||||
3. 查看所有批量同步的操作
|
||||
|
||||
## 📊 统计卡片说明
|
||||
|
||||
页面顶部的统计卡片会**实时计算**当前筛选条件下的数据:
|
||||
|
||||
- **成功**:操作成功完成的数量
|
||||
- **跳过**:因为各种原因跳过的数量(如已有数据、已推送等)
|
||||
- **失败**:操作失败的数量
|
||||
- **总计**:所有记录的总数
|
||||
|
||||
## 🎨 界面截图说明
|
||||
|
||||
### 统计卡片区域
|
||||
```
|
||||
┌─────────────┬─────────────┬─────────────┬─────────────┐
|
||||
│ 成功 │ 跳过 │ 失败 │ 总计 │
|
||||
│ 150 │ 500 │ 10 │ 660 │
|
||||
│ (绿色) │ (橙色) │ (红色) │ (蓝色) │
|
||||
└─────────────┴─────────────┴─────────────┴─────────────┘
|
||||
```
|
||||
|
||||
### 日志表格
|
||||
```
|
||||
序号 | 操作类型 | 订单号 | 目标行 | 物流链接 | 状态 | 错误信息 | 操作人 | 操作时间
|
||||
-----|----------|--------|--------|----------|------|----------|--------|----------
|
||||
1 | 批量同步 | JY123 | 2575 | https... | 成功 | - | admin | 22:03:30
|
||||
2 | 批量同步 | JY124 | 2576 | https... | 跳过 | 已有数据 | admin | 22:03:30
|
||||
```
|
||||
|
||||
## 🔧 技术实现
|
||||
|
||||
### 后端接口
|
||||
|
||||
**1. 查询操作日志列表**
|
||||
```
|
||||
GET /jarvis-api/jarvis/tendoc/operationLogs
|
||||
参数:
|
||||
- fileId: 文件ID(可选)
|
||||
- sheetId: 工作表ID(可选)
|
||||
- orderNo: 订单号(可选)
|
||||
- operationType: 操作类型(可选)
|
||||
- operationStatus: 操作状态(可选)
|
||||
```
|
||||
|
||||
**2. 查询最近的操作日志**
|
||||
```
|
||||
GET /jarvis-api/jarvis/tendoc/recentLogs
|
||||
参数:
|
||||
- fileId: 文件ID(可选)
|
||||
- limit: 限制数量(默认50)
|
||||
```
|
||||
|
||||
### 前端组件
|
||||
|
||||
- **组件位置**:`src/views/system/jdorder/components/TencentDocOperationLogs.vue`
|
||||
- **组件名称**:`TencentDocOperationLogs`
|
||||
- **依赖API**:`@/api/jarvis/tendoc.js`
|
||||
|
||||
## 📝 操作状态说明
|
||||
|
||||
### SUCCESS(成功)
|
||||
- 物流链接成功写入腾讯文档
|
||||
- 订单状态已更新
|
||||
- 操作日志已记录
|
||||
|
||||
### FAILED(失败)
|
||||
可能的原因:
|
||||
- 未找到订单
|
||||
- 订单物流链接为空
|
||||
- API调用失败
|
||||
- 写入异常
|
||||
|
||||
### SKIPPED(跳过)
|
||||
可能的原因:
|
||||
- 订单已推送(`tencent_doc_pushed = 1`)
|
||||
- 腾讯文档中该行已有物流链接
|
||||
- 分布式锁获取失败
|
||||
|
||||
## 🚀 性能优化建议
|
||||
|
||||
1. **定期清理历史日志**
|
||||
```sql
|
||||
-- 清理30天前的日志
|
||||
DELETE FROM tencent_doc_operation_log
|
||||
WHERE create_time < DATE_SUB(NOW(), INTERVAL 30 DAY);
|
||||
```
|
||||
|
||||
2. **添加索引优化查询**
|
||||
```sql
|
||||
-- 已创建的索引
|
||||
CREATE INDEX idx_file_id ON tencent_doc_operation_log(file_id);
|
||||
CREATE INDEX idx_order_no ON tencent_doc_operation_log(order_no);
|
||||
CREATE INDEX idx_create_time ON tencent_doc_operation_log(create_time);
|
||||
```
|
||||
|
||||
## 🔒 权限控制
|
||||
|
||||
目前日志查看功能没有单独的权限控制,与腾讯文档配置功能共用权限。
|
||||
|
||||
如需单独控制,可以:
|
||||
1. 在后端Controller添加权限注解
|
||||
2. 在前端路由配置中添加权限判断
|
||||
|
||||
## 📱 响应式设计
|
||||
|
||||
日志查看对话框支持响应式设计:
|
||||
- 宽度:90%(自适应屏幕)
|
||||
- 表格:最大高度500px,自动滚动
|
||||
- 分页:右对齐,自适应
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q1: 为什么看不到日志?
|
||||
|
||||
**A:** 可能原因:
|
||||
1. 还没有执行过批量同步
|
||||
2. fileId或sheetId参数不正确
|
||||
3. 后端接口异常
|
||||
|
||||
**解决方法:**
|
||||
- 先执行一次批量同步
|
||||
- 检查后端日志是否有错误
|
||||
- 检查数据库表 `tencent_doc_operation_log` 是否有数据
|
||||
|
||||
### Q2: 统计数字不准确?
|
||||
|
||||
**A:** 统计是基于**当前筛选条件**计算的,不是所有数据的统计。
|
||||
|
||||
例如:
|
||||
- 如果筛选了"失败"状态,统计卡片只会统计失败的记录
|
||||
- 重置筛选条件后,统计会更新
|
||||
|
||||
### Q3: 能否导出日志?
|
||||
|
||||
**A:** 当前版本不支持导出,但可以直接从数据库导出:
|
||||
|
||||
```sql
|
||||
-- 导出CSV格式
|
||||
SELECT
|
||||
operation_type,
|
||||
order_no,
|
||||
target_row,
|
||||
logistics_link,
|
||||
operation_status,
|
||||
error_message,
|
||||
operator,
|
||||
create_time
|
||||
INTO OUTFILE '/tmp/tendoc_logs.csv'
|
||||
FIELDS TERMINATED BY ','
|
||||
ENCLOSED BY '"'
|
||||
LINES TERMINATED BY '\n'
|
||||
FROM tencent_doc_operation_log
|
||||
WHERE file_id = 'DTUFydU9FTkRLbEN6'
|
||||
ORDER BY create_time DESC;
|
||||
```
|
||||
|
||||
### Q4: 如何清空所有日志?
|
||||
|
||||
**A:** 谨慎操作!执行以下SQL:
|
||||
|
||||
```sql
|
||||
-- 清空指定文档的日志
|
||||
DELETE FROM tencent_doc_operation_log
|
||||
WHERE file_id = 'DTUFydU9FTkRLbEN6';
|
||||
|
||||
-- 清空所有日志(慎用!)
|
||||
TRUNCATE TABLE tencent_doc_operation_log;
|
||||
```
|
||||
|
||||
## 🎉 使用效果
|
||||
|
||||
使用操作日志功能后,您可以:
|
||||
|
||||
1. ✅ **实时监控**同步状态
|
||||
2. ✅ **快速定位**问题订单
|
||||
3. ✅ **追溯历史**操作记录
|
||||
4. ✅ **统计分析**同步效率
|
||||
5. ✅ **错误诊断**失败原因
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2025-11-06 22:50
|
||||
**版本**: v1.0
|
||||
**作者**: AI Assistant
|
||||
|
||||
@@ -158,3 +158,21 @@ export function getDocSheetList(fileId) {
|
||||
})
|
||||
}
|
||||
|
||||
// 查询操作日志列表
|
||||
export function getOperationLogs(params) {
|
||||
return request({
|
||||
url: '/jarvis/tendoc/operationLogs',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询最近的操作日志
|
||||
export function getRecentLogs(params) {
|
||||
return request({
|
||||
url: '/jarvis/tendoc/recentLogs',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="商品类型" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="(scope.row.owner === 'g' || (!scope.row.popId && scope.row.owner !== 'pop')) ? 'success' : 'warning'">
|
||||
{{ (scope.row.owner === 'g' || (!scope.row.popId && scope.row.owner !== 'pop')) ? '自营' : 'POP' }}
|
||||
<el-tag :type="(scope.row.owner === 'g' || scope.row.owner === 'G') ? 'success' : 'warning'">
|
||||
{{ (scope.row.owner === 'g' || scope.row.owner === 'G') ? '自营' : 'POP' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -88,14 +88,14 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="佣金比例" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.commissionShare || scope.row.commission">{{ (scope.row.commissionShare || scope.row.commission) }}%</span>
|
||||
<span v-if="scope.row.commissionShare">{{ scope.row.commissionShare }}%</span>
|
||||
<span v-else style="color: #909399;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="佣金金额" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.commission">
|
||||
¥{{ formatCommissionAmount(scope.row.commission, scope.row.price) }}
|
||||
¥{{ formatPrice(scope.row.commission) }}
|
||||
</span>
|
||||
<span v-else style="color: #909399;">-</span>
|
||||
</template>
|
||||
@@ -126,8 +126,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="(scope.row.owner === 'g' || (!scope.row.popId && scope.row.owner !== 'pop')) ? 'success' : 'warning'">
|
||||
{{ (scope.row.owner === 'g' || (!scope.row.popId && scope.row.owner !== 'pop')) ? '自营' : 'POP' }}
|
||||
<el-tag :type="(scope.row.owner === 'g' || scope.row.owner === 'G') ? 'success' : 'warning'">
|
||||
{{ (scope.row.owner === 'g' || scope.row.owner === 'G') ? '自营' : 'POP' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -413,8 +413,9 @@ export default {
|
||||
this.form.selectedProduct = product
|
||||
this.form.queryResult = product
|
||||
this.form.skuName = product.skuName || product.title || product.productName || product.cleanSkuName || ''
|
||||
const ownerValue = product.owner || (product.popId ? 'pop' : 'g') || 'g'
|
||||
this.form.owner = ownerValue === 'p' ? 'pop' : (ownerValue === 'pop' ? 'pop' : 'g')
|
||||
const ownerValue = product.owner || 'g'
|
||||
// owner: 'g'/'G' = 自营, 'p'/'pop' = POP
|
||||
this.form.owner = (ownerValue === 'g' || ownerValue === 'G') ? 'g' : 'pop'
|
||||
|
||||
this.$modal.msgSuccess('已选择商品:' + this.form.skuName + '(' + (this.form.owner === 'g' ? '自营' : 'POP') + ')')
|
||||
},
|
||||
@@ -491,8 +492,9 @@ export default {
|
||||
this.form.selectedProduct = selectedProduct
|
||||
this.form.queryResult = selectedProduct
|
||||
this.form.skuName = selectedProduct.skuName || selectedProduct.title || selectedProduct.productName || selectedProduct.cleanSkuName || ''
|
||||
const ownerValue = selectedProduct.owner || (selectedProduct.popId ? 'pop' : 'g') || 'g'
|
||||
this.form.owner = ownerValue === 'p' ? 'pop' : (ownerValue === 'pop' ? 'pop' : 'g')
|
||||
const ownerValue = selectedProduct.owner || 'g'
|
||||
// owner: 'g'/'G' = 自营, 'p'/'pop' = POP
|
||||
this.form.owner = (ownerValue === 'g' || ownerValue === 'G') ? 'g' : 'pop'
|
||||
|
||||
// 调用批量创建和替换
|
||||
await this.handleReplace()
|
||||
@@ -509,8 +511,10 @@ export default {
|
||||
return Number(price).toFixed(2)
|
||||
},
|
||||
|
||||
/** 格式化佣金金额 */
|
||||
/** 格式化佣金金额(已废弃:commission字段本身就是佣金金额,不需要计算) */
|
||||
formatCommissionAmount(commission, price) {
|
||||
// 已废弃:commission 字段已经是佣金金额(如 86.67),不是百分比
|
||||
// 直接使用 formatPrice(scope.row.commission) 即可
|
||||
if (!commission || !price) return '0.00'
|
||||
// commission可能是百分比字符串或数值
|
||||
let commissionPercent = 0
|
||||
|
||||
@@ -170,6 +170,9 @@
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div slot="footer">
|
||||
<el-button @click="showOperationLogs = true" icon="el-icon-document" type="info" plain>
|
||||
查看操作日志
|
||||
</el-button>
|
||||
<el-button @click="handleTest" :loading="testLoading" icon="el-icon-setting">
|
||||
测试配置
|
||||
</el-button>
|
||||
@@ -181,6 +184,13 @@
|
||||
保存配置
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 操作日志查看对话框 -->
|
||||
<tencent-doc-operation-logs
|
||||
v-model="showOperationLogs"
|
||||
:file-id="form.fileId"
|
||||
:sheet-id="form.sheetId"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
@@ -193,9 +203,13 @@ import {
|
||||
getDocSheetList,
|
||||
getTencentDocAuthUrl
|
||||
} from '@/api/jarvis/tendoc'
|
||||
import TencentDocOperationLogs from './TencentDocOperationLogs'
|
||||
|
||||
export default {
|
||||
name: 'TencentDocAutoWriteConfig',
|
||||
components: {
|
||||
TencentDocOperationLogs
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
@@ -204,6 +218,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showOperationLogs: false,
|
||||
visible: false,
|
||||
config: {
|
||||
hasAccessToken: false,
|
||||
|
||||
304
src/views/system/jdorder/components/TencentDocOperationLogs.vue
Normal file
304
src/views/system/jdorder/components/TencentDocOperationLogs.vue
Normal file
@@ -0,0 +1,304 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="腾讯文档操作日志"
|
||||
:visible.sync="visible"
|
||||
width="90%"
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<!-- 搜索条件 -->
|
||||
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="80px">
|
||||
<el-form-item label="订单号">
|
||||
<el-input
|
||||
v-model="queryParams.orderNo"
|
||||
placeholder="请输入订单号"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 200px"
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作类型">
|
||||
<el-select v-model="queryParams.operationType" placeholder="请选择" clearable size="small" style="width: 150px">
|
||||
<el-option label="批量同步" value="BATCH_SYNC" />
|
||||
<el-option label="单个写入" value="WRITE_SINGLE" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作状态">
|
||||
<el-select v-model="queryParams.operationStatus" placeholder="请选择" clearable size="small" style="width: 150px">
|
||||
<el-option label="成功" value="SUCCESS" />
|
||||
<el-option label="失败" value="FAILED" />
|
||||
<el-option label="跳过" value="SKIPPED" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="small" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="small" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 统计信息卡片 -->
|
||||
<el-row :gutter="20" style="margin-bottom: 20px">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 24px; color: #67C23A; font-weight: bold">{{ statistics.success }}</div>
|
||||
<div style="color: #909399; margin-top: 8px">成功</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 24px; color: #E6A23C; font-weight: bold">{{ statistics.skipped }}</div>
|
||||
<div style="color: #909399; margin-top: 8px">跳过</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 24px; color: #F56C6C; font-weight: bold">{{ statistics.failed }}</div>
|
||||
<div style="color: #909399; margin-top: 8px">失败</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div style="text-align: center">
|
||||
<div style="font-size: 24px; color: #409EFF; font-weight: bold">{{ statistics.total }}</div>
|
||||
<div style="color: #909399; margin-top: 8px">总计</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 日志表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="logList"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
max-height="500"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||
|
||||
<el-table-column label="操作类型" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.operationType === 'BATCH_SYNC'" type="primary" size="small">批量同步</el-tag>
|
||||
<el-tag v-else-if="scope.row.operationType === 'WRITE_SINGLE'" type="success" size="small">单个写入</el-tag>
|
||||
<el-tag v-else size="small">{{ scope.row.operationType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="订单号" prop="orderNo" width="180" />
|
||||
|
||||
<el-table-column label="目标行" prop="targetRow" width="80" align="center" />
|
||||
|
||||
<el-table-column label="物流链接" prop="logisticsLink" min-width="200" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<a v-if="scope.row.logisticsLink" :href="scope.row.logisticsLink" target="_blank" style="color: #409EFF">
|
||||
{{ scope.row.logisticsLink }}
|
||||
</a>
|
||||
<span v-else style="color: #C0C4CC">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作状态" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.operationStatus === 'SUCCESS'" type="success" size="small">成功</el-tag>
|
||||
<el-tag v-else-if="scope.row.operationStatus === 'FAILED'" type="danger" size="small">失败</el-tag>
|
||||
<el-tag v-else-if="scope.row.operationStatus === 'SKIPPED'" type="warning" size="small">跳过</el-tag>
|
||||
<el-tag v-else type="info" size="small">{{ scope.row.operationStatus }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="错误信息" prop="errorMessage" min-width="200" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.errorMessage" style="color: #F56C6C">{{ scope.row.errorMessage }}</span>
|
||||
<span v-else style="color: #C0C4CC">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作人" prop="operator" width="100" align="center" />
|
||||
|
||||
<el-table-column label="操作时间" prop="createTime" width="160" align="center" />
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div style="text-align: right; margin-top: 20px">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="queryParams.pageNum"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="queryParams.pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
>
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
<el-button type="primary" icon="el-icon-refresh" @click="handleQuery">刷新</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getOperationLogs } from '@/api/jarvis/tendoc'
|
||||
|
||||
export default {
|
||||
name: 'TencentDocOperationLogs',
|
||||
props: {
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fileId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
sheetId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
logList: [],
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
fileId: '',
|
||||
sheetId: '',
|
||||
orderNo: '',
|
||||
operationType: '',
|
||||
operationStatus: ''
|
||||
},
|
||||
statistics: {
|
||||
success: 0,
|
||||
failed: 0,
|
||||
skipped: 0,
|
||||
total: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
visible: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (val) {
|
||||
this.initData()
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
this.queryParams.fileId = this.fileId
|
||||
this.queryParams.sheetId = this.sheetId
|
||||
},
|
||||
|
||||
/** 查询日志列表 */
|
||||
async getList() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getOperationLogs(this.queryParams)
|
||||
if (res.code === 200) {
|
||||
this.logList = res.data || []
|
||||
this.total = this.logList.length
|
||||
this.calculateStatistics()
|
||||
} else {
|
||||
this.$message.error(res.msg || '查询失败')
|
||||
}
|
||||
} catch (e) {
|
||||
this.$message.error('查询失败: ' + (e.message || '未知错误'))
|
||||
console.error('查询操作日志失败', e)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
/** 计算统计数据 */
|
||||
calculateStatistics() {
|
||||
this.statistics = {
|
||||
success: 0,
|
||||
failed: 0,
|
||||
skipped: 0,
|
||||
total: this.logList.length
|
||||
}
|
||||
|
||||
this.logList.forEach(log => {
|
||||
if (log.operationStatus === 'SUCCESS') {
|
||||
this.statistics.success++
|
||||
} else if (log.operationStatus === 'FAILED') {
|
||||
this.statistics.failed++
|
||||
} else if (log.operationStatus === 'SKIPPED') {
|
||||
this.statistics.skipped++
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
fileId: this.fileId,
|
||||
sheetId: this.sheetId,
|
||||
orderNo: '',
|
||||
operationType: '',
|
||||
operationStatus: ''
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
|
||||
/** 分页 */
|
||||
handleSizeChange(val) {
|
||||
this.queryParams.pageSize = val
|
||||
this.getList()
|
||||
},
|
||||
|
||||
handleCurrentChange(val) {
|
||||
this.queryParams.pageNum = val
|
||||
this.getList()
|
||||
},
|
||||
|
||||
/** 关闭对话框 */
|
||||
handleClose() {
|
||||
this.visible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-card {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.el-card:hover {
|
||||
transform: translateY(-2px);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user