+
+ 微信发货/确认收货同步日志
+ 记录向微信平台同步的操作结果,供排查与手动重试
+
+
+
+
+
记录ID:
+
订单号:
+
同步类型:
+
同步状态:
+
发货模式:
+
重试次数:
+
错误信息:
+
创建时间:
+
更新时间:
+
请求内容:
+
+
响应内容:
+
+
+
diff --git a/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/sync.js b/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/sync.js
index 60d37d1..b772d75 100644
--- a/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/sync.js
+++ b/addons/shopro_wechat_trade/public/assets/js/backend/shopro_wechat_trade/sync.js
@@ -1,4 +1,84 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+ var SYNC_TYPE_MAP = {
+ shipping: '发货同步',
+ confirm: '确认收货同步'
+ };
+
+ var DELIVERY_MODE_MAP = {
+ 1: '统一发货',
+ 2: '分拆发货'
+ };
+
+ function escapeHtml(text) {
+ return $('
').text(text == null ? '' : text).html();
+ }
+
+ function formatSyncType(value) {
+ var text = SYNC_TYPE_MAP[value] || value || '-';
+ if (value === 'shipping') {
+ return '
' + text + '';
+ }
+ if (value === 'confirm') {
+ return '
' + text + '';
+ }
+ return text;
+ }
+
+ function formatStatus(row) {
+ var status = row.status;
+ var retryCount = parseInt(row.retry_count, 10) || 0;
+ if (status === 'success') {
+ return '
成功';
+ }
+ if (status === 'failed') {
+ return '
失败';
+ }
+ if (status === 'pending') {
+ if (retryCount > 0) {
+ return '
待重试';
+ }
+ return '
处理中';
+ }
+ return status || '-';
+ }
+
+ function formatDeliveryMode(value, row) {
+ if (row.sync_type !== 'shipping') {
+ return '
-';
+ }
+ var text = DELIVERY_MODE_MAP[value] || ('模式' + value);
+ return text;
+ }
+
+ function formatErrorInfo(value, row) {
+ if (row.status === 'success') {
+ return '
-';
+ }
+ var parts = [];
+ if (row.errcode !== null && row.errcode !== undefined && row.errcode !== '') {
+ parts.push('[' + row.errcode + ']');
+ }
+ if (row.errmsg) {
+ parts.push(row.errmsg);
+ }
+ return parts.length ? escapeHtml(parts.join(' ')) : '
-';
+ }
+
+ function formatJsonText(raw) {
+ if (!raw) {
+ return '(无)';
+ }
+ try {
+ return JSON.stringify(JSON.parse(raw), null, 2);
+ } catch (e) {
+ return raw;
+ }
+ }
+
+ function formatDatetime(value) {
+ return value ? Table.api.formatter.datetime(value) : '-';
+ }
+
var Controller = {
index: function () {
Table.api.init({
@@ -9,55 +89,186 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
});
var table = $("#table");
+
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
sortOrder: 'desc',
+ search: false,
+ commonSearch: false,
+ showExport: false,
queryParams: function (params) {
params.status = $('#status-filter').val();
+ params.sync_type = $('#type-filter').val();
+ params.order_sn = $.trim($('#order-sn-filter').val());
return params;
},
columns: [
- { field: 'id', title: 'ID' },
- { field: 'order_sn', title: '订单号' },
- { field: 'sync_type', title: '类型' },
- { field: 'status', title: '状态' },
- { field: 'delivery_mode', title: '发货模式' },
- { field: 'errcode', title: 'errcode' },
- { field: 'errmsg', title: 'errmsg' },
- { field: 'retry_count', title: '重试次数' },
+ { field: 'id', title: 'ID', width: 70 },
+ {
+ field: 'order_sn',
+ title: '订单号',
+ formatter: function (value, row) {
+ if (!value) {
+ return '-';
+ }
+ if (row.order_id) {
+ return '
' + escapeHtml(value) + '';
+ }
+ return escapeHtml(value);
+ }
+ },
+ {
+ field: 'sync_type',
+ title: '同步类型',
+ formatter: function (value) {
+ return formatSyncType(value);
+ }
+ },
+ {
+ field: 'status',
+ title: '同步状态',
+ formatter: function (value, row) {
+ return formatStatus(row);
+ }
+ },
+ {
+ field: 'delivery_mode',
+ title: '发货模式',
+ formatter: function (value, row) {
+ return formatDeliveryMode(value, row);
+ }
+ },
+ {
+ field: 'errmsg',
+ title: '错误信息',
+ formatter: function (value, row) {
+ return formatErrorInfo(value, row);
+ }
+ },
+ {
+ field: 'retry_count',
+ title: '重试次数',
+ width: 90,
+ formatter: function (value, row) {
+ if (row.status === 'success') {
+ return '
-';
+ }
+ return value || 0;
+ }
+ },
{
field: 'createtime',
title: '创建时间',
- formatter: function (value) {
- return value ? Table.api.formatter.datetime(value) : '';
- }
+ formatter: formatDatetime
},
{
field: 'operate',
title: '操作',
+ width: 140,
table: table,
events: Table.api.events.operate,
formatter: function (value, row) {
- if (row.status === 'success') {
- return '-';
+ var html = [];
+ html.push('
详情');
+ if (row.status !== 'success') {
+ html.push('
重试');
}
- return '
重试';
+ return html.join('');
}
}
]
});
- $('#status-filter').on('change', function () {
+ function refreshTable() {
table.bootstrapTable('refresh');
+ }
+
+ $('#status-filter, #type-filter').on('change', refreshTable);
+
+ $('.btn-search').on('click', refreshTable);
+
+ $('#order-sn-filter').on('keypress', function (e) {
+ if (e.which === 13) {
+ refreshTable();
+ }
+ });
+
+ $('.btn-reset').on('click', function () {
+ $('#status-filter').val('');
+ $('#type-filter').val('');
+ $('#order-sn-filter').val('');
+ refreshTable();
+ });
+
+ $('.btn-filter-failed').on('click', function () {
+ $('#status-filter').val('failed');
+ $('#type-filter').val('');
+ refreshTable();
+ });
+
+ table.on('click', '.btn-order', function () {
+ var orderId = $(this).data('id');
+ Fast.api.open('shopro/order/order/detail?id=' + orderId, '订单详情');
});
table.on('click', '.btn-retry', function () {
var id = $(this).data('id');
- $.post('shopro_wechat_trade/sync/retry', { id: id }, function (ret) {
- Backend.api.toastr[ret.code === 1 ? 'success' : 'error'](ret.msg);
- table.bootstrapTable('refresh');
+ Layer.confirm('将重新向微信发起同步请求,是否继续?', { icon: 3, title: '确认重试' }, function (index) {
+ Layer.close(index);
+ $.post('shopro_wechat_trade/sync/retry', { id: id }, function (ret) {
+ Backend.api.toastr[ret.code === 1 ? 'success' : 'error'](ret.msg);
+ refreshTable();
+ });
+ });
+ });
+
+ table.on('click', '.btn-detail', function () {
+ var id = $(this).data('id');
+ $.get('shopro_wechat_trade/sync/detail', { id: id }, function (ret) {
+ if (ret.code !== 1) {
+ Backend.api.toastr.error(ret.msg || '加载失败');
+ return;
+ }
+ var row = ret.data || {};
+ var $tpl = $('#sync-detail-template').clone().removeAttr('id').removeClass('hide');
+ $tpl.find('.detail-id').text(row.id || '-');
+ $tpl.find('.detail-order-sn').text(row.order_sn || '-');
+ $tpl.find('.detail-sync-type').html(formatSyncType(row.sync_type));
+ $tpl.find('.detail-status').html(formatStatus(row));
+ if (row.sync_type === 'shipping') {
+ $tpl.find('.detail-delivery-mode').text(DELIVERY_MODE_MAP[row.delivery_mode] || ('模式' + row.delivery_mode));
+ $tpl.find('.detail-delivery-mode-row').show();
+ } else {
+ $tpl.find('.detail-delivery-mode-row').hide();
+ }
+ $tpl.find('.detail-retry').text(row.retry_count || 0);
+ if (row.status === 'success') {
+ $tpl.find('.detail-error-row').hide();
+ } else {
+ var errParts = [];
+ if (row.errcode !== null && row.errcode !== undefined && row.errcode !== '') {
+ errParts.push('[' + row.errcode + ']');
+ }
+ if (row.errmsg) {
+ errParts.push(row.errmsg);
+ }
+ $tpl.find('.detail-error').text(errParts.join(' ') || '-');
+ $tpl.find('.detail-error-row').show();
+ }
+ $tpl.find('.detail-create').text(formatDatetime(row.createtime));
+ $tpl.find('.detail-update').text(formatDatetime(row.updatetime));
+ $tpl.find('.detail-request').text(formatJsonText(row.request_payload));
+ $tpl.find('.detail-response').text(formatJsonText(row.response_payload));
+
+ Layer.open({
+ type: 1,
+ title: '同步记录详情 #' + row.id,
+ area: ['720px', '80%'],
+ shadeClose: true,
+ content: $tpl.prop('outerHTML')
+ });
});
});
diff --git a/application/admin/controller/shopro_wechat_trade/Sync.php b/application/admin/controller/shopro_wechat_trade/Sync.php
index 021b26e..72f713f 100644
--- a/application/admin/controller/shopro_wechat_trade/Sync.php
+++ b/application/admin/controller/shopro_wechat_trade/Sync.php
@@ -8,25 +8,68 @@ use think\Db;
class Sync extends Backend
{
+ protected function buildQuery($status = '', $syncType = '', $orderSn = '')
+ {
+ $query = Db::name('shopro_wechat_trade_sync');
+ if ($status !== '') {
+ $query->where('status', $status);
+ }
+ if ($syncType !== '') {
+ $query->where('sync_type', $syncType);
+ }
+ if ($orderSn !== '') {
+ $query->where('order_sn', 'like', '%' . $orderSn . '%');
+ }
+ return $query;
+ }
+
+ protected function getStats()
+ {
+ $rows = Db::name('shopro_wechat_trade_sync')
+ ->field('status, COUNT(*) AS cnt')
+ ->group('status')
+ ->select();
+ $stats = ['success' => 0, 'pending' => 0, 'failed' => 0, 'total' => 0];
+ foreach ($rows as $row) {
+ $key = $row['status'] ?? '';
+ if (isset($stats[$key])) {
+ $stats[$key] = intval($row['cnt']);
+ }
+ $stats['total'] += intval($row['cnt']);
+ }
+ return $stats;
+ }
+
public function index()
{
if ($this->request->isAjax()) {
$page = max(1, intval($this->request->get('page', 1)));
$limit = max(1, min(100, intval($this->request->get('limit', 20))));
$status = trim($this->request->get('status', ''));
+ $syncType = trim($this->request->get('sync_type', ''));
+ $orderSn = trim($this->request->get('order_sn', ''));
- $query = Db::name('shopro_wechat_trade_sync')->order('id', 'desc');
- if ($status !== '') {
- $query->where('status', $status);
- }
- $total = $query->count();
+ $query = $this->buildQuery($status, $syncType, $orderSn)->order('id', 'desc');
+ $total = (clone $query)->count();
$list = $query->page($page, $limit)->select();
return json(['total' => $total, 'rows' => $list]);
}
+
+ $this->view->assign('stats', $this->getStats());
return $this->view->fetch();
}
+ public function detail()
+ {
+ $id = intval($this->request->get('id'));
+ $row = Db::name('shopro_wechat_trade_sync')->where('id', $id)->find();
+ if (!$row) {
+ $this->error('记录不存在');
+ }
+ $this->success('', null, $row);
+ }
+
public function retry()
{
$id = intval($this->request->post('id'));
@@ -34,6 +77,9 @@ class Sync extends Backend
if (!$row) {
$this->error('记录不存在');
}
+ if ($row['status'] === 'success') {
+ $this->error('该记录已同步成功,无需重试');
+ }
try {
$service = new WxShippingService();
if ($row['sync_type'] === 'confirm') {
diff --git a/application/admin/view/shopro_wechat_trade/sync/index.html b/application/admin/view/shopro_wechat_trade/sync/index.html
index 25b1192..72c7f22 100644
--- a/application/admin/view/shopro_wechat_trade/sync/index.html
+++ b/application/admin/view/shopro_wechat_trade/sync/index.html
@@ -1,14 +1,122 @@
-
-
微信发货/确认收货同步日志
+
+
+
+ 微信发货/确认收货同步日志
+ 记录向微信平台同步的操作结果,供排查与手动重试
+
+
+
+
+
记录ID:
+
订单号:
+
同步类型:
+
同步状态:
+
发货模式:
+
重试次数:
+
错误信息:
+
创建时间:
+
更新时间:
+
请求内容:
+
+
响应内容:
+
+
+