5586 lines
292 KiB
HTML
5586 lines
292 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>批量查询接口测试</title>
|
||
<!-- Bootstrap CSS -->
|
||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||
<!-- jQuery -->
|
||
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
||
<!-- Bootstrap JS -->
|
||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||
<!-- SheetJS for Excel export -->
|
||
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
|
||
<!-- Label 预览模态框 -->
|
||
<div class="modal fade" id="labelPreviewModal" tabindex="-1" aria-labelledby="labelPreviewModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="labelPreviewModalLabel">Label 预览</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div id="labelPreviewContent"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</head>
|
||
<body>
|
||
<div class="container mt-5">
|
||
<h1 class="text-center mb-5">批量查询换单数据</h1>
|
||
|
||
<!-- 环境选择 -->
|
||
<div class="mb-4">
|
||
<label for="environment" class="form-label">环境选择</label>
|
||
<select class="form-select" id="environment" style="max-width: 400px;">
|
||
<option value="local">本地环境 (http://localhost:5002)</option>
|
||
<option value="test" selected>测试环境 (http://172.232.21.79:5002)</option>
|
||
<option value="production">生产环境 (https://lr.tooexp.com)</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 标签页导航 -->
|
||
<ul class="nav nav-tabs" id="queryTabs" role="tablist">
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link active" id="label-replace-tab" data-bs-toggle="tab" data-bs-target="#label-replace" type="button" role="tab" aria-controls="label-replace" aria-selected="true">标签替换请求</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="label-scan-tab" data-bs-toggle="tab" data-bs-target="#label-scan" type="button" role="tab" aria-controls="label-scan" aria-selected="false">标签扫描记录</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="arrival-handover-tab" data-bs-toggle="tab" data-bs-target="#arrival-handover" type="button" role="tab" aria-controls="arrival-handover" aria-selected="false">到货交接单</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="shipping-handover-tab" data-bs-toggle="tab" data-bs-target="#shipping-handover" type="button" role="tab" aria-controls="shipping-handover" aria-selected="false">出货交接单</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="bag-tag-tab" data-bs-toggle="tab" data-bs-target="#bag-tag" type="button" role="tab" aria-controls="bag-tag" aria-selected="false">集包数据查询</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="order-log-tab" data-bs-toggle="tab" data-bs-target="#order-log" type="button" role="tab" aria-controls="order-log" aria-selected="false">订单日志查询</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="data-dashboard-tab" data-bs-toggle="tab" data-bs-target="#data-dashboard" type="button" role="tab" aria-controls="data-dashboard" aria-selected="false">数据看板</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button class="nav-link" id="order-import-tab" data-bs-toggle="tab" data-bs-target="#order-import" type="button" role="tab" aria-controls="order-import" aria-selected="false">订单导入</button>
|
||
</li>
|
||
</ul>
|
||
|
||
<!-- 标签页内容 -->
|
||
<div class="tab-content" id="queryTabsContent">
|
||
<!-- 标签替换请求查询 -->
|
||
<div class="tab-pane fade show active" id="label-replace" role="tabpanel" aria-labelledby="label-replace-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">标签替换请求查询</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 筛选表单 -->
|
||
<form id="labelReplaceForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-3">
|
||
<label for="billOfLadingNumber" class="form-label">提单号</label>
|
||
<input type="text" class="form-control" id="billOfLadingNumber" placeholder="请输入提单号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="masterPackageNumber" class="form-label">大包号</label>
|
||
<input type="text" class="form-control" id="masterPackageNumber" placeholder="请输入大包号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="referenceNumber" class="form-label">参考号</label>
|
||
<input type="text" class="form-control" id="referenceNumber" placeholder="请输入参考号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="neutralWaybillNumber" class="form-label">中性面单单号</label>
|
||
<textarea class="form-control" id="neutralWaybillNumber" rows="3" placeholder="请输入中性面单单号,多个单号请换行分隔"></textarea>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="finalMileTrackingNumber" class="form-label">尾程跟踪单号</label>
|
||
<input type="text" class="form-control" id="finalMileTrackingNumber" placeholder="请输入尾程跟踪单号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="replaceStatus" class="form-label">换单状态</label>
|
||
<select class="form-select" id="replaceStatus">
|
||
<option value="">全部</option>
|
||
<option value="Y">正常换单</option>
|
||
<option value="N">冻结换单</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="customerId" class="form-label">客户</label>
|
||
<select class="form-select" id="customerId">
|
||
<option value="">全部</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="startCreatedAt" class="form-label">创建时间开始</label>
|
||
<input type="datetime-local" class="form-control" id="startCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="endCreatedAt" class="form-label">创建时间结束</label>
|
||
<input type="datetime-local" class="form-control" id="endCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="startReplacedAt" class="form-label">换单完成时间开始</label>
|
||
<input type="datetime-local" class="form-control" id="startReplacedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="endReplacedAt" class="form-label">换单完成时间结束</label>
|
||
<input type="datetime-local" class="form-control" id="endReplacedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="sortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="sortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
<option value="NeutralWaybillNumber">中性面单单号</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="sortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="sortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="pageSize" class="form-label">每页记录数</label>
|
||
<select class="form-select" id="pageSize">
|
||
<option value="500">500</option>
|
||
<option value="1000">1000</option>
|
||
<option value="2000">2000</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3" id="customPageSizeContainer" style="display: none;">
|
||
<label for="customPageSize" class="form-label">自定义记录数</label>
|
||
<input type="number" class="form-control" id="customPageSize" placeholder="请输入记录数" min="1" max="10000">
|
||
</div>
|
||
<div class="col-md-6 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetLabelReplaceForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="labelReplaceResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-success me-2" id="exportExcelBtn">导出Excel</button>
|
||
<div id="labelReplacePaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>客户简称</th>
|
||
<th>提单号</th>
|
||
<th>大包号</th>
|
||
<th>中性面单单号</th>
|
||
<th>尾程跟踪单号</th>
|
||
<th>袋牌号</th>
|
||
<th>有无面单</th>
|
||
<th>换单状态</th>
|
||
<th>换单完成时间</th>
|
||
<th>标签推送时间</th>
|
||
<th>创建时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="labelReplaceTableBody">
|
||
<tr>
|
||
<td colspan="12" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="labelReplacePagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 标签扫描记录查询 -->
|
||
<div class="tab-pane fade" id="label-scan" role="tabpanel" aria-labelledby="label-scan-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">标签扫描记录查询</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 筛选表单 -->
|
||
<form id="labelScanForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-3">
|
||
<label for="scanCustomerId" class="form-label">客户</label>
|
||
<select class="form-select" id="scanCustomerId">
|
||
<option value="">全部</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanNeutralWaybillNumber" class="form-label">中性面单单号</label>
|
||
<input type="text" class="form-control" id="scanNeutralWaybillNumber" placeholder="请输入中性面单单号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanFinalMileTrackingNumber" class="form-label">尾程跟踪单号</label>
|
||
<input type="text" class="form-control" id="scanFinalMileTrackingNumber" placeholder="请输入尾程跟踪单号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanResult" class="form-label">扫描结果</label>
|
||
<select class="form-select" id="scanResult">
|
||
<option value="">全部</option>
|
||
<option value="0">已返回面单</option>
|
||
<option value="1">无面单数据</option>
|
||
<option value="2">无下单数据</option>
|
||
<option value="3">订单被冻结</option>
|
||
<option value="4">订单已销毁</option>
|
||
<option value="5">其他</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanStartCreatedAt" class="form-label">创建时间开始</label>
|
||
<input type="datetime-local" class="form-control" id="scanStartCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanEndCreatedAt" class="form-label">创建时间结束</label>
|
||
<input type="datetime-local" class="form-control" id="scanEndCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanSortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="scanSortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
<option value="NeutralWaybillNumber">中性面单单号</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanSortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="scanSortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="scanPageSize" class="form-label">每页记录数</label>
|
||
<select class="form-select" id="scanPageSize">
|
||
<option value="500">500</option>
|
||
<option value="1000">1000</option>
|
||
<option value="2000">2000</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3" id="customScanPageSizeContainer" style="display: none;">
|
||
<label for="customScanPageSize" class="form-label">自定义记录数</label>
|
||
<input type="number" class="form-control" id="customScanPageSize" placeholder="请输入记录数" min="1" max="10000">
|
||
</div>
|
||
<div class="col-md-6 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetLabelScanForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="labelScanResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-success me-2" id="exportScanExcelBtn">导出Excel</button>
|
||
<div id="labelScanPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>客户简称</th>
|
||
<th>中性面单单号</th>
|
||
<th>尾程跟踪单号</th>
|
||
<th>扫描结果</th>
|
||
<th>描述</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="labelScanTableBody">
|
||
<tr>
|
||
<td colspan="10" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="labelScanPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 到货交接单 -->
|
||
<div class="tab-pane fade" id="arrival-handover" role="tabpanel" aria-labelledby="arrival-handover-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">到货交接单</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 功能操作区 -->
|
||
<div class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<!-- 添加到货交接单 -->
|
||
<div class="col-md-8">
|
||
<h3 class="h5 mb-3">添加到货交接单</h3>
|
||
<!-- 图片上传表单 -->
|
||
<form id="uploadArrivalPODForm" action="" method="post" enctype="multipart/form-data" target="uploadFrame" style="display: none;">
|
||
<input type="file" id="addPOD" name="files" multiple accept="image/*">
|
||
<input type="hidden" name="type" value="arrival">
|
||
<input type="hidden" name="handoverNumber" id="arrivalHandoverNumberForUpload">
|
||
</form>
|
||
|
||
<form id="addArrivalHandoverForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label for="addHandoverNumber" class="form-label">交接单号(头程物流跟踪号,多个请换行)</label>
|
||
<textarea class="form-control" id="addHandoverNumber" rows="3" placeholder="请输入交接单号,多个单号请换行分隔" required></textarea>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="addLogisticsProviderArrivalTime" class="form-label">头程物流商送达时间</label>
|
||
<input type="datetime-local" class="form-control" id="addLogisticsProviderArrivalTime" required>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="addReceiptTime" class="form-label">收货时间</label>
|
||
<input type="datetime-local" class="form-control" id="addReceiptTime" required>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="addPOD" class="form-label">POD(图片上传)</label>
|
||
<input type="file" class="form-control" id="addPOD" multiple accept="image/*">
|
||
<small class="form-text text-muted">支持上传多个图片文件</small>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label class="form-label">已上传图片</label>
|
||
<div id="uploadedArrivalPODs" class="mt-2 p-3 border border-dashed border-gray-300 rounded" style="min-height: 120px;">
|
||
<p class="text-muted text-center">点击或粘贴图片到此处</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="addRemarks" class="form-label">备注</label>
|
||
<textarea class="form-control" id="addRemarks" rows="2" placeholder="请输入备注"></textarea>
|
||
</div>
|
||
<div class="col-md-12">
|
||
<label for="timezone" class="form-label">时区选择</label>
|
||
<select class="form-select" id="timezone">
|
||
<option value="America/New_York" selected>美国纽约 (东部时间 UTC-5)</option>
|
||
<option value="America/Chicago">美国芝加哥 (中部时间 UTC-6)</option>
|
||
<option value="America/Denver">美国丹佛 (山地时间 UTC-7)</option>
|
||
<option value="America/Los_Angeles">美国洛杉矶 (太平洋时间 UTC-8)</option>
|
||
<option value="America/Anchorage">美国安克雷奇 (阿拉斯加时间 UTC-9)</option>
|
||
<option value="America/Honolulu">美国檀香山 (夏威夷时间 UTC-10)</option>
|
||
<option value="Asia/Shanghai">中国标准时间 (UTC+8)</option>
|
||
<option value="UTC">协调世界时 (UTC)</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="submit" class="btn btn-primary">添加</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<!-- 查询到货交接单 -->
|
||
<div class="col-md-4">
|
||
<h3 class="h5 mb-3 p-2 bg-primary text-white rounded">查询条件</h3>
|
||
<form id="arrivalHandoverForm" class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<div class="col-md-12">
|
||
<label for="handoverNumber" class="form-label">交接单号(多个请换行)</label>
|
||
<textarea class="form-control" id="handoverNumber" rows="3" placeholder="请输入交接单号,多个单号请换行分隔"></textarea>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="arrivalSortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="arrivalSortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
<option value="HandoverNumber">交接单号</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="arrivalSortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="arrivalSortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="arrivalPageSize" class="form-label">每页记录数</label>
|
||
<select class="form-select" id="arrivalPageSize">
|
||
<option value="500">500</option>
|
||
<option value="1000">1000</option>
|
||
<option value="2000">2000</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-6" id="customArrivalPageSizeContainer" style="display: none;">
|
||
<label for="customArrivalPageSize" class="form-label">自定义记录数</label>
|
||
<input type="number" class="form-control" id="customArrivalPageSize" placeholder="请输入记录数" min="1" max="10000">
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetArrivalHandoverForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="arrivalHandoverResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-danger me-2" id="deleteSelectedHandoverForms">删除选中</button>
|
||
<div id="arrivalHandoverPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th><input type="checkbox" id="selectAllHandoverForms"></th>
|
||
<th>ID</th>
|
||
<th>客户简称</th>
|
||
<th>交接单号</th>
|
||
<th>头程物流商送达时间</th>
|
||
<th>收货时间</th>
|
||
<th>POD</th>
|
||
<th>备注</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>时区</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="arrivalHandoverTableBody">
|
||
<tr>
|
||
<td colspan="11" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="arrivalHandoverPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 出货交接单 -->
|
||
<div class="tab-pane fade" id="shipping-handover" role="tabpanel" aria-labelledby="shipping-handover-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">出货交接单</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 功能操作区 -->
|
||
<div class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<!-- 添加出货交接单 -->
|
||
<div class="col-md-8">
|
||
<h3 class="h5 mb-3">添加出货交接单</h3>
|
||
<!-- 图片上传表单 -->
|
||
<form id="uploadShippingPODForm" action="" method="post" enctype="multipart/form-data" target="uploadFrame" style="display: none;">
|
||
<input type="file" id="addShippingPOD" name="files" multiple accept="image/*">
|
||
<input type="hidden" name="type" value="shipping">
|
||
<input type="hidden" name="handoverNumber" id="shippingHandoverNumberForUpload">
|
||
</form>
|
||
|
||
<form id="addShippingHandoverForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label for="addShippingHandoverNumber" class="form-label">交接单号</label>
|
||
<input type="text" class="form-control" id="addShippingHandoverNumber" placeholder="请输入交接单号,或留空自动生成">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="addChannel" class="form-label">渠道</label>
|
||
<select class="form-select" id="addChannel">
|
||
<option value="">请选择渠道</option>
|
||
<option value="UPS">UPS</option>
|
||
<option value="USPS">USPS</option>
|
||
<option value="GOFO">GOFO</option>
|
||
<option value="UNIUNI">UNIUNI</option>
|
||
<option value="SPEEDX">SPEEDX</option>
|
||
<option value="YWX">YWX</option>
|
||
<option value="SWIFTX">SWIFTX</option>
|
||
<option value="FEDEX">FEDEX</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="addDeliveryTime" class="form-label">交货时间</label>
|
||
<input type="datetime-local" class="form-control" id="addDeliveryTime">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="addShippingPOD" class="form-label">POD(图片上传)</label>
|
||
<input type="file" class="form-control" id="addShippingPOD" multiple accept="image/*">
|
||
<small class="form-text text-muted">支持上传多个图片文件</small>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="addShippingPODUrls" class="form-label">POD链接(多个链接用逗号分隔)</label>
|
||
<input type="text" class="form-control" id="addShippingPODUrls" placeholder="请输入S3链接,多个链接用逗号分隔">
|
||
<small class="form-text text-muted">可以直接输入预生成的S3链接</small>
|
||
</div>
|
||
<div class="col-md-12">
|
||
<label class="form-label">已上传图片</label>
|
||
<div id="uploadedShippingPODs" class="mt-2 p-3 border border-dashed border-gray-300 rounded" style="min-height: 120px;">
|
||
<p class="text-muted text-center">点击或粘贴图片到此处</p>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="addShippingRemarks" class="form-label">备注</label>
|
||
<textarea class="form-control" id="addShippingRemarks" rows="2" placeholder="请输入备注"></textarea>
|
||
</div>
|
||
<div class="col-md-12">
|
||
<label for="shippingTimezone" class="form-label">时区选择</label>
|
||
<select class="form-select" id="shippingTimezone">
|
||
<option value="America/New_York" selected>美国纽约 (东部时间 UTC-5)</option>
|
||
<option value="America/Chicago">美国芝加哥 (中部时间 UTC-6)</option>
|
||
<option value="America/Denver">美国丹佛 (山地时间 UTC-7)</option>
|
||
<option value="America/Los_Angeles">美国洛杉矶 (太平洋时间 UTC-8)</option>
|
||
<option value="America/Anchorage">美国安克雷奇 (阿拉斯加时间 UTC-9)</option>
|
||
<option value="America/Honolulu">美国檀香山 (夏威夷时间 UTC-10)</option>
|
||
<option value="Asia/Shanghai">中国标准时间 (UTC+8)</option>
|
||
<option value="UTC">协调世界时 (UTC)</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="button" class="btn btn-secondary me-2" id="generateShippingHandoverNumber">生成交接单号</button>
|
||
<button type="submit" class="btn btn-primary">添加</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<!-- 关联袋牌 -->
|
||
<div class="col-md-4">
|
||
<h3 class="h5 mb-3 p-2 bg-primary text-white rounded">关联袋牌</h3>
|
||
<form id="associateBagTagsForm" class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<div class="col-md-12">
|
||
<label for="shippingHandoverFormId" class="form-label">出货交接单ID</label>
|
||
<input type="number" class="form-control" id="shippingHandoverFormId" placeholder="请输入出货交接单ID" required>
|
||
</div>
|
||
<div class="col-md-12">
|
||
<label for="bagTagNumbers" class="form-label">袋牌号(多个请换行)</label>
|
||
<textarea class="form-control" id="bagTagNumbers" rows="3" placeholder="请输入袋牌号,多个牌号请换行分隔" required></textarea>
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="submit" class="btn btn-primary">关联</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
<!-- 查询关联袋牌 -->
|
||
<h3 class="h5 mb-3 p-2 bg-primary text-white rounded">查询关联袋牌</h3>
|
||
<form id="queryAssociatedBagTagsForm" class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<div class="col-md-12">
|
||
<label for="queryShippingHandoverFormId" class="form-label">出货交接单ID</label>
|
||
<input type="number" class="form-control" id="queryShippingHandoverFormId" placeholder="请输入出货交接单ID" required>
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="submit" class="btn btn-primary">查询</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 查询出货交接单 -->
|
||
<div class="mb-4">
|
||
<h3 class="h5 mb-3 p-2 bg-primary text-white rounded">查询条件</h3>
|
||
<form id="shippingHandoverForm" class="mb-4 p-3 border rounded bg-light">
|
||
<div class="row g-3">
|
||
<div class="col-md-3">
|
||
<label for="shippingHandoverNumber" class="form-label">交接单号</label>
|
||
<input type="text" class="form-control" id="shippingHandoverNumber" placeholder="请输入交接单号">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="shippingChannel" class="form-label">渠道</label>
|
||
<select class="form-select" id="shippingChannel">
|
||
<option value="">全部</option>
|
||
<option value="UPS">UPS</option>
|
||
<option value="USPS">USPS</option>
|
||
<option value="GOFO">GOFO</option>
|
||
<option value="UNIUNI">UNIUNI</option>
|
||
<option value="SPEEDX">SPEEDX</option>
|
||
<option value="YWX">YWX</option>
|
||
<option value="SWIFTX">SWIFTX</option>
|
||
<option value="FEDEX">FEDEX</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="shippingCreator" class="form-label">创建人</label>
|
||
<input type="text" class="form-control" id="shippingCreator" placeholder="请输入创建人">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="startDeliveryTime" class="form-label">交货时间开始</label>
|
||
<input type="datetime-local" class="form-control" id="startDeliveryTime">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="endDeliveryTime" class="form-label">交货时间结束</label>
|
||
<input type="datetime-local" class="form-control" id="endDeliveryTime">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="shippingSortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="shippingSortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
<option value="HandoverNumber">交接单号</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="shippingSortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="shippingSortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="shippingPageSize" class="form-label">每页记录数</label>
|
||
<select class="form-select" id="shippingPageSize">
|
||
<option value="500">500</option>
|
||
<option value="1000">1000</option>
|
||
<option value="2000">2000</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3" id="customShippingPageSizeContainer" style="display: none;">
|
||
<label for="customShippingPageSize" class="form-label">自定义记录数</label>
|
||
<input type="number" class="form-control" id="customShippingPageSize" placeholder="请输入记录数" min="1" max="10000">
|
||
</div>
|
||
<div class="col-md-6 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetShippingHandoverForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="shippingHandoverResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-danger me-2" id="deleteSelectedShippingHandoverForms">删除选中</button>
|
||
<div id="shippingHandoverPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th><input type="checkbox" id="selectAllShippingHandoverForms"></th>
|
||
<th>ID</th>
|
||
<th>交接单号</th>
|
||
<th>箱数</th>
|
||
<th>交货单量</th>
|
||
<th>交货渠道</th>
|
||
<th>交货时间</th>
|
||
<th>时区</th>
|
||
<th>POD</th>
|
||
<th>备注</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="shippingHandoverTableBody">
|
||
<tr>
|
||
<td colspan="13" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="shippingHandoverPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 数据看板 -->
|
||
<div class="tab-pane fade" id="data-dashboard" role="tabpanel" aria-labelledby="data-dashboard-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">数据看板</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 数据看板查询表单 -->
|
||
<form id="dashboardQueryForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label for="arrivalNumber" class="form-label">交接单号</label>
|
||
<input type="text" class="form-control" id="arrivalNumber" placeholder="请输入交接单号">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="dashboardStartDate" class="form-label">开始日期</label>
|
||
<input type="date" class="form-control" id="dashboardStartDate">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="dashboardEndDate" class="form-label">结束日期</label>
|
||
<input type="date" class="form-control" id="dashboardEndDate">
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="dashboardCustomerId" class="form-label">客户</label>
|
||
<select class="form-select" id="dashboardCustomerId">
|
||
<option value="">全部</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-12 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary me-2" id="resetDashboardForm">重置</button>
|
||
<button type="button" class="btn btn-warning" id="exportDailyStatsChineseBtn">导出运维监控</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 当天扫描后未下单数量 -->
|
||
<div class="mb-4 p-3 border rounded bg-info text-white">
|
||
<h3 class="h5 mb-2">当天扫描后未下单数量</h3>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<p><strong>未下单数量:</strong><span id="todayUnorderedCount" class="text-white">0</span></p>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<p><strong>扫描总数:</strong><span id="todayScanTotal" class="text-white">0</span></p>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<p><strong>统计日期:</strong><span id="todayDate" class="text-white"></span></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="dataDashboardResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-success me-2" id="exportDashboardExcelBtn">导出Excel</button>
|
||
<div id="dataDashboardPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>客户简称</th>
|
||
<th>已有标签率</th>
|
||
<th>未换单完成数量</th>
|
||
<th>提单号</th>
|
||
<th>大箱号</th>
|
||
<th>到货订单数量</th>
|
||
<th>换单完成数量</th>
|
||
<th>无标签数据数量</th>
|
||
<th>到货时间</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="dataDashboardTableBody">
|
||
<tr>
|
||
<td colspan="10" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="dataDashboardPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 订单导入 -->
|
||
<div class="tab-pane fade" id="order-import" role="tabpanel" aria-labelledby="order-import-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">订单导入</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 导入表单 -->
|
||
<form id="orderImportForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-4">
|
||
<label for="importCustomerId" class="form-label">客户选择</label>
|
||
<select class="form-select" id="importCustomerId" required>
|
||
<option value="">请选择客户</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="labelFilenameMapping" class="form-label">标签文件名映射为:</label>
|
||
<select class="form-select" id="labelFilenameMapping" required>
|
||
<option value="none">无</option>
|
||
<option value="neutralWaybill">中性面单单号</option>
|
||
<option value="finalMileTracking">尾程单号</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<label for="excelFile" class="form-label">Excel文件</label>
|
||
<input type="file" class="form-control" id="excelFile" accept=".xlsx,.xls" required>
|
||
<small class="form-text text-muted">支持.xlsx和.xls格式</small>
|
||
<div class="mt-2">
|
||
<button type="button" class="btn btn-sm btn-outline-secondary" id="downloadTemplateBtn">下载模板</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col-md-12">
|
||
<label class="form-label">Excel列要求</label>
|
||
<div class="p-3 border rounded bg-light">
|
||
<p>Excel文件必须包含以下列:</p>
|
||
<ul>
|
||
<li><strong>BillOfLadingNumber</strong> - 提单号(支持纯数字格式)</li>
|
||
<li><strong>MasterPackageNumber</strong> - 大包号(支持纯数字格式)</li>
|
||
<li><strong>NeutralWaybillNumber</strong> - 中性面单单号(必填)</li>
|
||
<li><strong>FinalMileTrackingNumber</strong> - 尾程单号</li>
|
||
<li><strong>Label</strong> - 标签内容(可选,会根据选择的映射生成URL)</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="col-md-12 d-flex justify-content-end">
|
||
<button type="submit" class="btn btn-primary">导入订单</button>
|
||
<button type="button" class="btn btn-secondary ms-2" id="resetOrderImportForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 进度显示 -->
|
||
<div id="importProgress" class="mb-4" style="display: none;">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="h5">导入进度</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="progress mb-3">
|
||
<div class="progress-bar" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||
</div>
|
||
<div class="row">
|
||
<div class="col-md-4">
|
||
<p><strong>总订单数:</strong><span id="totalOrders">0</span></p>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<p><strong>已处理:</strong><span id="processedOrders">0</span></p>
|
||
</div>
|
||
<div class="col-md-4">
|
||
<p><strong>进度:</strong><span id="progressPercentage">0%</span></p>
|
||
</div>
|
||
</div>
|
||
<div id="importStatus" class="mt-2"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="importResult" class="mt-4" style="display: none;">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="h5">导入结果</h3>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="row mb-3">
|
||
<div class="col-md-3">
|
||
<p><strong>总订单数:</strong><span id="resultTotalCount">0</span></p>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<p><strong>成功:</strong><span id="resultSuccessCount" class="text-success">0</span></p>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<p><strong>失败:</strong><span id="resultFailedCount" class="text-danger">0</span></p>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<p><strong>成功率:</strong><span id="resultSuccessRate">0%</span></p>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>提单号</th>
|
||
<th>大包号</th>
|
||
<th>中性面单单号</th>
|
||
<th>尾程单号</th>
|
||
<th>状态</th>
|
||
<th>消息</th>
|
||
<th>标签</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="importResultTableBody">
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 面单文件上传 -->
|
||
|
||
|
||
<!-- 订单日志查询 -->
|
||
<div class="tab-pane fade" id="order-log" role="tabpanel" aria-labelledby="order-log-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">订单日志查询</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 筛选表单 -->
|
||
<form id="orderLogForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-6">
|
||
<label for="neutralWaybillNumber" class="form-label">中性面单单号</label>
|
||
<input type="text" class="form-control" id="orderLogNeutralWaybillNumber" placeholder="请输入中性面单单号">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="finalMileTrackingNumber" class="form-label">尾程单号</label>
|
||
<input type="text" class="form-control" id="orderLogFinalMileTrackingNumber" placeholder="请输入尾程单号">
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="orderLogSortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="orderLogSortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="orderLogSortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="orderLogSortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-12 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetOrderLogForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="orderLogResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-success me-2" id="exportOrderLogExcelBtn">导出Excel</button>
|
||
<div id="orderLogPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>中性面单单号</th>
|
||
<th>尾程单号</th>
|
||
<th>操作类型</th>
|
||
<th>操作详情</th>
|
||
<th>操作人</th>
|
||
<th>操作时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="orderLogTableBody">
|
||
<tr>
|
||
<td colspan="7" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="orderLogPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 集包数据查询 -->
|
||
<div class="tab-pane fade" id="bag-tag" role="tabpanel" aria-labelledby="bag-tag-tab">
|
||
<div class="card mt-4">
|
||
<div class="card-header">
|
||
<h2 class="h4">集包数据查询</h2>
|
||
</div>
|
||
<div class="card-body">
|
||
<!-- 筛选表单 -->
|
||
<form id="bagTagForm" class="mb-4">
|
||
<div class="row g-3">
|
||
<div class="col-md-3">
|
||
<label for="bagTagNumber" class="form-label">袋牌号码</label>
|
||
<input type="text" class="form-control" id="bagTagNumber" placeholder="请输入袋牌号码">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagChannel" class="form-label">渠道</label>
|
||
<select class="form-select" id="bagTagChannel">
|
||
<option value="">全部</option>
|
||
<option value="UPS">UPS</option>
|
||
<option value="USPS">USPS</option>
|
||
<option value="GOFO">GOFO</option>
|
||
<option value="UNIUNI">UNIUNI</option>
|
||
<option value="SPEEDX">SPEEDX</option>
|
||
<option value="YWX">YWX</option>
|
||
<option value="SWIFTX">SWIFTX</option>
|
||
<option value="FEDEX">FEDEX</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagStatus" class="form-label">状态</label>
|
||
<select class="form-select" id="bagTagStatus">
|
||
<option value="">全部</option>
|
||
<option value="Generated">已生成</option>
|
||
<option value="Opened">已打开</option>
|
||
<option value="Closed">已关闭</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagCreator" class="form-label">创建人</label>
|
||
<input type="text" class="form-control" id="bagTagCreator" placeholder="请输入创建人">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagStartCreatedAt" class="form-label">创建时间开始</label>
|
||
<input type="datetime-local" class="form-control" id="bagTagStartCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagEndCreatedAt" class="form-label">创建时间结束</label>
|
||
<input type="datetime-local" class="form-control" id="bagTagEndCreatedAt">
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagSortBy" class="form-label">排序字段</label>
|
||
<select class="form-select" id="bagTagSortBy">
|
||
<option value="CreatedAt">创建时间</option>
|
||
<option value="Id">ID</option>
|
||
<option value="TagNumber">袋牌号码</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagSortOrder" class="form-label">排序顺序</label>
|
||
<select class="form-select" id="bagTagSortOrder">
|
||
<option value="desc">降序</option>
|
||
<option value="asc">升序</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3">
|
||
<label for="bagTagPageSize" class="form-label">每页记录数</label>
|
||
<select class="form-select" id="bagTagPageSize">
|
||
<option value="500">500</option>
|
||
<option value="1000">1000</option>
|
||
<option value="2000">2000</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<div class="col-md-3" id="customBagTagPageSizeContainer" style="display: none;">
|
||
<label for="customBagTagPageSize" class="form-label">自定义记录数</label>
|
||
<input type="number" class="form-control" id="customBagTagPageSize" placeholder="请输入记录数" min="1" max="10000">
|
||
</div>
|
||
<div class="col-md-6 d-flex align-items-end">
|
||
<button type="submit" class="btn btn-primary me-2">查询</button>
|
||
<button type="button" class="btn btn-secondary" id="resetBagTagForm">重置</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
|
||
<!-- 结果展示 -->
|
||
<div id="bagTagResult" class="mt-4">
|
||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||
<h3 class="h5">查询结果</h3>
|
||
<div class="d-flex align-items-center">
|
||
<button type="button" class="btn btn-success me-2" id="exportBagTagExcelBtn">导出Excel</button>
|
||
<div id="bagTagPaginationInfo" class="text-muted"></div>
|
||
</div>
|
||
</div>
|
||
<div class="table-responsive">
|
||
<table class="table table-striped table-bordered">
|
||
<thead>
|
||
<tr>
|
||
<th>ID</th>
|
||
<th>袋牌号码</th>
|
||
<th>渠道</th>
|
||
<th>状态</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>打开时间</th>
|
||
<th>关闭时间</th>
|
||
<th>关联运单数量</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="bagTagTableBody">
|
||
<tr>
|
||
<td colspan="10" class="text-center">请点击查询按钮获取数据</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<!-- 分页控件 -->
|
||
<nav id="bagTagPagination" class="mt-3">
|
||
<ul class="pagination justify-content-center"></ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 气泡弹窗 -->
|
||
<div id="bubbleNotification" class="fixed inset-0 flex items-center justify-center z-50 pointer-events-none" style="display: none;">
|
||
<div class="bg-white rounded-lg shadow-lg p-6 max-w-md mx-auto text-center">
|
||
<div class="text-green-500 mb-2">
|
||
<svg xmlns="http://www.w3.org/2000/svg" class="h-12 w-12 mx-auto" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||
</svg>
|
||
</div>
|
||
<h3 class="text-lg font-medium text-gray-900 mb-2">操作完成</h3>
|
||
<p class="text-gray-600" id="bubbleMessage">共找到 0 条记录</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 编辑出货交接单模态框 -->
|
||
<div class="modal fade" id="editShippingHandoverModal" tabindex="-1" aria-labelledby="editShippingHandoverModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="editShippingHandoverModalLabel">编辑出货交接单</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="editShippingHandoverForm">
|
||
<input type="hidden" id="editId">
|
||
<div class="mb-3">
|
||
<label for="editDeliveryTime" class="form-label">交货时间</label>
|
||
<input type="datetime-local" class="form-control" id="editDeliveryTime">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editTimezone" class="form-label">时区</label>
|
||
<select class="form-select" id="editTimezone">
|
||
<option value="America/New_York">美国纽约 (东部时间 UTC-5)</option>
|
||
<option value="America/Chicago">美国芝加哥 (中部时间 UTC-6)</option>
|
||
<option value="America/Denver">美国丹佛 (山地时间 UTC-7)</option>
|
||
<option value="America/Los_Angeles">美国洛杉矶 (太平洋时间 UTC-8)</option>
|
||
<option value="America/Anchorage">美国安克雷奇 (阿拉斯加时间 UTC-9)</option>
|
||
<option value="America/Honolulu">美国檀香山 (夏威夷时间 UTC-10)</option>
|
||
<option value="Asia/Shanghai">中国标准时间 (UTC+8)</option>
|
||
<option value="UTC">协调世界时 (UTC)</option>
|
||
</select>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editShippingPOD" class="form-label">POD(图片上传)</label>
|
||
<input type="file" class="form-control" id="editShippingPOD" multiple accept="image/*">
|
||
<small class="form-text text-muted">支持上传多个图片文件</small>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editShippingPODUrls" class="form-label">POD链接(多个链接用逗号分隔)</label>
|
||
<input type="text" class="form-control" id="editShippingPODUrls" placeholder="请输入S3链接,多个链接用逗号分隔">
|
||
<small class="form-text text-muted">可以直接输入预生成的S3链接</small>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">已上传图片</label>
|
||
<div id="editUploadedShippingPODs" class="mt-2 p-3 border border-dashed border-gray-300 rounded" style="min-height: 120px;">
|
||
<p class="text-muted text-center">点击或粘贴图片到此处</p>
|
||
</div>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editRemarks" class="form-label">备注</label>
|
||
<textarea class="form-control" id="editRemarks" rows="3"></textarea>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||
<button type="button" class="btn btn-primary" id="saveEditBtn">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 隐藏的iframe用于表单提交 -->
|
||
<iframe name="uploadFrame" id="uploadFrame" style="display: none;"></iframe>
|
||
|
||
<!-- 编辑到货交接单模态框 -->
|
||
<div class="modal fade" id="editArrivalHandoverModal" tabindex="-1" aria-labelledby="editArrivalHandoverModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="editArrivalHandoverModalLabel">编辑到货交接单</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="editArrivalHandoverForm">
|
||
<input type="hidden" id="editArrivalId">
|
||
<input type="hidden" id="editArrivalHandoverNumber">
|
||
<div class="mb-3">
|
||
<label for="editLogisticsProviderArrivalTime" class="form-label">头程物流商送达时间</label>
|
||
<input type="datetime-local" class="form-control" id="editLogisticsProviderArrivalTime">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editReceiptTime" class="form-label">收货时间</label>
|
||
<input type="datetime-local" class="form-control" id="editReceiptTime">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editArrivalPODUpload" class="form-label">POD(图片上传)</label>
|
||
<input type="file" class="form-control" id="editArrivalPODUpload" multiple accept="image/*">
|
||
<small class="form-text text-muted">支持上传多个图片文件</small>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editArrivalPOD" class="form-label">POD链接(多个链接用逗号分隔)</label>
|
||
<input type="text" class="form-control" id="editArrivalPOD" placeholder="请输入S3链接,多个链接用逗号分隔">
|
||
<small class="form-text text-muted">可以直接输入预生成的S3链接</small>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label class="form-label">已上传图片</label>
|
||
<div id="editUploadedArrivalPODs" class="mt-2 p-3 border border-dashed border-gray-300 rounded" style="min-height: 120px;">
|
||
<p class="text-muted text-center">点击或粘贴图片到此处</p>
|
||
</div>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editArrivalTimezone" class="form-label">时区</label>
|
||
<select class="form-select" id="editArrivalTimezone">
|
||
<option value="America/New_York">美国纽约 (东部时间 UTC-5)</option>
|
||
<option value="America/Chicago">美国芝加哥 (中部时间 UTC-6)</option>
|
||
<option value="America/Denver">美国丹佛 (山地时间 UTC-7)</option>
|
||
<option value="America/Los_Angeles">美国洛杉矶 (太平洋时间 UTC-8)</option>
|
||
<option value="America/Anchorage">美国安克雷奇 (阿拉斯加时间 UTC-9)</option>
|
||
<option value="America/Honolulu">美国檀香山 (夏威夷时间 UTC-10)</option>
|
||
<option value="Asia/Shanghai">中国标准时间 (UTC+8)</option>
|
||
<option value="UTC">协调世界时 (UTC)</option>
|
||
</select>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editArrivalRemarks" class="form-label">备注</label>
|
||
<textarea class="form-control" id="editArrivalRemarks" rows="3"></textarea>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||
<button type="button" class="btn btn-primary" id="saveArrivalEditBtn">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- POD 预览模态框 -->
|
||
<div class="modal fade" id="podPreviewModal" tabindex="-1" aria-labelledby="podPreviewModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="podPreviewModalLabel">POD 预览</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<div id="podPreviewContent"></div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<style>
|
||
/* 气泡弹窗样式 */
|
||
.fixed {
|
||
position: fixed;
|
||
}
|
||
.inset-0 {
|
||
top: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
left: 0;
|
||
}
|
||
.flex {
|
||
display: flex;
|
||
}
|
||
.items-center {
|
||
align-items: center;
|
||
}
|
||
.justify-center {
|
||
justify-content: center;
|
||
}
|
||
.z-50 {
|
||
z-index: 50;
|
||
}
|
||
.pointer-events-none {
|
||
pointer-events: none;
|
||
}
|
||
.bg-white {
|
||
background-color: white;
|
||
}
|
||
.rounded-lg {
|
||
border-radius: 0.5rem;
|
||
}
|
||
.shadow-lg {
|
||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||
}
|
||
.p-6 {
|
||
padding: 1.5rem;
|
||
}
|
||
.max-w-md {
|
||
max-width: 28rem;
|
||
}
|
||
.mx-auto {
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
}
|
||
.text-center {
|
||
text-align: center;
|
||
}
|
||
.text-green-500 {
|
||
color: #10b981;
|
||
}
|
||
.mb-2 {
|
||
margin-bottom: 0.5rem;
|
||
}
|
||
.h-12 {
|
||
height: 3rem;
|
||
}
|
||
.w-12 {
|
||
width: 3rem;
|
||
}
|
||
.text-lg {
|
||
font-size: 1.125rem;
|
||
}
|
||
.font-medium {
|
||
font-weight: 500;
|
||
}
|
||
.text-gray-900 {
|
||
color: #111827;
|
||
}
|
||
.text-gray-600 {
|
||
color: #4b5563;
|
||
}
|
||
|
||
/* 表格样式优化 */
|
||
.table {
|
||
table-layout: auto;
|
||
width: 100%;
|
||
}
|
||
.table th,
|
||
.table td {
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.table-responsive {
|
||
overflow-x: auto;
|
||
}
|
||
|
||
.cursor-pointer {
|
||
cursor: pointer;
|
||
}
|
||
|
||
.cursor-pointer:hover {
|
||
text-decoration: underline;
|
||
}
|
||
</style>
|
||
|
||
<script>
|
||
// 环境配置
|
||
const environments = {
|
||
local: 'http://localhost:5002',
|
||
test: 'http://172.232.21.79:5002',
|
||
production: 'https://lr.tooexp.com'
|
||
};
|
||
|
||
// 获取当前环境的基础URL
|
||
function getBaseUrl() {
|
||
const env = $('#environment').val();
|
||
return environments[env] || environments.test;
|
||
}
|
||
|
||
// 显示气泡弹窗
|
||
function showBubbleNotification(message) {
|
||
const bubble = $('#bubbleNotification');
|
||
const bubbleMessage = $('#bubbleMessage');
|
||
|
||
bubbleMessage.text(message);
|
||
bubble.css('display', 'flex');
|
||
|
||
// 2秒后自动隐藏
|
||
setTimeout(() => {
|
||
bubble.css('display', 'none');
|
||
}, 2000);
|
||
}
|
||
|
||
// JSONP 回调函数
|
||
function jsonpCallback(response) {
|
||
// 这个函数会被后端返回的 JavaScript 代码调用
|
||
console.log('JSONP response:', response);
|
||
}
|
||
|
||
// 客户列表回调函数
|
||
function customerListCallback(response) {
|
||
if (response.status === 'ok') {
|
||
// 填充标签替换请求的客户下拉框
|
||
const customerSelect = $('#customerId');
|
||
customerSelect.empty();
|
||
customerSelect.append('<option value="">全部</option>');
|
||
|
||
// 填充标签扫描记录的客户下拉框
|
||
const scanCustomerSelect = $('#scanCustomerId');
|
||
scanCustomerSelect.empty();
|
||
scanCustomerSelect.append('<option value="">全部</option>');
|
||
scanCustomerSelect.append('<option value="0">无客户</option>');
|
||
|
||
// 填充订单导入的客户下拉框
|
||
const importCustomerSelect = $('#importCustomerId');
|
||
importCustomerSelect.empty();
|
||
importCustomerSelect.append('<option value="">请选择客户</option>');
|
||
|
||
// 填充数据看板的客户下拉框
|
||
const dashboardCustomerSelect = $('#dashboardCustomerId');
|
||
dashboardCustomerSelect.empty();
|
||
dashboardCustomerSelect.append('<option value="">全部</option>');
|
||
|
||
response.data.forEach(customer => {
|
||
customerSelect.append(`<option value="${customer.Id}">${customer.CustomerCode}</option>`);
|
||
scanCustomerSelect.append(`<option value="${customer.Id}">${customer.CustomerCode}</option>`);
|
||
importCustomerSelect.append(`<option value="${customer.Id}">${customer.CustomerCode}</option>`);
|
||
dashboardCustomerSelect.append(`<option value="${customer.Id}">${customer.CustomerCode}</option>`);
|
||
});
|
||
}
|
||
}
|
||
|
||
// 生成出货交接单号回调函数
|
||
function generateShippingHandoverNumberCallback(response) {
|
||
console.log('Generate shipping handover number response:', response);
|
||
if (response && response.code === 0 && response.data) {
|
||
$('#addShippingHandoverNumber').val(response.data);
|
||
showBubbleNotification('成功生成交接单号');
|
||
} else {
|
||
showBubbleNotification('生成失败: ' + (response ? response.message : '未知错误'));
|
||
}
|
||
}
|
||
|
||
// 获取客户列表
|
||
function loadCustomerList() {
|
||
const url = getBaseUrl() + '/api/Label/customers';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'customerListCallback',
|
||
success: function(response) {
|
||
console.log('Customer list loaded:', response);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to load customer list:', error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 页面加载完成后获取客户列表
|
||
$(document).ready(function() {
|
||
loadCustomerList();
|
||
|
||
// 环境切换时重新加载客户列表
|
||
$('#environment').change(function() {
|
||
loadCustomerList();
|
||
showBubbleNotification('环境已切换,正在加载对应环境的客户列表...');
|
||
});
|
||
|
||
// 订单日志查询表单提交
|
||
$('#orderLogForm').submit(function(e) {
|
||
e.preventDefault();
|
||
queryOrderLog();
|
||
});
|
||
|
||
// 重置订单日志查询表单
|
||
$('#resetOrderLogForm').click(function() {
|
||
$('#orderLogNeutralWaybillNumber').val('');
|
||
$('#orderLogFinalMileTrackingNumber').val('');
|
||
$('#orderLogSortBy').val('CreatedAt');
|
||
$('#orderLogSortOrder').val('desc');
|
||
});
|
||
|
||
// 导出订单日志Excel
|
||
$('#exportOrderLogExcelBtn').click(function() {
|
||
exportOrderLogToExcel();
|
||
});
|
||
|
||
// 提单号预报表单提交
|
||
// 数据看板表单提交
|
||
$('#dashboardQueryForm').submit(function(e) {
|
||
e.preventDefault();
|
||
queryDashboard();
|
||
});
|
||
|
||
// 重置数据看板表单
|
||
$('#resetDashboardForm').click(function() {
|
||
$('#arrivalNumber').val('');
|
||
$('#dashboardStartDate').val('');
|
||
$('#dashboardEndDate').val('');
|
||
$('#dashboardCustomerId').val('');
|
||
});
|
||
|
||
// 导出数据看板Excel
|
||
$('#exportDashboardExcelBtn').click(function() {
|
||
exportDashboardToExcel();
|
||
});
|
||
|
||
// 导出运维监控数据Excel
|
||
$('#exportDailyStatsChineseBtn').click(function() {
|
||
exportDailyStatsChineseToExcel();
|
||
});
|
||
|
||
// 加载当天扫描后未下单数量
|
||
loadTodayUnorderedCount();
|
||
});
|
||
|
||
// 生成GUID(与后端一致)
|
||
function generateGuid() {
|
||
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||
return v.toString(16);
|
||
});
|
||
}
|
||
|
||
// 订单日志查询
|
||
function queryOrderLog() {
|
||
const neutralWaybillNumber = $('#orderLogNeutralWaybillNumber').val().trim();
|
||
const finalMileTrackingNumber = $('#orderLogFinalMileTrackingNumber').val().trim();
|
||
const sortBy = $('#orderLogSortBy').val();
|
||
const sortOrder = $('#orderLogSortOrder').val();
|
||
|
||
if (!neutralWaybillNumber && !finalMileTrackingNumber) {
|
||
showBubbleNotification('请至少输入中性面单单号或尾程单号');
|
||
return;
|
||
}
|
||
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/order-log/query';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
data: {
|
||
neutralWaybillNumber: neutralWaybillNumber,
|
||
finalMileTrackingNumber: finalMileTrackingNumber,
|
||
sortBy: sortBy,
|
||
sortOrder: sortOrder
|
||
},
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
console.log('Order log query response:', response);
|
||
if (response && response.code === 0) {
|
||
displayOrderLogResult(response.data);
|
||
showBubbleNotification(`共找到 ${response.data.length} 条订单日志记录`);
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + (response ? response.message : '未知错误'));
|
||
$('#orderLogTableBody').html('<tr><td colspan="7" class="text-center">查询失败</td></tr>');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to query order log:', error);
|
||
showBubbleNotification('查询失败: ' + error);
|
||
$('#orderLogTableBody').html('<tr><td colspan="7" class="text-center">查询失败</td></tr>');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 展示订单日志查询结果
|
||
function displayOrderLogResult(data) {
|
||
const tableBody = $('#orderLogTableBody');
|
||
tableBody.empty();
|
||
|
||
if (!data || data.length === 0) {
|
||
tableBody.html('<tr><td colspan="7" class="text-center">无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td>${item.Id || ''}</td>`);
|
||
row.append(`<td>${item.NeutralWaybillNumber || ''}</td>`);
|
||
row.append(`<td>${item.FinalMileTrackingNumber || ''}</td>`);
|
||
row.append(`<td>${item.OperationType || ''}</td>`);
|
||
row.append(`<td>${item.OperationDetails || ''}</td>`);
|
||
row.append(`<td>${item.Operator || ''}</td>`);
|
||
row.append(`<td>${item.CreatedAt || ''}</td>`);
|
||
tableBody.append(row);
|
||
});
|
||
}
|
||
|
||
// 导出订单日志到Excel
|
||
function exportOrderLogToExcel() {
|
||
const neutralWaybillNumber = $('#orderLogNeutralWaybillNumber').val().trim();
|
||
const finalMileTrackingNumber = $('#orderLogFinalMileTrackingNumber').val().trim();
|
||
const sortBy = $('#orderLogSortBy').val();
|
||
const sortOrder = $('#orderLogSortOrder').val();
|
||
|
||
if (!neutralWaybillNumber && !finalMileTrackingNumber) {
|
||
showBubbleNotification('请至少输入中性面单单号或尾程单号');
|
||
return;
|
||
}
|
||
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/order-log/export';
|
||
|
||
// 构建导出URL
|
||
let exportUrl = url + '?';
|
||
if (neutralWaybillNumber) exportUrl += `neutralWaybillNumber=${encodeURIComponent(neutralWaybillNumber)}&`;
|
||
if (finalMileTrackingNumber) exportUrl += `finalMileTrackingNumber=${encodeURIComponent(finalMileTrackingNumber)}&`;
|
||
exportUrl += `sortBy=${encodeURIComponent(sortBy)}&sortOrder=${encodeURIComponent(sortOrder)}`;
|
||
|
||
// 打开导出链接
|
||
window.open(exportUrl, '_blank');
|
||
}
|
||
|
||
// 预生成S3链接
|
||
function generateS3Url(type, handoverNumber, fileName, uniqueId) {
|
||
const endpoint = 'https://pod.us-ord-1.linodeobjects.com';
|
||
const yearMonth = new Date().toISOString().slice(0, 7).replace('-', '');
|
||
let prefix = '';
|
||
|
||
if (type === 'arrival') {
|
||
prefix = `arrivalhandover/${yearMonth}/`;
|
||
} else if (type === 'shipping') {
|
||
prefix = `shippinghandover/${yearMonth}/`;
|
||
} else {
|
||
prefix = 'pod/';
|
||
}
|
||
|
||
const objectKey = `${prefix}${handoverNumber}_${uniqueId}_${fileName}`;
|
||
return `${endpoint}/${objectKey}`;
|
||
}
|
||
|
||
// 传统表单提交上传文件
|
||
function uploadFilesWithForm(files, type, handoverNumber, uniqueIds) {
|
||
let formId, handoverNumberInputId;
|
||
|
||
if (type === 'arrival') {
|
||
formId = 'uploadArrivalPODForm';
|
||
handoverNumberInputId = 'arrivalHandoverNumberForUpload';
|
||
} else if (type === 'shipping') {
|
||
formId = 'uploadShippingPODForm';
|
||
handoverNumberInputId = 'shippingHandoverNumberForUpload';
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
// 获取当前环境的基础URL
|
||
const baseUrl = getBaseUrl();
|
||
|
||
// 设置表单的action属性
|
||
document.getElementById(formId).action = baseUrl + '/api/upload';
|
||
|
||
// 设置交接单号
|
||
$('#' + handoverNumberInputId).val(handoverNumber);
|
||
|
||
// 为每个文件添加唯一ID到表单
|
||
const form = document.getElementById(formId);
|
||
|
||
// 移除旧的uniqueIds输入
|
||
const oldInputs = form.querySelectorAll('input[name="uniqueIds"]');
|
||
oldInputs.forEach(input => input.remove());
|
||
|
||
// 移除旧的文件输入
|
||
const oldFileInput = form.querySelector('input[type="file"]');
|
||
if (oldFileInput) {
|
||
oldFileInput.remove();
|
||
}
|
||
|
||
// 添加新的文件输入
|
||
const fileInput = document.createElement('input');
|
||
fileInput.type = 'file';
|
||
fileInput.name = 'files';
|
||
fileInput.multiple = true;
|
||
fileInput.accept = 'image/*';
|
||
fileInput.id = type === 'arrival' ? 'addPOD' : 'addShippingPOD';
|
||
form.appendChild(fileInput);
|
||
|
||
// 复制文件到新的文件输入
|
||
const dataTransfer = new DataTransfer();
|
||
for (let i = 0; i < files.length; i++) {
|
||
dataTransfer.items.add(files[i]);
|
||
}
|
||
fileInput.files = dataTransfer.files;
|
||
|
||
// 添加新的uniqueIds输入
|
||
for (let i = 0; i < files.length; i++) {
|
||
const input = document.createElement('input');
|
||
input.type = 'hidden';
|
||
input.name = 'uniqueIds';
|
||
// 使用传入的uniqueId或生成新的
|
||
input.value = uniqueIds && uniqueIds[i] ? uniqueIds[i] : generateGuid();
|
||
form.appendChild(input);
|
||
}
|
||
|
||
// 提交表单
|
||
form.submit();
|
||
return true;
|
||
}
|
||
|
||
// 数据看板查询
|
||
function queryDashboard() {
|
||
const arrivalNumber = $('#arrivalNumber').val().trim();
|
||
const startDate = $('#dashboardStartDate').val();
|
||
const endDate = $('#dashboardEndDate').val();
|
||
const customerId = $('#dashboardCustomerId').val();
|
||
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/dashboard/query';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
data: {
|
||
arrivalNumber: arrivalNumber,
|
||
startDate: startDate,
|
||
endDate: endDate,
|
||
customerId: customerId
|
||
},
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
console.log('Dashboard query response:', response);
|
||
if (response && response.code === 0) {
|
||
displayDataDashboardResult(response.data);
|
||
loadTodayUnorderedCount();
|
||
showBubbleNotification(`共找到 ${response.data.length} 条记录`);
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + (response ? response.message : '未知错误'));
|
||
$('#dataDashboardTableBody').html('<tr><td colspan="10" class="text-center">查询失败</td></tr>');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to query dashboard:', error);
|
||
showBubbleNotification('查询失败: ' + error);
|
||
$('#dataDashboardTableBody').html('<tr><td colspan="10" class="text-center">查询失败</td></tr>');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 展示数据看板查询结果
|
||
function displayDataDashboardResult(data) {
|
||
const tableBody = $('#dataDashboardTableBody');
|
||
tableBody.empty();
|
||
|
||
if (!data || data.length === 0) {
|
||
tableBody.html('<tr><td colspan="10" class="text-center">无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td>${item.CustomerCode || ''}</td>`);
|
||
row.append(`<td>${item.LabelRate || '0%'}</td>`);
|
||
row.append(`<td>${item.ReplacePendingCount || 0}</td>`);
|
||
row.append(`<td>${item.BillOfLadingNumber || ''}</td>`);
|
||
row.append(`<td>${item.MasterPackageNumber || ''}</td>`);
|
||
row.append(`<td>${item.ArrivalOrderCount || 0}</td>`);
|
||
row.append(`<td>${item.ReplaceCompletedCount || 0}</td>`);
|
||
row.append(`<td>${item.NoLabelDataCount || 0}</td>`);
|
||
const arrivalTime = item.ArrivalTime ? item.ArrivalTime.replace('T', ' ') : '';
|
||
row.append(`<td>${arrivalTime}</td>`);
|
||
row.append(`<td><button class="btn btn-sm btn-primary viewDetails" data-arrival="${item.ArrivalNumber || ''}">查看详情</button></td>`);
|
||
tableBody.append(row);
|
||
});
|
||
|
||
$('.viewDetails').click(function() {
|
||
const arrival = $(this).data('arrival');
|
||
showBubbleNotification(`查看交接单 ${arrival} 的详情`);
|
||
});
|
||
}
|
||
|
||
// 加载当天扫描后未下单数量
|
||
function loadTodayUnorderedCount() {
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/dashboard/today-unordered';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
console.log('Today unordered count response:', response);
|
||
if (response && response.code === 0) {
|
||
const data = response.data;
|
||
$('#todayUnorderedCount').text(data.unorderedCount || 0);
|
||
$('#todayScanTotal').text(data.totalCount || 0);
|
||
$('#todayDate').text(data.date || '');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to load today unordered count:', error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 导出数据看板到Excel
|
||
function exportDashboardToExcel() {
|
||
let dashboardType, billOfLadingNumber, masterPackageNumber, startDate, endDate, customerId;
|
||
|
||
// 检测当前激活的标签页
|
||
if ($('#bill-of-lading-tab').hasClass('active')) {
|
||
// 提单号预报
|
||
dashboardType = 'billOfLading';
|
||
billOfLadingNumber = $('#billOfLadingNumber').val().trim();
|
||
startDate = $('#billOfLadingStartDate').val();
|
||
endDate = $('#billOfLadingEndDate').val();
|
||
customerId = $('#billOfLadingCustomerId').val();
|
||
masterPackageNumber = '';
|
||
} else if ($('#master-package-tab').hasClass('active')) {
|
||
// 大箱号预报
|
||
dashboardType = 'masterPackage';
|
||
masterPackageNumber = $('#masterPackageNumber').val().trim();
|
||
startDate = $('#masterPackageStartDate').val();
|
||
endDate = $('#masterPackageEndDate').val();
|
||
customerId = $('#masterPackageCustomerId').val();
|
||
billOfLadingNumber = '';
|
||
} else {
|
||
// 默认提单号预报
|
||
dashboardType = 'billOfLading';
|
||
billOfLadingNumber = $('#billOfLadingNumber').val().trim();
|
||
startDate = $('#billOfLadingStartDate').val();
|
||
endDate = $('#billOfLadingEndDate').val();
|
||
customerId = $('#billOfLadingCustomerId').val();
|
||
masterPackageNumber = '';
|
||
}
|
||
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/dashboard/export';
|
||
|
||
// 构建导出URL
|
||
let exportUrl = url + '?';
|
||
exportUrl += `type=${encodeURIComponent(dashboardType)}&`;
|
||
if (billOfLadingNumber) exportUrl += `billOfLadingNumber=${encodeURIComponent(billOfLadingNumber)}&`;
|
||
if (masterPackageNumber) exportUrl += `masterPackageNumber=${encodeURIComponent(masterPackageNumber)}&`;
|
||
if (startDate) exportUrl += `startDate=${encodeURIComponent(startDate)}&`;
|
||
if (endDate) exportUrl += `endDate=${encodeURIComponent(endDate)}&`;
|
||
if (customerId) exportUrl += `customerId=${encodeURIComponent(customerId)}`;
|
||
|
||
// 打开导出链接
|
||
window.open(exportUrl, '_blank');
|
||
}
|
||
|
||
// 导出运维监控数据Excel
|
||
function exportDailyStatsChineseToExcel() {
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/dashboard/daily-stats-chinese/export-excel';
|
||
|
||
// 打开导出链接
|
||
window.open(url, '_blank');
|
||
}
|
||
|
||
// 显示已上传的图片
|
||
function displayUploadedImages(containerId, imageUrls) {
|
||
const container = $('#' + containerId);
|
||
container.empty();
|
||
|
||
imageUrls.forEach(url => {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + url + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
container.append(imgDiv);
|
||
});
|
||
}
|
||
|
||
// 初始化图片粘贴和点击功能
|
||
function initImagePaste() {
|
||
// 为到货交接单POD区域添加粘贴事件
|
||
$('#uploadedArrivalPODs').on('paste', function(e) {
|
||
handlePaste(e, 'addPOD', 'uploadedArrivalPODs', function(imageUrls) {
|
||
// 处理上传后的图片URL
|
||
console.log('Arrival POD images uploaded:', imageUrls);
|
||
// 将S3 URL添加到POD链接输入框
|
||
if (imageUrls && imageUrls.length > 0) {
|
||
const currentUrls = $('#editArrivalPOD').val().trim();
|
||
const newUrls = currentUrls ? currentUrls + ',' + imageUrls.join(',') : imageUrls.join(',');
|
||
$('#editArrivalPOD').val(newUrls);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 为到货交接单POD区域添加点击事件
|
||
$('#uploadedArrivalPODs').on('click', function() {
|
||
$('#addPOD').click();
|
||
});
|
||
|
||
// 为出货交接单POD区域添加粘贴事件
|
||
$('#uploadedShippingPODs').on('paste', function(e) {
|
||
handlePaste(e, 'addShippingPOD', 'uploadedShippingPODs', function(imageUrls) {
|
||
// 处理上传后的图片URL
|
||
console.log('Shipping POD images uploaded:', imageUrls);
|
||
// 将S3 URL添加到POD链接输入框
|
||
if (imageUrls && imageUrls.length > 0) {
|
||
const currentUrls = $('#addShippingPODUrls').val().trim();
|
||
const newUrls = currentUrls ? currentUrls + ',' + imageUrls.join(',') : imageUrls.join(',');
|
||
$('#addShippingPODUrls').val(newUrls);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 为出货交接单POD区域添加点击事件
|
||
$('#uploadedShippingPODs').on('click', function() {
|
||
$('#addShippingPOD').click();
|
||
});
|
||
|
||
// 为编辑到货交接单POD区域添加粘贴事件
|
||
$('#editUploadedArrivalPODs').on('paste', function(e) {
|
||
handlePaste(e, 'editArrivalPODUpload', 'editUploadedArrivalPODs', function(imageUrls) {
|
||
// 处理上传后的图片URL
|
||
console.log('Edit Arrival POD images uploaded:', imageUrls);
|
||
// 将S3 URL添加到POD链接输入框
|
||
if (imageUrls && imageUrls.length > 0) {
|
||
const currentUrls = $('#editArrivalPOD').val().trim();
|
||
const newUrls = currentUrls ? currentUrls + ',' + imageUrls.join(',') : imageUrls.join(',');
|
||
$('#editArrivalPOD').val(newUrls);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 为编辑到货交接单POD区域添加点击事件
|
||
$('#editUploadedArrivalPODs').on('click', function(e) {
|
||
// 只有当点击的是空白区域时才触发文件选择器
|
||
if (e.target === this) {
|
||
$('#editArrivalPODUpload').click();
|
||
}
|
||
});
|
||
|
||
// 为编辑出货交接单POD区域添加粘贴事件
|
||
$('#editUploadedShippingPODs').on('paste', function(e) {
|
||
handlePaste(e, 'editShippingPOD', 'editUploadedShippingPODs', function(imageUrls) {
|
||
// 处理上传后的图片URL
|
||
console.log('Edit Shipping POD images uploaded:', imageUrls);
|
||
// 将S3 URL添加到POD链接输入框
|
||
if (imageUrls && imageUrls.length > 0) {
|
||
const currentUrls = $('#editShippingPODUrls').val().trim();
|
||
const newUrls = currentUrls ? currentUrls + ',' + imageUrls.join(',') : imageUrls.join(',');
|
||
$('#editShippingPODUrls').val(newUrls);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 为编辑出货交接单POD区域添加点击事件
|
||
$('#editUploadedShippingPODs').on('click', function(e) {
|
||
// 只有当点击的是空白区域时才触发文件选择器
|
||
if (e.target === this) {
|
||
$('#editShippingPOD').click();
|
||
}
|
||
});
|
||
}
|
||
|
||
// 处理粘贴事件
|
||
function handlePaste(e, fileInputId, containerId, callback) {
|
||
e.preventDefault(); // 阻止默认粘贴行为,避免打开文件管理
|
||
|
||
const items = e.originalEvent.clipboardData.items;
|
||
const files = [];
|
||
|
||
for (let i = 0; i < items.length; i++) {
|
||
if (items[i].type.indexOf('image') !== -1) {
|
||
const file = items[i].getAsFile();
|
||
if (file) {
|
||
files.push(file);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (files.length > 0) {
|
||
// 将粘贴的文件添加到文件输入控件
|
||
const fileInput = document.getElementById(fileInputId);
|
||
const dataTransfer = new DataTransfer();
|
||
|
||
// 保留原有文件
|
||
if (fileInput.files) {
|
||
for (let i = 0; i < fileInput.files.length; i++) {
|
||
dataTransfer.items.add(fileInput.files[i]);
|
||
}
|
||
}
|
||
|
||
// 添加新粘贴的文件
|
||
files.forEach(file => {
|
||
dataTransfer.items.add(file);
|
||
});
|
||
|
||
fileInput.files = dataTransfer.files;
|
||
|
||
// 显示预览图片(本地预览,不上传)
|
||
files.forEach(file => {
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + e.target.result + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 从文件输入控件中移除对应的文件
|
||
removeFileFromInput(fileInput, file);
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
$('#' + containerId).append(imgDiv);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
});
|
||
}
|
||
}
|
||
|
||
// 从文件输入控件中移除指定文件
|
||
function removeFileFromInput(fileInput, fileToRemove) {
|
||
const dataTransfer = new DataTransfer();
|
||
for (let i = 0; i < fileInput.files.length; i++) {
|
||
const file = fileInput.files[i];
|
||
// 通过文件名和大小来匹配文件
|
||
if (file.name !== fileToRemove.name || file.size !== fileToRemove.size) {
|
||
dataTransfer.items.add(file);
|
||
}
|
||
}
|
||
fileInput.files = dataTransfer.files;
|
||
}
|
||
|
||
$(document).ready(function() {
|
||
loadCustomerList();
|
||
|
||
// 初始化图片粘贴功能
|
||
initImagePaste();
|
||
|
||
// POD 预览按钮点击事件
|
||
$(document).on('click', '.preview-pod-btn', function() {
|
||
const pod = $(this).data('pod');
|
||
const previewContent = $('#podPreviewContent');
|
||
|
||
// 清空预览内容
|
||
previewContent.empty();
|
||
|
||
// 检查 POD 是否包含多个链接(逗号分隔)
|
||
const podItems = pod.split(',').map(item => item.trim());
|
||
|
||
if (podItems.length > 1) {
|
||
// 多个 POD 链接,显示为图片列表
|
||
const gallery = $('<div class="row"></div>');
|
||
podItems.forEach(item => {
|
||
if (item) {
|
||
if (item.startsWith('http')) {
|
||
// 图片链接
|
||
const col = $('<div class="col-md-6 mb-3"></div>');
|
||
const img = $('<img>').attr('src', item).addClass('img-fluid rounded').css('max-height', '300px');
|
||
col.append(img);
|
||
gallery.append(col);
|
||
} else {
|
||
// 文本内容
|
||
const col = $('<div class="col-md-12 mb-3"></div>');
|
||
const p = $('<p>').text(item).addClass('border p-3 rounded bg-light');
|
||
col.append(p);
|
||
gallery.append(col);
|
||
}
|
||
}
|
||
});
|
||
previewContent.append(gallery);
|
||
} else if (podItems.length === 1 && podItems[0]) {
|
||
const item = podItems[0];
|
||
if (item.startsWith('http')) {
|
||
// 单个图片链接
|
||
const img = $('<img>').attr('src', item).addClass('img-fluid rounded').css('max-height', '500px');
|
||
previewContent.append(img);
|
||
} else {
|
||
// 单个文本内容
|
||
const p = $('<p>').text(item).addClass('border p-3 rounded bg-light');
|
||
previewContent.append(p);
|
||
}
|
||
} else {
|
||
// 空 POD
|
||
previewContent.append('<p class="text-muted">无 POD 内容</p>');
|
||
}
|
||
|
||
// 显示模态框
|
||
$('#podPreviewModal').modal('show');
|
||
});
|
||
|
||
// 保存编辑按钮点击事件
|
||
$('#saveEditBtn').click(function() {
|
||
saveShippingHandoverEdit();
|
||
});
|
||
|
||
// 保存到货交接单编辑按钮点击事件
|
||
$('#saveArrivalEditBtn').click(function() {
|
||
saveArrivalHandoverEdit();
|
||
});
|
||
|
||
// 为文件选择器添加变化事件,显示预览图片
|
||
$('#addPOD').change(function(e) {
|
||
const files = e.target.files;
|
||
const containerId = 'uploadedArrivalPODs';
|
||
|
||
if (files.length > 0) {
|
||
// 清空容器
|
||
$('#' + containerId).empty();
|
||
|
||
// 显示预览图片
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + e.target.result + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 从文件输入控件中移除对应的文件
|
||
removeFileFromInput(e.target, file);
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
$('#' + containerId).append(imgDiv);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 为出货交接单的文件选择器添加变化事件
|
||
$('#addShippingPOD').change(function(e) {
|
||
const files = e.target.files;
|
||
const containerId = 'uploadedShippingPODs';
|
||
|
||
if (files.length > 0) {
|
||
// 清空容器
|
||
$('#' + containerId).empty();
|
||
|
||
// 显示预览图片
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + e.target.result + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 从文件输入控件中移除对应的文件
|
||
removeFileFromInput(e.target, file);
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
$('#' + containerId).append(imgDiv);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 为编辑到货交接单的文件选择器添加变化事件
|
||
$('#editArrivalPODUpload').change(function(e) {
|
||
const files = e.target.files;
|
||
const containerId = 'editUploadedArrivalPODs';
|
||
|
||
if (files.length > 0) {
|
||
// 清空容器
|
||
$('#' + containerId).empty();
|
||
|
||
// 显示预览图片
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + e.target.result + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 从文件输入控件中移除对应的文件
|
||
removeFileFromInput(e.target, file);
|
||
// 更新POD链接输入框
|
||
updateEditArrivalPODUrls();
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
$('#' + containerId).append(imgDiv);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 为编辑出货交接单的文件选择器添加变化事件
|
||
$('#editShippingPOD').change(function(e) {
|
||
const files = e.target.files;
|
||
const containerId = 'editUploadedShippingPODs';
|
||
|
||
if (files.length > 0) {
|
||
// 清空容器
|
||
$('#' + containerId).empty();
|
||
|
||
// 显示预览图片
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const reader = new FileReader();
|
||
reader.onload = function(e) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + e.target.result + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 从文件输入控件中移除对应的文件
|
||
removeFileFromInput(e.target, file);
|
||
// 更新POD链接输入框
|
||
updateEditShippingPODUrls();
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
$('#' + containerId).append(imgDiv);
|
||
};
|
||
reader.readAsDataURL(file);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 监听每页记录数选择变化
|
||
$('#pageSize').change(function() {
|
||
if ($(this).val() === 'custom') {
|
||
$('#customPageSizeContainer').show();
|
||
} else {
|
||
$('#customPageSizeContainer').hide();
|
||
}
|
||
});
|
||
|
||
// 监听扫描记录查询每页记录数选择变化
|
||
$('#scanPageSize').change(function() {
|
||
if ($(this).val() === 'custom') {
|
||
$('#customScanPageSizeContainer').show();
|
||
} else {
|
||
$('#customScanPageSizeContainer').hide();
|
||
}
|
||
});
|
||
|
||
// 监听到货交接单查询每页记录数选择变化
|
||
$('#arrivalPageSize').change(function() {
|
||
if ($(this).val() === 'custom') {
|
||
$('#customArrivalPageSizeContainer').show();
|
||
} else {
|
||
$('#customArrivalPageSizeContainer').hide();
|
||
}
|
||
});
|
||
|
||
// 监听出货交接单查询每页记录数选择变化
|
||
$('#shippingPageSize').change(function() {
|
||
if ($(this).val() === 'custom') {
|
||
$('#customShippingPageSizeContainer').show();
|
||
} else {
|
||
$('#customShippingPageSizeContainer').hide();
|
||
}
|
||
});
|
||
|
||
// 添加到货交接单表单提交
|
||
$('#addArrivalHandoverForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const handoverNumbers = $('#addHandoverNumber').val().trim().split('\n').filter(hn => hn.trim() !== '');
|
||
const logisticsProviderArrivalTime = $('#addLogisticsProviderArrivalTime').val();
|
||
const receiptTime = $('#addReceiptTime').val();
|
||
const files = $('#addPOD')[0].files;
|
||
const remarks = $('#addRemarks').val().trim();
|
||
const timezone = $('#timezone').val();
|
||
|
||
if (handoverNumbers.length === 0) {
|
||
showBubbleNotification('请输入至少一个交接单号');
|
||
return;
|
||
}
|
||
|
||
// 处理每个交接单号
|
||
handoverNumbers.forEach(handoverNumber => {
|
||
let pod = '';
|
||
let uniqueIds = [];
|
||
|
||
// 如果有文件上传,预生成S3链接
|
||
if (files.length > 0) {
|
||
// 预生成S3链接
|
||
const preGeneratedUrls = [];
|
||
uniqueIds = [];
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const uniqueId = generateGuid();
|
||
uniqueIds.push(uniqueId);
|
||
const preGeneratedUrl = generateS3Url('arrival', handoverNumber, file.name, uniqueId);
|
||
preGeneratedUrls.push(preGeneratedUrl);
|
||
}
|
||
|
||
// 将预生成的链接添加到POD链接输入框
|
||
pod = preGeneratedUrls.join(',');
|
||
}
|
||
|
||
// 先处理到货交接单添加(不带POD)
|
||
processArrivalHandoverForm(handoverNumber, logisticsProviderArrivalTime, receiptTime, pod, remarks, timezone, function() {
|
||
// 成功创建到货交接单后上传图片
|
||
if (files.length > 0) {
|
||
// 上传图片完成后再更新POD字段
|
||
setTimeout(function() {
|
||
uploadFilesWithForm(files, 'arrival', handoverNumber, uniqueIds);
|
||
}, 1000); // 延迟1秒,确保图片上传完成
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
// 处理单个到货交接单添加
|
||
function processArrivalHandoverForm(handoverNumber, logisticsProviderArrivalTime, receiptTime, pod, remarks, timezone, callback) {
|
||
const url = getBaseUrl() + '/api/arrival-handover/create';
|
||
|
||
// 构建请求数据
|
||
const data = {
|
||
HandoverNumber: handoverNumber,
|
||
LogisticsProviderArrivalTime: logisticsProviderArrivalTime,
|
||
ReceiptTime: receiptTime,
|
||
Remarks: remarks,
|
||
Creator: 'system',
|
||
TimeZone: timezone
|
||
};
|
||
|
||
// 只有当 POD 不为空时才传递
|
||
if (pod && pod.trim() !== '') {
|
||
data.POD = pod;
|
||
}
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'createArrivalHandoverCallback',
|
||
data: data,
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('成功添加到货交接单');
|
||
// 清空表单
|
||
$('#addArrivalHandoverForm')[0].reset();
|
||
$('#uploadedArrivalPODs').empty();
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
// 执行回调函数
|
||
if (typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
} else {
|
||
showBubbleNotification('添加失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 处理到货交接单批量添加
|
||
function processArrivalHandoverForms(handoverNumbers, logisticsProviderArrivalTime, receiptTime, pod, remarks, timezone, callback) {
|
||
// 批量添加到货交接单
|
||
const promises = handoverNumbers.map(async (handoverNumber) => {
|
||
const url = getBaseUrl() + '/api/arrival-handover/create';
|
||
|
||
// 构建请求数据
|
||
const data = {
|
||
HandoverNumber: handoverNumber,
|
||
LogisticsProviderArrivalTime: logisticsProviderArrivalTime,
|
||
ReceiptTime: receiptTime,
|
||
Remarks: remarks,
|
||
Creator: 'system',
|
||
TimeZone: timezone
|
||
};
|
||
|
||
// 只有当 POD 不为空时才传递
|
||
if (pod && pod.trim() !== '') {
|
||
data.POD = pod;
|
||
}
|
||
|
||
return new Promise((resolve, reject) => {
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'createArrivalHandoverCallback',
|
||
data: data,
|
||
success: function(response) {
|
||
resolve(response);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
reject(error);
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
Promise.all(promises)
|
||
.then(results => {
|
||
showBubbleNotification(`成功添加 ${handoverNumbers.length} 个到货交接单`);
|
||
// 清空表单
|
||
$('#addArrivalHandoverForm')[0].reset();
|
||
$('#uploadedArrivalPODs').empty();
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
// 执行回调函数
|
||
if (typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
})
|
||
.catch(error => {
|
||
showBubbleNotification('添加失败: ' + error);
|
||
});
|
||
}
|
||
|
||
// 创建到货交接单回调函数
|
||
function createArrivalHandoverCallback(response) {
|
||
// 回调函数处理
|
||
}
|
||
|
||
// 查询到货交接单表单提交
|
||
$('#arrivalHandoverForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const page = 1;
|
||
const pageSize = $('#arrivalPageSize').val() === 'custom' ? $('#customArrivalPageSize').val() : $('#arrivalPageSize').val();
|
||
const sortBy = $('#arrivalSortBy').val();
|
||
const sortOrder = $('#arrivalSortOrder').val();
|
||
const handoverNumber = $('#handoverNumber').val().trim().replace(/\s+/g, ','); // 将多行输入转换为逗号分隔的字符串
|
||
|
||
const url = getBaseUrl() + '/api/arrival-handover/list';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'getArrivalHandoverListCallback',
|
||
data: {
|
||
page: page,
|
||
pageSize: pageSize,
|
||
sortBy: sortBy,
|
||
sortOrder: sortOrder,
|
||
handoverNumber: handoverNumber
|
||
},
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
renderArrivalHandoverTable(response.data.forms);
|
||
// 渲染分页
|
||
showBubbleNotification('共找到 ' + response.data.totalCount + ' 条记录');
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 获取到货交接单列表回调函数
|
||
function getArrivalHandoverListCallback(response) {
|
||
if (response.code === 0) {
|
||
renderArrivalHandoverTable(response.data.forms);
|
||
// 渲染分页
|
||
showBubbleNotification('共找到 ' + response.data.totalCount + ' 条记录');
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 重置到货交接单表单
|
||
$('#resetArrivalHandoverForm').click(function() {
|
||
$('#arrivalHandoverForm')[0].reset();
|
||
});
|
||
|
||
// 全选/取消全选到货交接单
|
||
$('#selectAllHandoverForms').change(function() {
|
||
const isChecked = $(this).prop('checked');
|
||
$('.handover-form-checkbox').prop('checked', isChecked);
|
||
});
|
||
|
||
// 批量删除到货交接单
|
||
$('#deleteSelectedHandoverForms').click(function() {
|
||
const selectedIds = [];
|
||
$('.handover-form-checkbox:checked').each(function() {
|
||
selectedIds.push($(this).data('id'));
|
||
});
|
||
|
||
if (selectedIds.length === 0) {
|
||
showBubbleNotification('请选择要删除的到货交接单');
|
||
return;
|
||
}
|
||
|
||
if (confirm('确定要删除选中的到货交接单吗?')) {
|
||
selectedIds.forEach(id => {
|
||
const url = getBaseUrl() + '/api/arrival-handover/delete/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'deleteArrivalHandoverCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
});
|
||
|
||
// 删除到货交接单回调函数
|
||
function deleteArrivalHandoverCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 添加出货交接单表单提交
|
||
$('#addShippingHandoverForm').submit(function(e) {
|
||
e.preventDefault();
|
||
let handoverNumber = $('#addShippingHandoverNumber').val().trim();
|
||
const channel = $('#addChannel').val();
|
||
const deliveryTime = $('#addDeliveryTime').val();
|
||
const files = $('#addShippingPOD')[0].files;
|
||
const podUrls = $('#addShippingPODUrls').val().trim();
|
||
const remarks = $('#addShippingRemarks').val().trim();
|
||
const timezone = $('#shippingTimezone').val();
|
||
|
||
// 验证渠道是否选择
|
||
if (!channel) {
|
||
showBubbleNotification('请选择渠道');
|
||
return;
|
||
}
|
||
|
||
// 生成交接单号(如果未提供)
|
||
if (!handoverNumber) {
|
||
$.ajax({
|
||
url: getBaseUrl() + '/api/shipping-handover/generate-number',
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'generateShippingHandoverNumberCallback',
|
||
data: { channel: channel },
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
handoverNumber = response.data;
|
||
$('#addShippingHandoverNumber').val(handoverNumber);
|
||
processFormWithHandoverNumber(handoverNumber, channel, deliveryTime, files, podUrls, remarks, timezone);
|
||
} else {
|
||
showBubbleNotification('生成交接单号失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('生成交接单号失败: ' + error);
|
||
}
|
||
});
|
||
} else {
|
||
processFormWithHandoverNumber(handoverNumber, channel, deliveryTime, files, podUrls, remarks, timezone);
|
||
}
|
||
});
|
||
|
||
// 处理表单提交(带交接单号)
|
||
function processFormWithHandoverNumber(handoverNumber, channel, deliveryTime, files, podUrls, remarks, timezone) {
|
||
// 优先使用直接输入的POD链接
|
||
let pod = podUrls || '';
|
||
let uniqueIds = [];
|
||
|
||
// 如果有文件上传,预生成S3链接
|
||
if (files.length > 0 && !pod) {
|
||
// 预生成S3链接
|
||
const preGeneratedUrls = [];
|
||
uniqueIds = [];
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const uniqueId = generateGuid();
|
||
uniqueIds.push(uniqueId);
|
||
const preGeneratedUrl = generateS3Url('shipping', handoverNumber, file.name, uniqueId);
|
||
preGeneratedUrls.push(preGeneratedUrl);
|
||
}
|
||
|
||
// 将预生成的链接添加到POD链接输入框
|
||
pod = preGeneratedUrls.join(',');
|
||
$('#addShippingPODUrls').val(pod);
|
||
}
|
||
|
||
// 先处理出货交接单添加(不带POD)
|
||
processShippingHandoverForm(handoverNumber, channel, deliveryTime, '', remarks, timezone, function() {
|
||
// 成功创建出货交接单后上传图片
|
||
if (files.length > 0) {
|
||
// 上传图片完成后再更新POD字段
|
||
setTimeout(function() {
|
||
uploadFilesWithForm(files, 'shipping', handoverNumber, uniqueIds);
|
||
// 上传完成后更新POD字段
|
||
if (pod) {
|
||
updateShippingHandoverFormPOD(handoverNumber, pod);
|
||
}
|
||
}, 1000); // 延迟1秒,确保图片上传完成
|
||
} else if (pod) {
|
||
// 没有文件上传但有POD链接,直接更新
|
||
updateShippingHandoverFormPOD(handoverNumber, pod);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 生成对象键
|
||
function generateObjectKey(handoverNumber, uniqueId, fileName, type) {
|
||
const yearMonth = new Date().toISOString().slice(0, 7).replace('-', '');
|
||
let prefix = '';
|
||
|
||
if (type === 'arrival') {
|
||
prefix = `arrivalhandover/${yearMonth}/`;
|
||
} else if (type === 'shipping') {
|
||
prefix = `shippinghandover/${yearMonth}/`;
|
||
} else {
|
||
prefix = 'pod/';
|
||
}
|
||
|
||
return `${prefix}${handoverNumber}_${uniqueId}_${fileName}`;
|
||
}
|
||
|
||
// 处理出货交接单添加
|
||
function processShippingHandoverForm(handoverNumber, channel, deliveryTime, pod, remarks, timezone, callback) {
|
||
const url = getBaseUrl() + '/api/shipping-handover/create';
|
||
|
||
// 构建请求数据,只传递非空字段
|
||
const data = {
|
||
HandoverNumber: handoverNumber,
|
||
Channel: channel,
|
||
DeliveryTime: deliveryTime,
|
||
Creator: 'system',
|
||
TimeZone: timezone
|
||
};
|
||
|
||
// 只有当 POD 不为空时才传递
|
||
if (pod && pod.trim() !== '') {
|
||
data.POD = pod;
|
||
}
|
||
|
||
// 只有当 Remarks 不为空时才传递
|
||
if (remarks && remarks.trim() !== '') {
|
||
data.Remarks = remarks;
|
||
}
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'createShippingHandoverCallback',
|
||
data: data,
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('成功添加出货交接单');
|
||
// 清空表单
|
||
$('#addShippingHandoverForm')[0].reset();
|
||
$('#uploadedShippingPODs').empty();
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
// 执行回调函数
|
||
if (typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
} else {
|
||
showBubbleNotification('添加失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新出货交接单POD字段
|
||
function updateShippingHandoverFormPOD(handoverNumber, podLinks, callback) {
|
||
const url = getBaseUrl() + '/api/shipping-handover/update-pod';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'updateShippingHandoverFormPODCallback',
|
||
data: {
|
||
handoverNumber: handoverNumber,
|
||
podLinks: podLinks
|
||
},
|
||
success: function(response) {
|
||
if (typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新出货交接单POD回调函数
|
||
function updateShippingHandoverFormPODCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('成功更新POD字段');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新POD失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 更新到货交接单POD字段
|
||
function updateArrivalHandoverFormPOD(handoverNumber, podLinks, callback) {
|
||
// 先获取到货交接单ID
|
||
const getUrl = getBaseUrl() + '/api/arrival-handover/get-by-number/' + handoverNumber;
|
||
|
||
$.ajax({
|
||
url: getUrl,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'getArrivalHandoverFormByNumberCallback',
|
||
success: function(response) {
|
||
if (response.code === 0 && response.data) {
|
||
const formId = response.data.id;
|
||
// 更新POD字段
|
||
const updateUrl = getBaseUrl() + '/api/arrival-handover/update/' + formId;
|
||
|
||
$.ajax({
|
||
url: updateUrl,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'updateArrivalHandoverFormCallback',
|
||
data: {
|
||
POD: podLinks
|
||
},
|
||
success: function(response) {
|
||
if (typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
} else {
|
||
showBubbleNotification('获取到货交接单失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 获取到货交接单回调函数
|
||
function getArrivalHandoverFormByNumberCallback(response) {
|
||
// 回调函数处理
|
||
}
|
||
|
||
// 更新到货交接单回调函数
|
||
function updateArrivalHandoverFormCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('成功更新到货交接单');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 创建出货交接单回调函数
|
||
function createShippingHandoverCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('成功添加出货交接单');
|
||
// 清空表单
|
||
$('#addShippingHandoverForm')[0].reset();
|
||
$('#uploadedShippingPODs').empty();
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('添加失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 生成出货交接单号
|
||
$('#generateShippingHandoverNumber').click(function() {
|
||
const channel = $('#addChannel').val();
|
||
if (!channel) {
|
||
showBubbleNotification('请先选择渠道');
|
||
return;
|
||
}
|
||
|
||
const url = getBaseUrl() + '/api/shipping-handover/generate-number';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'generateShippingHandoverNumberCallback',
|
||
data: {
|
||
channel: channel
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 查询出货交接单表单提交
|
||
$('#shippingHandoverForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const page = 1;
|
||
const pageSize = $('#shippingPageSize').val() === 'custom' ? $('#customShippingPageSize').val() : $('#shippingPageSize').val();
|
||
const sortBy = $('#shippingSortBy').val();
|
||
const sortOrder = $('#shippingSortOrder').val();
|
||
const handoverNumber = $('#shippingHandoverNumber').val().trim();
|
||
const channel = $('#shippingChannel').val();
|
||
const creator = $('#shippingCreator').val().trim();
|
||
const startDeliveryTime = $('#startDeliveryTime').val();
|
||
const endDeliveryTime = $('#endDeliveryTime').val();
|
||
|
||
const url = getBaseUrl() + '/api/shipping-handover/list';
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'getShippingHandoverListCallback',
|
||
data: {
|
||
page: page,
|
||
pageSize: pageSize,
|
||
sortBy: sortBy,
|
||
sortOrder: sortOrder,
|
||
handoverNumber: handoverNumber,
|
||
channel: channel,
|
||
creator: creator,
|
||
startDeliveryTime: startDeliveryTime,
|
||
endDeliveryTime: endDeliveryTime
|
||
},
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
renderShippingHandoverTable(response.data.forms);
|
||
// 渲染分页
|
||
showBubbleNotification('共找到 ' + response.data.totalCount + ' 条记录');
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 获取出货交接单列表回调函数
|
||
function getShippingHandoverListCallback(response) {
|
||
if (response.code === 0) {
|
||
renderShippingHandoverTable(response.data.forms);
|
||
// 渲染分页
|
||
showBubbleNotification('共找到 ' + response.data.totalCount + ' 条记录');
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 重置出货交接单表单
|
||
$('#resetShippingHandoverForm').click(function() {
|
||
$('#shippingHandoverForm')[0].reset();
|
||
});
|
||
|
||
// 全选/取消全选出货交接单
|
||
$('#selectAllShippingHandoverForms').change(function() {
|
||
const isChecked = $(this).prop('checked');
|
||
$('.shipping-handover-form-checkbox').prop('checked', isChecked);
|
||
});
|
||
|
||
// 批量删除出货交接单
|
||
$('#deleteSelectedShippingHandoverForms').click(function() {
|
||
const selectedIds = [];
|
||
$('.shipping-handover-form-checkbox:checked').each(function() {
|
||
selectedIds.push($(this).data('id'));
|
||
});
|
||
|
||
if (selectedIds.length === 0) {
|
||
showBubbleNotification('请选择要删除的出货交接单');
|
||
return;
|
||
}
|
||
|
||
if (confirm('确定要删除选中的出货交接单吗?')) {
|
||
selectedIds.forEach(id => {
|
||
const url = getBaseUrl() + '/api/shipping-handover/delete/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'deleteShippingHandoverCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
});
|
||
|
||
// 删除出货交接单回调函数
|
||
function deleteShippingHandoverCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 关联袋牌表单提交
|
||
$('#associateBagTagsForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const shippingHandoverFormId = $('#shippingHandoverFormId').val();
|
||
const bagTagNumbers = $('#bagTagNumbers').val().trim().split('\n').filter(tag => tag.trim() !== '');
|
||
|
||
if (!shippingHandoverFormId) {
|
||
showBubbleNotification('请输入出货交接单ID');
|
||
return;
|
||
}
|
||
|
||
if (bagTagNumbers.length === 0) {
|
||
showBubbleNotification('请输入至少一个袋牌号');
|
||
return;
|
||
}
|
||
|
||
// 先获取出货交接单的详情,包括渠道信息
|
||
const shippingHandoverUrl = getBaseUrl() + '/api/shipping-handover/get/' + shippingHandoverFormId;
|
||
|
||
$.ajax({
|
||
url: shippingHandoverUrl,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(shippingHandoverResponse) {
|
||
if (shippingHandoverResponse.code === 0) {
|
||
const shippingHandoverChannel = shippingHandoverResponse.data.Channel;
|
||
|
||
// 验证所有袋牌的渠道是否与出货交接单的渠道一致
|
||
let allChannelsMatch = true;
|
||
let mismatchedBagTags = [];
|
||
|
||
// 遍历袋牌号码,验证渠道
|
||
let validatedBagTags = 0;
|
||
let existingBagTags = [];
|
||
|
||
bagTagNumbers.forEach(bagTagNumber => {
|
||
const bagTagUrl = getBaseUrl() + '/api/bagtag/' + bagTagNumber;
|
||
|
||
$.ajax({
|
||
url: bagTagUrl,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(bagTagResponse) {
|
||
validatedBagTags++;
|
||
|
||
if (bagTagResponse.code === 0) {
|
||
const bagTagChannel = bagTagResponse.data.ChannelName;
|
||
const bagTagStatus = bagTagResponse.data.Status;
|
||
|
||
if (bagTagChannel !== shippingHandoverChannel) {
|
||
allChannelsMatch = false;
|
||
mismatchedBagTags.push(bagTagNumber + ' (渠道不一致)');
|
||
} else {
|
||
existingBagTags.push(bagTagNumber);
|
||
}
|
||
} else {
|
||
allChannelsMatch = false;
|
||
mismatchedBagTags.push(bagTagNumber + ' (袋牌不存在)');
|
||
}
|
||
|
||
// 当所有袋牌都验证完成后
|
||
if (validatedBagTags === bagTagNumbers.length) {
|
||
if (allChannelsMatch) {
|
||
// 所有袋牌渠道都匹配,执行关联操作
|
||
const associateUrl = getBaseUrl() + '/api/shipping-handover/bag-tag/associate-by-number/' + shippingHandoverFormId;
|
||
|
||
$.ajax({
|
||
url: associateUrl,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'associateBagTagsCallback',
|
||
data: {
|
||
bagTagNumbers: existingBagTags.join(',')
|
||
},
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification(`成功关联 ${existingBagTags.length} 个袋牌`);
|
||
// 清空表单
|
||
$('#associateBagTagsForm')[0].reset();
|
||
} else {
|
||
showBubbleNotification('关联失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
} else {
|
||
// 有袋牌渠道不匹配或不存在,显示错误信息
|
||
showBubbleNotification('关联失败: ' + mismatchedBagTags.join(', '));
|
||
}
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
validatedBagTags++;
|
||
allChannelsMatch = false;
|
||
mismatchedBagTags.push(bagTagNumber + ' (获取袋牌信息失败)');
|
||
|
||
// 当所有袋牌都验证完成后
|
||
if (validatedBagTags === bagTagNumbers.length) {
|
||
showBubbleNotification('关联失败: ' + mismatchedBagTags.join(', '));
|
||
}
|
||
}
|
||
});
|
||
});
|
||
} else {
|
||
showBubbleNotification('获取出货交接单详情失败: ' + shippingHandoverResponse.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('获取出货交接单详情失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 关联袋牌回调函数
|
||
function associateBagTagsCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification(`成功关联袋牌`);
|
||
// 清空表单
|
||
$('#associateBagTagsForm')[0].reset();
|
||
} else {
|
||
showBubbleNotification('关联失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 查询关联袋牌表单提交
|
||
$('#queryAssociatedBagTagsForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const shippingHandoverFormId = $('#queryShippingHandoverFormId').val();
|
||
|
||
if (!shippingHandoverFormId) {
|
||
showBubbleNotification('请输入出货交接单ID');
|
||
return;
|
||
}
|
||
|
||
const url = getBaseUrl() + '/api/shipping-handover/bag-tag/list/' + shippingHandoverFormId;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'queryAssociatedBagTagsCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification(`共找到 ${response.data.length} 个关联袋牌`);
|
||
// 显示袋牌列表
|
||
alert('关联袋牌列表:\n' + response.data.map(tag => tag.TagNumber).join('\n'));
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 查询关联袋牌回调函数
|
||
function queryAssociatedBagTagsCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification(`共找到 ${response.data.length} 个关联袋牌`);
|
||
// 显示袋牌列表
|
||
alert('关联袋牌列表:\n' + response.data.map(tag => tag.TagNumber).join('\n'));
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 查询袋牌回调函数(用于表格中的查询袋牌按钮)
|
||
function queryBagTagsCallback(response) {
|
||
// 此回调函数在 ajax 调用中直接处理响应,不需要在这里重复处理
|
||
}
|
||
});
|
||
|
||
// 渲染到货交接单表格
|
||
function renderArrivalHandoverTable(forms) {
|
||
const tableBody = $('#arrivalHandoverTableBody');
|
||
tableBody.empty();
|
||
|
||
if (forms && forms.length > 0) {
|
||
forms.forEach(form => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td><input type="checkbox" class="handover-form-checkbox" data-id="${form.Id}"></td>`);
|
||
row.append(`<td>${form.Id}</td>`);
|
||
|
||
// 添加客户简称列,初始显示加载中
|
||
const customerCell = $('<td>加载中...</td>');
|
||
row.append(customerCell);
|
||
|
||
row.append(`<td>${form.HandoverNumber}</td>`);
|
||
row.append(`<td>${form.LogisticsProviderArrivalTime ? new Date(form.LogisticsProviderArrivalTime).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${form.ReceiptTime ? new Date(form.ReceiptTime).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${form.POD && form.POD.trim() !== '' ? '<span class="text-success">有并支持查看预览</span> <button class="btn btn-sm btn-info ml-2 preview-pod-btn" data-pod="' + form.POD + '">预览</button>' : '无'}</td>`);
|
||
row.append(`<td>${form.Remarks || '-'}</td>`);
|
||
row.append(`<td>${form.Creator}</td>`);
|
||
row.append(`<td>${new Date(form.CreatedAt).toLocaleString()}</td>`);
|
||
row.append(`<td>${form.TimeZone || '-'}</td>`);
|
||
row.append(`<td class="d-flex flex-wrap gap-1">
|
||
<button class="btn btn-sm btn-primary arrival-edit-btn" data-id="${form.Id}">编辑</button>
|
||
<button class="btn btn-sm btn-danger arrival-delete-btn" data-id="${form.Id}">删除</button>
|
||
</td>`);
|
||
|
||
tableBody.append(row);
|
||
|
||
// 异步获取客户简称
|
||
fetchCustomerAbbreviation(form.HandoverNumber, customerCell);
|
||
});
|
||
|
||
// 添加事件处理程序
|
||
$('.arrival-edit-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
editArrivalHandoverForm(id);
|
||
});
|
||
|
||
$('.arrival-delete-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
if (confirm('确定要删除到货交接单 ID: ' + id + ' 吗?')) {
|
||
const url = getBaseUrl() + '/api/arrival-handover/delete/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'deleteArrivalHandoverCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
tableBody.append('<tr><td colspan="12" class="text-center">暂无数据</td></tr>');
|
||
}
|
||
}
|
||
|
||
// 获取客户简称
|
||
function fetchCustomerAbbreviation(handoverNumber, cell) {
|
||
const baseUrl = getBaseUrl();
|
||
|
||
// 先尝试通过BillOfLadingNumber查询
|
||
let url = baseUrl + '/api/Label/label-replace/batch?page=1&pageSize=1&billOfLadingNumber=' + handoverNumber;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
if (response.status === 'ok' && response.data && response.data.length > 0) {
|
||
// 找到记录,获取CustomerCode
|
||
const customerCode = response.data[0].CustomerCode;
|
||
if (customerCode) {
|
||
cell.text(customerCode);
|
||
} else {
|
||
// 尝试通过MasterPackageNumber查询
|
||
fetchByMasterPackageNumber(handoverNumber, cell);
|
||
}
|
||
} else {
|
||
// 尝试通过MasterPackageNumber查询
|
||
fetchByMasterPackageNumber(handoverNumber, cell);
|
||
}
|
||
},
|
||
error: function() {
|
||
// 尝试通过MasterPackageNumber查询
|
||
fetchByMasterPackageNumber(handoverNumber, cell);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 通过MasterPackageNumber查询
|
||
function fetchByMasterPackageNumber(handoverNumber, cell) {
|
||
const baseUrl = getBaseUrl();
|
||
const url = baseUrl + '/api/Label/label-replace/batch?page=1&pageSize=1&masterPackageNumber=' + handoverNumber;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
if (response.status === 'ok' && response.data && response.data.length > 0) {
|
||
// 找到记录,获取CustomerCode
|
||
const customerCode = response.data[0].CustomerCode;
|
||
if (customerCode) {
|
||
cell.text(customerCode);
|
||
} else {
|
||
cell.text('-');
|
||
}
|
||
} else {
|
||
cell.text('-');
|
||
}
|
||
},
|
||
error: function() {
|
||
cell.text('-');
|
||
}
|
||
});
|
||
}
|
||
|
||
// 渲染出货交接单表格
|
||
function renderShippingHandoverTable(forms) {
|
||
const tableBody = $('#shippingHandoverTableBody');
|
||
tableBody.empty();
|
||
|
||
if (forms && forms.length > 0) {
|
||
forms.forEach(form => {
|
||
// 创建行元素
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td><input type="checkbox" class="shipping-handover-form-checkbox" data-id="${form.Id}"></td>`);
|
||
row.append(`<td>${form.Id}</td>`);
|
||
row.append(`<td>${form.HandoverNumber}</td>`);
|
||
|
||
// 添加箱数和交货单量的占位符
|
||
const boxCountCell = $('<td>加载中...</td>');
|
||
const orderCountCell = $('<td>加载中...</td>');
|
||
row.append(boxCountCell);
|
||
row.append(orderCountCell);
|
||
|
||
row.append(`<td>${form.Channel}</td>`);
|
||
row.append(`<td>${form.DeliveryTime ? new Date(form.DeliveryTime).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${form.TimeZone || '-'}</td>`);
|
||
row.append(`<td>${form.POD ? '<span class="text-success">有并支持查看预览</span> <button class="btn btn-sm btn-info ml-2 preview-pod-btn" data-pod="' + form.POD + '">预览</button>' : '无'}</td>`);
|
||
row.append(`<td>${form.Remarks || '-'}</td>`);
|
||
row.append(`<td>${form.Creator}</td>`);
|
||
row.append(`<td>${new Date(form.CreatedAt).toLocaleString()}</td>`);
|
||
row.append(`<td class="d-flex flex-wrap gap-1">
|
||
<button class="btn btn-sm btn-primary edit-btn" data-id="${form.Id}">编辑</button>
|
||
<button class="btn btn-sm btn-danger delete-btn" data-id="${form.Id}">删除</button>
|
||
<button class="btn btn-sm btn-success query-bag-tags-btn" data-id="${form.Id}">查询袋牌</button>
|
||
</td>`);
|
||
|
||
tableBody.append(row);
|
||
|
||
// 加载箱数和交货单量
|
||
loadBagTagAndPackageCount(form.Id, boxCountCell, orderCountCell);
|
||
});
|
||
|
||
// 添加事件处理程序
|
||
$('.edit-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
editShippingHandoverForm(id);
|
||
});
|
||
|
||
$('.delete-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
if (confirm('确定要删除出货交接单 ID: ' + id + ' 吗?')) {
|
||
const url = getBaseUrl() + '/api/shipping-handover/delete/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'deleteShippingHandoverCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('删除成功');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
|
||
$('.query-bag-tags-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
const row = $(this).closest('tr');
|
||
const bagTagRow = row.next('.bag-tag-detail-row');
|
||
|
||
if (bagTagRow.length > 0) {
|
||
// 切换袋牌明细行的显示状态
|
||
bagTagRow.toggle();
|
||
$(this).text(bagTagRow.is(':visible') ? '收起袋牌' : '查询袋牌');
|
||
} else {
|
||
// 加载袋牌数据并创建明细行
|
||
const url = getBaseUrl() + '/api/shipping-handover/bag-tag/list/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'queryBagTagsCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
const bagTags = response.data;
|
||
if (bagTags && bagTags.length > 0) {
|
||
// 创建袋牌明细行
|
||
const newBagTagRow = $('<tr class="bag-tag-detail-row"></tr>');
|
||
newBagTagRow.append(`<td colspan="12">
|
||
<div class="p-3 bg-light rounded">
|
||
<h6 class="mb-2">交接单 ID: ${id} 关联的袋牌</h6>
|
||
<div class="table-responsive">
|
||
<table class="table table-sm table-striped">
|
||
<thead>
|
||
<tr>
|
||
<th>袋牌号码</th>
|
||
<th>小包数量</th>
|
||
<th>状态</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>打开时间</th>
|
||
<th>关闭时间</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
${bagTags.map(tag => `
|
||
<tr>
|
||
<td>${tag.TagNumber || '-'}</td>
|
||
<td>${tag.WaybillCount || 0}</td>
|
||
<td>${tag.Status || '-'}</td>
|
||
<td>${tag.Creator || '-'}</td>
|
||
<td>${tag.CreatedAt ? new Date(tag.CreatedAt).toLocaleString() : '-'}</td>
|
||
<td>${tag.OpenedAt ? new Date(tag.OpenedAt).toLocaleString() : '-'}</td>
|
||
<td>${tag.ClosedAt ? new Date(tag.ClosedAt).toLocaleString() : '-'}</td>
|
||
</tr>
|
||
`).join('')}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</td>`);
|
||
row.after(newBagTagRow);
|
||
// 显示明细行
|
||
newBagTagRow.show();
|
||
// 更新按钮文本
|
||
$('.query-bag-tags-btn[data-id="' + id + '"]').text('收起袋牌');
|
||
} else {
|
||
showBubbleNotification('该交接单未关联任何袋牌');
|
||
}
|
||
} else {
|
||
showBubbleNotification('查询袋牌失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
} else {
|
||
tableBody.append('<tr><td colspan="12" class="text-center">暂无数据</td></tr>');
|
||
}
|
||
}
|
||
|
||
// 并发请求控制
|
||
const requestQueue = {
|
||
queue: [],
|
||
processing: 0,
|
||
maxConcurrent: 3, // 最多同时处理3个请求
|
||
|
||
add: function(task) {
|
||
this.queue.push(task);
|
||
this.process();
|
||
},
|
||
|
||
process: function() {
|
||
if (this.queue.length > 0 && this.processing < this.maxConcurrent) {
|
||
this.processing++;
|
||
const task = this.queue.shift();
|
||
task().then(() => {
|
||
this.processing--;
|
||
this.process();
|
||
}).catch(() => {
|
||
this.processing--;
|
||
this.process();
|
||
});
|
||
}
|
||
}
|
||
};
|
||
|
||
// 加载袋牌数量和包裹数量
|
||
function loadBagTagAndPackageCount(shippingHandoverFormId, boxCountCell, orderCountCell) {
|
||
const task = function() {
|
||
return new Promise((resolve, reject) => {
|
||
const url = getBaseUrl() + '/api/shipping-handover/bag-tag/count/' + shippingHandoverFormId;
|
||
|
||
// 使用 JSONP 请求,与其他 API 调用保持一致
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'countBagTagsCallback',
|
||
timeout: 10000, // 添加10秒超时
|
||
success: function(response) {
|
||
console.log('袋牌和包裹数量响应:', response);
|
||
if (response && response.code === 0) {
|
||
const bagTagCount = response.data ? response.data.bagTagCount || 0 : 0;
|
||
const packageCount = response.data ? response.data.packageCount || 0 : 0;
|
||
boxCountCell.text(bagTagCount);
|
||
orderCountCell.text(packageCount);
|
||
} else {
|
||
boxCountCell.text('0');
|
||
orderCountCell.text('0');
|
||
}
|
||
resolve();
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('加载袋牌和包裹数量失败:', error, status);
|
||
boxCountCell.text('0');
|
||
orderCountCell.text('0');
|
||
resolve(); // 即使失败也继续处理队列
|
||
}
|
||
});
|
||
});
|
||
};
|
||
|
||
// 将任务添加到队列
|
||
requestQueue.add(task);
|
||
}
|
||
|
||
// 袋牌和包裹数量统计回调函数
|
||
function countBagTagsCallback(response) {
|
||
// 此回调函数在 ajax 调用中直接处理响应,不需要在这里重复处理
|
||
}
|
||
|
||
// 编辑出货交接单
|
||
function editShippingHandoverForm(id) {
|
||
const url = getBaseUrl() + '/api/shipping-handover/get/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'getShippingHandoverDetailCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
const form = response.data;
|
||
$('#editId').val(form.Id);
|
||
// 转换时间格式为datetime-local所需的格式
|
||
if (form.DeliveryTime) {
|
||
const deliveryTime = new Date(form.DeliveryTime);
|
||
$('#editDeliveryTime').val(deliveryTime.toISOString().slice(0, 16));
|
||
} else {
|
||
$('#editDeliveryTime').val('');
|
||
}
|
||
$('#editTimezone').val(form.TimeZone || 'America/New_York');
|
||
$('#editShippingPODUrls').val(form.POD || '');
|
||
$('#editRemarks').val(form.Remarks || '');
|
||
|
||
// 显示已上传的POD图片
|
||
const editUploadedShippingPODs = $('#editUploadedShippingPODs');
|
||
editUploadedShippingPODs.empty();
|
||
if (form.POD) {
|
||
const podItems = form.POD.split(',').map(item => item.trim());
|
||
podItems.forEach(item => {
|
||
if (item && item.startsWith('http')) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + item + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 更新POD链接输入框
|
||
updateEditShippingPODUrls();
|
||
// 确保预览模态框中的图片也被移除
|
||
$('#podPreviewContent').empty();
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
editUploadedShippingPODs.append(imgDiv);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 如果没有已上传的图片,显示提示信息
|
||
if (editUploadedShippingPODs.children().length === 0) {
|
||
editUploadedShippingPODs.append('<p class="text-muted text-center">点击或粘贴图片到此处</p>');
|
||
}
|
||
|
||
$('#editShippingHandoverModal').modal('show');
|
||
} else {
|
||
showBubbleNotification('获取详情失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 获取出货交接单详情回调函数
|
||
function getShippingHandoverDetailCallback(response) {
|
||
// 此回调函数在 ajax 调用中直接处理响应,不需要在这里重复处理
|
||
}
|
||
|
||
// 更新编辑出货交接单的POD链接输入框
|
||
function updateEditShippingPODUrls() {
|
||
const editUploadedShippingPODs = $('#editUploadedShippingPODs');
|
||
const podUrls = [];
|
||
|
||
// 从已上传的图片中获取链接
|
||
editUploadedShippingPODs.find('img').each(function() {
|
||
podUrls.push($(this).attr('src'));
|
||
});
|
||
|
||
// 从输入框中获取其他链接(只保留非图片链接)
|
||
const inputUrls = $('#editShippingPODUrls').val().split(',').map(item => item.trim()).filter(item => item && !item.startsWith('http'));
|
||
|
||
// 合并并去重
|
||
const allUrls = [...new Set([...podUrls, ...inputUrls])];
|
||
|
||
// 更新输入框
|
||
$('#editShippingPODUrls').val(allUrls.join(','));
|
||
}
|
||
|
||
// 更新编辑到货交接单的POD链接输入框
|
||
function updateEditArrivalPODUrls() {
|
||
const editUploadedArrivalPODs = $('#editUploadedArrivalPODs');
|
||
const podUrls = [];
|
||
|
||
// 从已上传的图片中获取链接
|
||
editUploadedArrivalPODs.find('img').each(function() {
|
||
podUrls.push($(this).attr('src'));
|
||
});
|
||
|
||
// 从输入框中获取其他链接(只保留非图片链接)
|
||
const inputUrls = $('#editArrivalPOD').val().split(',').map(item => item.trim()).filter(item => item && !item.startsWith('http'));
|
||
|
||
// 合并并去重
|
||
const allUrls = [...new Set([...podUrls, ...inputUrls])];
|
||
|
||
// 更新输入框
|
||
$('#editArrivalPOD').val(allUrls.join(','));
|
||
}
|
||
|
||
// 保存编辑
|
||
function saveShippingHandoverEdit() {
|
||
const id = $('#editId').val();
|
||
const deliveryTime = $('#editDeliveryTime').val();
|
||
const pod = $('#editShippingPODUrls').val().trim();
|
||
const remarks = $('#editRemarks').val().trim();
|
||
const timezone = $('#editTimezone').val();
|
||
|
||
// 先上传图片
|
||
const files = $('#editShippingPOD')[0].files;
|
||
if (files.length > 0) {
|
||
const handoverNumber = 'EDIT_' + id;
|
||
const uniqueIds = [];
|
||
const imageUrls = [];
|
||
|
||
// 预生成S3链接
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const uniqueId = generateGuid();
|
||
uniqueIds.push(uniqueId);
|
||
const imageUrl = generateS3Url('shipping', handoverNumber, file.name, uniqueId);
|
||
imageUrls.push(imageUrl);
|
||
}
|
||
|
||
// 上传图片
|
||
uploadFilesWithForm(files, 'shipping', handoverNumber, uniqueIds);
|
||
|
||
// 延迟更新POD,确保图片上传完成
|
||
setTimeout(function() {
|
||
// 合并已有的POD链接和新上传的图片链接
|
||
const existingPod = pod ? pod + ',' : '';
|
||
const newPod = existingPod + imageUrls.join(',');
|
||
|
||
updateShippingHandoverFormPOD(id, newPod, function() {
|
||
// 保存其他字段
|
||
saveShippingHandoverFields(id, deliveryTime, newPod, remarks, timezone);
|
||
});
|
||
}, 2000);
|
||
} else {
|
||
// 没有新图片,直接保存
|
||
saveShippingHandoverFields(id, deliveryTime, pod, remarks, timezone);
|
||
}
|
||
}
|
||
|
||
// 保存出货交接单字段
|
||
function saveShippingHandoverFields(id, deliveryTime, pod, remarks, timezone) {
|
||
const url = getBaseUrl() + '/api/shipping-handover/update/' + id;
|
||
|
||
// 构建请求数据
|
||
const data = {
|
||
DeliveryTime: deliveryTime,
|
||
TimeZone: timezone,
|
||
POD: pod || '' // 总是传递 POD 字段,为空时传递空字符串
|
||
};
|
||
|
||
// 只有当 Remarks 不为空时才传递
|
||
if (remarks && remarks.trim() !== '') {
|
||
data.Remarks = remarks;
|
||
}
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'updateShippingHandoverCallback',
|
||
data: data,
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('更新成功');
|
||
$('#editShippingHandoverModal').modal('hide');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新出货交接单回调函数
|
||
function updateShippingHandoverCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('更新成功');
|
||
$('#editShippingHandoverModal').modal('hide');
|
||
// 重新查询
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
// 编辑到货交接单
|
||
function editArrivalHandoverForm(id) {
|
||
const url = getBaseUrl() + '/api/arrival-handover/get/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'getArrivalHandoverDetailCallback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
const form = response.data;
|
||
$('#editArrivalId').val(form.Id);
|
||
$('#editArrivalHandoverNumber').val(form.HandoverNumber);
|
||
// 直接使用数据库中的时间值,不进行时区转换
|
||
// 假设数据库中存储的时间格式已经是YYYY-MM-DDTHH:MM格式
|
||
if (form.LogisticsProviderArrivalTime) {
|
||
// 确保时间格式为datetime-local所需的格式
|
||
let timeStr = form.LogisticsProviderArrivalTime;
|
||
// 如果时间字符串包含秒,去掉秒部分
|
||
if (timeStr.includes(':')) {
|
||
const parts = timeStr.split('T');
|
||
if (parts.length === 2) {
|
||
const timeParts = parts[1].split(':');
|
||
if (timeParts.length >= 2) {
|
||
timeStr = parts[0] + 'T' + timeParts[0] + ':' + timeParts[1];
|
||
}
|
||
}
|
||
}
|
||
$('#editLogisticsProviderArrivalTime').val(timeStr);
|
||
} else {
|
||
$('#editLogisticsProviderArrivalTime').val('');
|
||
}
|
||
if (form.ReceiptTime) {
|
||
// 确保时间格式为datetime-local所需的格式
|
||
let timeStr = form.ReceiptTime;
|
||
// 如果时间字符串包含秒,去掉秒部分
|
||
if (timeStr.includes(':')) {
|
||
const parts = timeStr.split('T');
|
||
if (parts.length === 2) {
|
||
const timeParts = parts[1].split(':');
|
||
if (timeParts.length >= 2) {
|
||
timeStr = parts[0] + 'T' + timeParts[0] + ':' + timeParts[1];
|
||
}
|
||
}
|
||
}
|
||
$('#editReceiptTime').val(timeStr);
|
||
} else {
|
||
$('#editReceiptTime').val('');
|
||
}
|
||
$('#editArrivalPOD').val(form.POD || '');
|
||
$('#editArrivalTimezone').val(form.TimeZone || 'America/New_York');
|
||
$('#editArrivalRemarks').val(form.Remarks || '');
|
||
|
||
// 显示已上传的POD图片
|
||
const editUploadedArrivalPODs = $('#editUploadedArrivalPODs');
|
||
editUploadedArrivalPODs.empty();
|
||
if (form.POD) {
|
||
const podItems = form.POD.split(',').map(item => item.trim());
|
||
podItems.forEach(item => {
|
||
if (item && item.startsWith('http')) {
|
||
const imgDiv = $('<div class="d-inline-block mr-2 mb-2" style="position: relative;"></div>');
|
||
const img = $('<img src="' + item + '" style="width: 100px; height: 100px; object-fit: cover; border: 1px solid #ddd; border-radius: 4px;">');
|
||
const removeBtn = $('<button type="button" class="btn btn-sm btn-danger" style="position: absolute; top: -5px; right: -5px; border-radius: 50%; width: 20px; height: 20px; padding: 0; display: flex; align-items: center; justify-content: center;">×</button>');
|
||
|
||
removeBtn.click(function() {
|
||
imgDiv.remove();
|
||
// 更新POD链接输入框
|
||
updateEditArrivalPODUrls();
|
||
// 确保预览模态框中的图片也被移除
|
||
$('#podPreviewContent').empty();
|
||
// 如果没有图片了,清空POD输入框
|
||
if (editUploadedArrivalPODs.children().length === 0) {
|
||
editUploadedArrivalPODs.append('<p class="text-muted text-center">点击或粘贴图片到此处</p>');
|
||
$('#editArrivalPOD').val('');
|
||
}
|
||
});
|
||
|
||
imgDiv.append(img);
|
||
imgDiv.append(removeBtn);
|
||
editUploadedArrivalPODs.append(imgDiv);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 如果没有已上传的图片,显示提示信息
|
||
if (editUploadedArrivalPODs.children().length === 0) {
|
||
editUploadedArrivalPODs.append('<p class="text-muted text-center">点击或粘贴图片到此处</p>');
|
||
$('#editArrivalPOD').val('');
|
||
}
|
||
|
||
$('#editArrivalHandoverModal').modal('show');
|
||
} else {
|
||
showBubbleNotification('获取详情失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 获取到货交接单详情回调函数
|
||
function getArrivalHandoverDetailCallback(response) {
|
||
// 此回调函数在 ajax 调用中直接处理响应,不需要在这里重复处理
|
||
}
|
||
|
||
// 保存到货交接单编辑
|
||
function saveArrivalHandoverEdit() {
|
||
const id = $('#editArrivalId').val();
|
||
const logisticsProviderArrivalTime = $('#editLogisticsProviderArrivalTime').val();
|
||
const receiptTime = $('#editReceiptTime').val();
|
||
const remarks = $('#editArrivalRemarks').val().trim();
|
||
const timezone = $('#editArrivalTimezone').val();
|
||
|
||
// 检查是否有图片预览,如果没有,清空POD
|
||
const editUploadedArrivalPODs = $('#editUploadedArrivalPODs');
|
||
const hasImages = editUploadedArrivalPODs.find('img').length > 0;
|
||
|
||
// 先上传图片
|
||
const files = $('#editArrivalPODUpload')[0].files;
|
||
if (files.length > 0) {
|
||
const handoverNumber = $('#editArrivalHandoverNumber').val() || 'EDIT_ARRIVAL_' + id;
|
||
const uniqueIds = [];
|
||
const imageUrls = [];
|
||
|
||
// 预生成S3链接
|
||
for (let i = 0; i < files.length; i++) {
|
||
const file = files[i];
|
||
const uniqueId = generateGuid();
|
||
uniqueIds.push(uniqueId);
|
||
const imageUrl = generateS3Url('arrival', handoverNumber, file.name, uniqueId);
|
||
imageUrls.push(imageUrl);
|
||
}
|
||
|
||
// 上传图片
|
||
uploadFilesWithForm(files, 'arrival', handoverNumber, uniqueIds);
|
||
|
||
// 延迟更新,确保图片上传完成
|
||
setTimeout(function() {
|
||
// 合并已有的POD链接和新上传的图片链接
|
||
let newPod = imageUrls.join(',');
|
||
|
||
// 直接保存所有字段,包括POD
|
||
saveArrivalHandoverFields(id, logisticsProviderArrivalTime, receiptTime, newPod, remarks, timezone);
|
||
}, 2000);
|
||
} else {
|
||
// 没有新图片,直接保存
|
||
// 明确检查是否有图片,如果没有,强制清空POD
|
||
const finalPod = hasImages ? $('#editArrivalPOD').val().trim() : '';
|
||
// 确保POD字段被正确传递
|
||
console.log('Saving arrival handover with POD:', finalPod);
|
||
saveArrivalHandoverFields(id, logisticsProviderArrivalTime, receiptTime, finalPod, remarks, timezone);
|
||
}
|
||
}
|
||
|
||
// 保存到货交接单字段
|
||
function saveArrivalHandoverFields(id, logisticsProviderArrivalTime, receiptTime, pod, remarks, timezone) {
|
||
const url = getBaseUrl() + '/api/arrival-handover/update/' + id;
|
||
|
||
// 构建请求数据
|
||
const data = {
|
||
TimeZone: timezone
|
||
};
|
||
|
||
// 只有当值不为空时才传递
|
||
if (logisticsProviderArrivalTime) {
|
||
data.LogisticsProviderArrivalTime = logisticsProviderArrivalTime;
|
||
}
|
||
if (receiptTime) {
|
||
data.ReceiptTime = receiptTime;
|
||
}
|
||
if (remarks) {
|
||
data.Remarks = remarks;
|
||
}
|
||
|
||
// 总是传递 POD 字段,当为空时传递 null
|
||
data.POD = pod && pod.trim() !== '' ? pod : null;
|
||
|
||
// 确保POD字段被正确传递
|
||
console.log('Sending POD to server:', data.POD);
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'updateArrivalHandoverCallback',
|
||
data: data,
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('更新成功');
|
||
$('#editArrivalHandoverModal').modal('hide');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新到货交接单回调函数
|
||
function updateArrivalHandoverCallback(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('更新成功');
|
||
$('#editArrivalHandoverModal').modal('hide');
|
||
// 重新查询
|
||
$('#arrivalHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
}
|
||
|
||
|
||
// 时区选择变化
|
||
$('#timezone').change(function() {
|
||
// 可以在这里添加时区变化的处理逻辑
|
||
showBubbleNotification('时区已更新');
|
||
});
|
||
|
||
// 监听集包数据查询每页记录数选择变化
|
||
$('#bagTagPageSize').change(function() {
|
||
if ($(this).val() === 'custom') {
|
||
$('#customBagTagPageSizeContainer').show();
|
||
} else {
|
||
$('#customBagTagPageSizeContainer').hide();
|
||
}
|
||
});
|
||
|
||
// 集包数据查询表单提交
|
||
$('#bagTagForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const page = 1;
|
||
const pageSize = getBagTagPageSize();
|
||
const sortBy = $('#bagTagSortBy').val();
|
||
const sortOrder = $('#bagTagSortOrder').val();
|
||
const tagNumber = $('#bagTagNumber').val();
|
||
const channel = $('#bagTagChannel').val();
|
||
const status = $('#bagTagStatus').val();
|
||
const creator = $('#bagTagCreator').val();
|
||
const bagTagStartCreatedAt = $('#bagTagStartCreatedAt').val();
|
||
const bagTagEndCreatedAt = $('#bagTagEndCreatedAt').val();
|
||
|
||
const url = getBaseUrl() + '/api/bagtag/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&tagNumber=' + tagNumber + '&channel=' + channel + '&status=' + status + '&creator=' + creator + '&startCreatedAt=' + bagTagStartCreatedAt + '&endCreatedAt=' + bagTagEndCreatedAt;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderBagTagTable(response.data);
|
||
renderPagination('bagTag', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
showBubbleNotification('共找到 ' + response.totalCount + ' 条记录');
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 重置集包数据查询表单
|
||
$('#resetBagTagForm').click(function() {
|
||
$('#bagTagForm')[0].reset();
|
||
$('#customBagTagPageSizeContainer').hide();
|
||
});
|
||
|
||
// 集包数据导出Excel
|
||
$('#exportBagTagExcelBtn').click(function() {
|
||
// 检查是否有数据
|
||
const bagTagData = window.bagTagData;
|
||
if (!bagTagData || bagTagData.length === 0) {
|
||
showBubbleNotification('没有数据可导出');
|
||
return;
|
||
}
|
||
|
||
showBubbleNotification('正在准备导出数据,请稍候...');
|
||
|
||
// 获取当前查询参数
|
||
const sortBy = $('#bagTagSortBy').val();
|
||
const sortOrder = $('#bagTagSortOrder').val();
|
||
const tagNumber = $('#bagTagNumber').val();
|
||
const channel = $('#bagTagChannel').val();
|
||
const status = $('#bagTagStatus').val();
|
||
const creator = $('#bagTagCreator').val();
|
||
const bagTagStartCreatedAt = $('#bagTagStartCreatedAt').val();
|
||
const bagTagEndCreatedAt = $('#bagTagEndCreatedAt').val();
|
||
|
||
// 封装JSONP请求为Promise
|
||
function jsonpRequest(url) {
|
||
return new Promise((resolve, reject) => {
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: resolve,
|
||
error: reject
|
||
});
|
||
});
|
||
}
|
||
|
||
// 获取所有袋牌数据
|
||
async function getAllBagTagData() {
|
||
try {
|
||
// 首先获取第一页数据和总页数
|
||
const firstPageUrl = getBaseUrl() + '/api/bagtag/batch?page=1&pageSize=100&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&tagNumber=' + tagNumber + '&channel=' + channel + '&status=' + status + '&creator=' + creator + '&startCreatedAt=' + bagTagStartCreatedAt + '&endCreatedAt=' + bagTagEndCreatedAt;
|
||
const firstPageResponse = await jsonpRequest(firstPageUrl);
|
||
|
||
if (firstPageResponse.status !== 'ok') {
|
||
throw new Error('获取第一页数据失败: ' + (firstPageResponse.message || '未知错误'));
|
||
}
|
||
|
||
const totalPages = firstPageResponse.totalPages;
|
||
const allBagTagData = [...firstPageResponse.data];
|
||
|
||
// 获取剩余页的数据
|
||
for (let page = 2; page <= totalPages; page++) {
|
||
const pageUrl = getBaseUrl() + '/api/bagtag/batch?page=' + page + '&pageSize=100&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&tagNumber=' + tagNumber + '&channel=' + channel + '&status=' + status + '&creator=' + creator + '&startCreatedAt=' + bagTagStartCreatedAt + '&endCreatedAt=' + bagTagEndCreatedAt;
|
||
const pageResponse = await jsonpRequest(pageUrl);
|
||
|
||
if (pageResponse.status === 'ok') {
|
||
allBagTagData.push(...pageResponse.data);
|
||
} else {
|
||
console.warn('获取第 ' + page + ' 页数据失败,跳过该页');
|
||
}
|
||
}
|
||
|
||
return allBagTagData;
|
||
} catch (error) {
|
||
console.error('获取袋牌数据失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
// 获取单个袋牌的运单数据
|
||
async function getWaybillsForBagTag(bagTag) {
|
||
try {
|
||
if (bagTag.waybillCount <= 0) {
|
||
return [];
|
||
}
|
||
|
||
const url = getBaseUrl() + '/api/bagtag/' + bagTag.tagNumber + '/waybills';
|
||
const response = await jsonpRequest(url);
|
||
|
||
if (response.code === 0 && response.data) {
|
||
return response.data;
|
||
} else {
|
||
console.warn('获取袋牌 ' + bagTag.tagNumber + ' 的运单数据失败:', response.message);
|
||
return [];
|
||
}
|
||
} catch (error) {
|
||
console.error('获取袋牌 ' + bagTag.tagNumber + ' 的运单数据失败:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
// 主导出逻辑
|
||
async function exportData() {
|
||
try {
|
||
// 获取所有袋牌数据
|
||
const allBagTagData = await getAllBagTagData();
|
||
|
||
if (allBagTagData.length === 0) {
|
||
showBubbleNotification('没有数据可导出');
|
||
return;
|
||
}
|
||
|
||
// 准备袋牌信息数据
|
||
const bagTagSheetData = allBagTagData.map(item => {
|
||
return {
|
||
'袋牌号码': item.tagNumber || '-',
|
||
'渠道': item.channelName || '-',
|
||
'状态': item.status || '-',
|
||
'创建人': item.creator || '-',
|
||
'创建时间': item.createdAt ? new Date(item.createdAt).toLocaleString() : '-',
|
||
'打开时间': item.openedAt ? new Date(item.openedAt).toLocaleString() : '-',
|
||
'关闭时间': item.closedAt ? new Date(item.closedAt).toLocaleString() : '-',
|
||
'关联运单数量': item.waybillCount || 0
|
||
};
|
||
});
|
||
|
||
// 准备小包明细数据
|
||
const waybillSheetData = [];
|
||
|
||
// 逐个获取每个袋牌的运单数据
|
||
for (const bagTag of allBagTagData) {
|
||
const waybills = await getWaybillsForBagTag(bagTag);
|
||
|
||
// 添加运单数据到导出列表
|
||
waybills.forEach(w => {
|
||
waybillSheetData.push({
|
||
'袋牌号码': bagTag.tagNumber || '-',
|
||
'尾程跟踪单号': w.FinalMileTrackingNumber || '-',
|
||
'中性面单号': w.NeutralWaybillNumber || '-',
|
||
'换单完成时间': w.ReplaceCompletedTime ? new Date(w.ReplaceCompletedTime).toLocaleString() : '-',
|
||
'提单号': w.BillOfLadingNumber || '-',
|
||
'客户简称': w.CustomerAbbreviation || '-',
|
||
'创建人': w.Creator || '-',
|
||
'创建时间': w.CreatedAt ? new Date(w.CreatedAt).toLocaleString() : '-',
|
||
'备注': w.Remark || '-'
|
||
});
|
||
});
|
||
}
|
||
|
||
// 验证数据一致性
|
||
const expectedWaybillCount = bagTagSheetData.reduce((total, item) => total + (item['关联运单数量'] || 0), 0);
|
||
const actualWaybillCount = waybillSheetData.length;
|
||
|
||
console.log('验证数据一致性:');
|
||
console.log('预期运单数量:', expectedWaybillCount);
|
||
console.log('实际运单数量:', actualWaybillCount);
|
||
|
||
if (expectedWaybillCount !== actualWaybillCount) {
|
||
console.warn('运单数量不一致,可能存在数据缺失');
|
||
showBubbleNotification('警告: 运单数量可能存在不一致,导出数据可能不完整');
|
||
}
|
||
|
||
// 导出Excel
|
||
exportExcel([
|
||
{
|
||
sheetName: '袋牌信息',
|
||
data: bagTagSheetData
|
||
},
|
||
{
|
||
sheetName: '小包明细',
|
||
data: waybillSheetData
|
||
}
|
||
], '集包数据');
|
||
|
||
showBubbleNotification('导出完成');
|
||
} catch (error) {
|
||
console.error('导出失败:', error);
|
||
showBubbleNotification('导出失败: ' + (error.message || '未知错误'));
|
||
}
|
||
}
|
||
|
||
// 开始导出过程
|
||
exportData();
|
||
});
|
||
|
||
// 获取实际的页大小
|
||
function getPageSize() {
|
||
const pageSize = $('#pageSize').val();
|
||
if (pageSize === 'custom') {
|
||
const customSize = $('#customPageSize').val();
|
||
return customSize || 500;
|
||
}
|
||
return pageSize;
|
||
}
|
||
|
||
// 获取扫描记录查询的实际页大小
|
||
function getScanPageSize() {
|
||
const pageSize = $('#scanPageSize').val();
|
||
if (pageSize === 'custom') {
|
||
const customSize = $('#customScanPageSize').val();
|
||
return customSize || 500;
|
||
}
|
||
return pageSize;
|
||
}
|
||
|
||
// 获得到货批次查询的实际页大小
|
||
function getArrivalPageSize() {
|
||
const pageSize = $('#arrivalPageSize').val();
|
||
if (pageSize === 'custom') {
|
||
const customSize = $('#customArrivalPageSize').val();
|
||
return customSize || 500;
|
||
}
|
||
return pageSize;
|
||
}
|
||
|
||
// 获取集包数据查询的实际页大小
|
||
function getBagTagPageSize() {
|
||
const pageSize = $('#bagTagPageSize').val();
|
||
if (pageSize === 'custom') {
|
||
const customSize = $('#customBagTagPageSize').val();
|
||
return customSize || 500;
|
||
}
|
||
return pageSize;
|
||
}
|
||
|
||
// 结果映射
|
||
const scanResultMap = {
|
||
0: '已返回面单',
|
||
1: '无面单数据',
|
||
2: '无下单数据',
|
||
3: '订单被冻结',
|
||
4: '订单已销毁',
|
||
5: '其他'
|
||
};
|
||
|
||
// 标签替换请求查询
|
||
$('#labelReplaceForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const page = 1;
|
||
const pageSize = getPageSize();
|
||
const sortBy = $('#sortBy').val();
|
||
const sortOrder = $('#sortOrder').val();
|
||
const billOfLadingNumber = $('#billOfLadingNumber').val();
|
||
const masterPackageNumber = $('#masterPackageNumber').val();
|
||
const referenceNumber = $('#referenceNumber').val();
|
||
const neutralWaybillNumber = $('#neutralWaybillNumber').val().trim().replace(/\s+/g, ','); // 将多行输入转换为逗号分隔的字符串
|
||
const finalMileTrackingNumber = $('#finalMileTrackingNumber').val();
|
||
const replaceStatus = $('#replaceStatus').val();
|
||
const customerId = $('#customerId').val();
|
||
const startCreatedAt = $('#startCreatedAt').val();
|
||
const endCreatedAt = $('#endCreatedAt').val();
|
||
const startReplacedAt = $('#startReplacedAt').val();
|
||
const endReplacedAt = $('#endReplacedAt').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-replace/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&billOfLadingNumber=' + billOfLadingNumber + '&masterPackageNumber=' + masterPackageNumber + '&referenceNumber=' + referenceNumber + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&replaceStatus=' + replaceStatus + '&customerId=' + customerId + '&startCreatedAt=' + startCreatedAt + '&endCreatedAt=' + endCreatedAt + '&startReplacedAt=' + startReplacedAt + '&endReplacedAt=' + endReplacedAt;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderLabelReplaceTable(response.data);
|
||
renderPagination('labelReplace', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
// 显示气泡弹窗
|
||
showBubbleNotification('共找到 ' + response.totalCount + ' 条记录');
|
||
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 标签扫描记录查询
|
||
$('#labelScanForm').submit(function(e) {
|
||
e.preventDefault();
|
||
const page = 1;
|
||
const pageSize = getScanPageSize();
|
||
const sortBy = $('#scanSortBy').val();
|
||
const sortOrder = $('#scanSortOrder').val();
|
||
const customerId = $('#scanCustomerId').val();
|
||
const neutralWaybillNumber = $('#scanNeutralWaybillNumber').val();
|
||
const finalMileTrackingNumber = $('#scanFinalMileTrackingNumber').val();
|
||
const result = $('#scanResult').val();
|
||
const scanStartCreatedAt = $('#scanStartCreatedAt').val();
|
||
const scanEndCreatedAt = $('#scanEndCreatedAt').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-scan/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&customerId=' + customerId + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&result=' + result + '&startCreatedAt=' + scanStartCreatedAt + '&endCreatedAt=' + scanEndCreatedAt;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderLabelScanTable(response.data);
|
||
renderPagination('labelScan', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
// 显示气泡弹窗
|
||
showBubbleNotification('共找到 ' + response.totalCount + ' 条记录');
|
||
|
||
} else {
|
||
showBubbleNotification('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 渲染标签替换请求表格
|
||
function renderLabelReplaceTable(data) {
|
||
const tbody = $('#labelReplaceTableBody');
|
||
tbody.empty();
|
||
|
||
if (data.length === 0) {
|
||
tbody.append('<tr><td colspan="12" class="text-center">暂无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td>${item.Id || '-'}</td>`);
|
||
row.append(`<td>${item.CustomerCode || '-'}</td>`);
|
||
row.append(`<td>${item.BillOfLadingNumber || '-'}</td>`);
|
||
row.append(`<td>${item.MasterPackageNumber || '-'}</td>`);
|
||
row.append(`<td>${item.NeutralWaybillNumber || '-'}</td>`);
|
||
row.append(`<td>${item.FinalMileTrackingNumber || '-'}</td>`);
|
||
row.append(`<td>${item.BagTagNumber || '-'}</td>`);
|
||
|
||
// 有无面单字段 - 根据 Label 字段判断
|
||
const hasLabel = item.Label && item.Label.trim() !== '';
|
||
if (hasLabel) {
|
||
// 检查是否为 URL 资源
|
||
if (item.Label.startsWith('http://') || item.Label.startsWith('https://')) {
|
||
const encodedUrl = encodeURIComponent(item.Label);
|
||
row.append(`<td><span class="text-success cursor-pointer" data-url="${encodedUrl}">有</span></td>`);
|
||
} else {
|
||
// 非 URL 资源,显示原数据
|
||
row.append(`<td><span class="text-success cursor-pointer" data-content="${item.Label}">有</span></td>`);
|
||
}
|
||
} else {
|
||
row.append(`<td><span class="text-muted cursor-pointer" data-content="无">无</span></td>`);
|
||
}
|
||
|
||
row.append(`<td>${item.ReplaceStatus === 'Y' ? '正常换单' : '冻结换单'}</td>`);
|
||
row.append(`<td>${item.ReplacedAt ? new Date(item.ReplacedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.LabelRetrievedAt ? new Date(item.LabelRetrievedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.CreatedAt ? new Date(item.CreatedAt).toLocaleString() : '-'}</td>`);
|
||
tbody.append(row);
|
||
});
|
||
|
||
// 添加点击预览事件(使用事件委托,确保动态生成的元素也能触发)
|
||
$('#labelReplaceTableBody').on('click', '.cursor-pointer', function() {
|
||
// 检查是否有 data-url 属性(URL 资源)
|
||
if ($(this).data('url')) {
|
||
const encodedUrl = $(this).data('url');
|
||
if (encodedUrl) {
|
||
const url = decodeURIComponent(encodedUrl);
|
||
// 直接打开 URL 资源
|
||
window.open(url, '_blank');
|
||
}
|
||
}
|
||
// 检查是否有 data-content 属性(非 URL 资源)
|
||
else if ($(this).data('content')) {
|
||
const content = $(this).data('content');
|
||
if (content) {
|
||
// 显示原数据
|
||
$('#labelPreviewContent').html(`<p class="border p-3 rounded bg-light">${content}</p>`);
|
||
$('#labelPreviewModal').modal('show');
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
// 渲染标签扫描记录表格
|
||
function renderLabelScanTable(data) {
|
||
const tbody = $('#labelScanTableBody');
|
||
tbody.empty();
|
||
|
||
if (data.length === 0) {
|
||
tbody.append('<tr><td colspan="8" class="text-center">暂无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td>${item.Id || '-'}</td>`);
|
||
row.append(`<td>${item.CustomerCode || '-'}</td>`);
|
||
row.append(`<td>${item.NeutralWaybillNumber || '-'}</td>`);
|
||
row.append(`<td>${item.FinalMileTrackingNumber || '-'}</td>`);
|
||
row.append(`<td>${scanResultMap[item.Result] || item.Result || '-'}</td>`);
|
||
row.append(`<td>${item.Description || '-'}</td>`);
|
||
row.append(`<td>${item.CreatedBy || '-'}</td>`);
|
||
row.append(`<td>${item.CreatedAt ? new Date(item.CreatedAt).toLocaleString() : '-'}</td>`);
|
||
tbody.append(row);
|
||
});
|
||
}
|
||
|
||
// 渲染到货批次表格
|
||
function renderArrivalBatchTable(data) {
|
||
const tbody = $('#arrivalBatchTableBody');
|
||
tbody.empty();
|
||
|
||
if (data.length === 0) {
|
||
tbody.append('<tr><td colspan="8" class="text-center">暂无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
// 转换时间格式为datetime-local所需的格式
|
||
let logisticsDeliveryTime = '';
|
||
let warehouseReceiptTime = '';
|
||
if (item.LogisticsDeliveryTime) {
|
||
const logisticsTime = new Date(item.LogisticsDeliveryTime);
|
||
logisticsDeliveryTime = logisticsTime.toISOString().slice(0, 16);
|
||
}
|
||
if (item.WarehouseReceiptTime) {
|
||
const warehouseTime = new Date(item.WarehouseReceiptTime);
|
||
warehouseReceiptTime = warehouseTime.toISOString().slice(0, 16);
|
||
}
|
||
row.append(`<td><input type="checkbox" class="batch-checkbox" data-id="${item.Id}"></td>`);
|
||
row.append(`<td>${item.Id || '-'}</td>`);
|
||
row.append(`<td><input type="text" class="form-control" data-field="TrackingNumber" data-id="${item.Id}" value="${item.TrackingNumber || ''}"></td>`);
|
||
row.append(`<td><input type="datetime-local" class="form-control" data-field="LogisticsDeliveryTime" data-id="${item.Id}" value="${logisticsDeliveryTime}"></td>`);
|
||
row.append(`<td><input type="datetime-local" class="form-control" data-field="WarehouseReceiptTime" data-id="${item.Id}" value="${warehouseReceiptTime}"></td>`);
|
||
row.append(`<td>${item.CreatedAt ? new Date(item.CreatedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.UpdatedAt ? new Date(item.UpdatedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>
|
||
<button class="btn btn-sm btn-success me-1" onclick="saveBatchEdit(${item.Id})">保存</button>
|
||
<button class="btn btn-sm btn-danger" onclick="deleteArrivalBatch(${item.Id})">删除</button>
|
||
</td>`);
|
||
tbody.append(row);
|
||
});
|
||
|
||
// 绑定输入框变化事件
|
||
$('.form-control[data-field]').change(function() {
|
||
const id = $(this).data('id');
|
||
const field = $(this).data('field');
|
||
const value = $(this).val();
|
||
// 可以在这里添加实时验证或其他处理
|
||
});
|
||
}
|
||
|
||
// 渲染集包数据表格
|
||
function renderBagTagTable(data) {
|
||
const tbody = $('#bagTagTableBody');
|
||
tbody.empty();
|
||
|
||
// 存储数据到全局变量,用于导出
|
||
window.bagTagData = data;
|
||
|
||
if (data.length === 0) {
|
||
tbody.append('<tr><td colspan="10" class="text-center">暂无数据</td></tr>');
|
||
return;
|
||
}
|
||
|
||
data.forEach(item => {
|
||
// 主行
|
||
const row = $('<tr class="bag-tag-row"></tr>');
|
||
row.append(`<td>${item.id || '-'}</td>`);
|
||
row.append(`<td>${item.tagNumber || '-'}</td>`);
|
||
row.append(`<td>${item.channelName || '-'}</td>`);
|
||
row.append(`<td>${item.status || '-'}</td>`);
|
||
row.append(`<td>${item.creator || '-'}</td>`);
|
||
row.append(`<td>${item.createdAt ? new Date(item.createdAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.openedAt ? new Date(item.openedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.closedAt ? new Date(item.closedAt).toLocaleString() : '-'}</td>`);
|
||
row.append(`<td>${item.waybillCount || 0}</td>`);
|
||
row.append(`<td><button class="btn btn-sm btn-primary view-waybills" data-tag-number="${item.tagNumber}">${item.waybillCount > 0 ? '查看运单' : '无运单'}</button></td>`);
|
||
tbody.append(row);
|
||
|
||
// 运单明细行(默认隐藏,动态加载)
|
||
const waybillRow = $('<tr class="waybill-detail-row" style="display: none;"></tr>');
|
||
waybillRow.append(`<td colspan="10">
|
||
<div class="p-3 bg-light rounded">
|
||
<h6 class="mb-2">袋牌 ${item.tagNumber} 的运单明细</h6>
|
||
<div class="table-responsive" id="waybill-content-${item.tagNumber}">
|
||
<div class="text-center p-3">加载中...</div>
|
||
</div>
|
||
</div>
|
||
</td>`);
|
||
tbody.append(waybillRow);
|
||
});
|
||
|
||
// 绑定查看运单按钮事件
|
||
$('.view-waybills').click(function() {
|
||
const tagNumber = $(this).data('tag-number');
|
||
const row = $(this).closest('.bag-tag-row');
|
||
const waybillRow = row.next('.waybill-detail-row');
|
||
|
||
if (waybillRow.length > 0) {
|
||
if (waybillRow.is(':visible')) {
|
||
waybillRow.hide();
|
||
$(this).text('查看运单');
|
||
} else {
|
||
waybillRow.show();
|
||
$(this).text('收起运单');
|
||
|
||
// 动态加载运单明细
|
||
const contentDiv = $(`#waybill-content-${tagNumber}`);
|
||
|
||
// 检查是否已经有缓存数据
|
||
const bagTagItem = window.bagTagData.find(item => item.tagNumber === tagNumber);
|
||
if (bagTagItem && bagTagItem.waybills) {
|
||
// 使用缓存数据
|
||
const waybills = bagTagItem.waybills;
|
||
if (waybills.length > 0) {
|
||
let html = `
|
||
<table class="table table-sm table-striped">
|
||
<thead>
|
||
<tr>
|
||
<th>尾程跟踪单号</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>备注</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
${waybills.map(w => `
|
||
<tr>
|
||
<td>${w.finalMileTrackingNumber || '-'}</td>
|
||
<td>${w.creator || '-'}</td>
|
||
<td>${w.createdAt ? new Date(w.createdAt).toLocaleString() : '-'}</td>
|
||
<td>${w.remark || '-'}</td>
|
||
</tr>
|
||
`).join('')}
|
||
</tbody>
|
||
</table>
|
||
`;
|
||
contentDiv.html(html);
|
||
} else {
|
||
contentDiv.html('<div class="text-center p-3">无运单数据</div>');
|
||
}
|
||
} else {
|
||
// 首次加载,从服务器获取数据
|
||
contentDiv.html('<div class="text-center p-3">加载中...</div>');
|
||
|
||
const url = getBaseUrl() + '/api/bagtag/' + tagNumber + '/waybills';
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.code === 0 && response.data) {
|
||
const waybills = response.data;
|
||
|
||
// 转换数据格式并缓存
|
||
const formattedWaybills = waybills.map(w => ({
|
||
finalMileTrackingNumber: w.FinalMileTrackingNumber,
|
||
neutralWaybillNumber: w.NeutralWaybillNumber,
|
||
replaceCompletedTime: w.ReplaceCompletedTime,
|
||
billOfLadingNumber: w.BillOfLadingNumber,
|
||
customerAbbreviation: w.CustomerAbbreviation,
|
||
creator: w.Creator,
|
||
createdAt: w.CreatedAt,
|
||
remark: w.Remark
|
||
}));
|
||
|
||
// 存储到bagTagData中
|
||
if (bagTagItem) {
|
||
bagTagItem.waybills = formattedWaybills;
|
||
}
|
||
|
||
if (waybills.length > 0) {
|
||
let html = `
|
||
<table class="table table-sm table-striped">
|
||
<thead>
|
||
<tr>
|
||
<th>尾程跟踪单号</th>
|
||
<th>创建人</th>
|
||
<th>创建时间</th>
|
||
<th>备注</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
${waybills.map(w => `
|
||
<tr>
|
||
<td>${w.FinalMileTrackingNumber || '-'}</td>
|
||
<td>${w.Creator || '-'}</td>
|
||
<td>${w.CreatedAt ? new Date(w.CreatedAt).toLocaleString() : '-'}</td>
|
||
<td>${w.Remark || '-'}</td>
|
||
</tr>
|
||
`).join('')}
|
||
</tbody>
|
||
</table>
|
||
`;
|
||
contentDiv.html(html);
|
||
} else {
|
||
contentDiv.html('<div class="text-center p-3">无运单数据</div>');
|
||
}
|
||
} else {
|
||
contentDiv.html('<div class="text-center p-3 text-danger">加载失败: ' + (response.message || '未知错误') + '</div>');
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
contentDiv.html('<div class="text-center p-3 text-danger">请求失败: ' + error + '</div>');
|
||
}
|
||
});
|
||
}
|
||
}
|
||
} else {
|
||
showBubbleNotification(`袋牌 ${tagNumber} 无关联运单`);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 保存编辑
|
||
function saveBatchEdit(id) {
|
||
const trackingNumber = $(`input[data-field="TrackingNumber"][data-id="${id}"]`).val();
|
||
const logisticsDeliveryTime = $(`input[data-field="LogisticsDeliveryTime"][data-id="${id}"]`).val();
|
||
const warehouseReceiptTime = $(`input[data-field="WarehouseReceiptTime"][data-id="${id}"]`).val();
|
||
const timezone = $('#timezone').val();
|
||
|
||
const url = getBaseUrl() + '/api/arrival-batch/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'PUT',
|
||
data: JSON.stringify({
|
||
trackingNumber: trackingNumber,
|
||
logisticsDeliveryTime: logisticsDeliveryTime,
|
||
warehouseReceiptTime: warehouseReceiptTime,
|
||
timezone: timezone
|
||
}),
|
||
contentType: 'application/json',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
showBubbleNotification('到货批次更新成功');
|
||
// 重新查询
|
||
$('#arrivalBatchForm').submit();
|
||
} else {
|
||
showBubbleNotification('更新失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 编辑到货批次
|
||
function editArrivalBatch(id, trackingNumber, logisticsDeliveryTime, warehouseReceiptTime) {
|
||
$('#editBatchId').val(id);
|
||
$('#editTrackingNumber').val(trackingNumber);
|
||
// 转换时间格式为datetime-local所需的格式
|
||
if (logisticsDeliveryTime) {
|
||
const logisticsTime = new Date(logisticsDeliveryTime);
|
||
$('#editLogisticsDeliveryTime').val(logisticsTime.toISOString().slice(0, 16));
|
||
}
|
||
if (warehouseReceiptTime) {
|
||
const warehouseTime = new Date(warehouseReceiptTime);
|
||
$('#editWarehouseReceiptTime').val(warehouseTime.toISOString().slice(0, 16));
|
||
}
|
||
$('#editArrivalBatchModal').modal('show');
|
||
}
|
||
|
||
// 删除到货批次
|
||
function deleteArrivalBatch(id) {
|
||
if (confirm('确定要删除这个到货批次吗?')) {
|
||
const url = getBaseUrl() + '/api/arrival-batch/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'DELETE',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
showBubbleNotification('到货批次删除成功');
|
||
// 重新查询
|
||
$('#arrivalBatchForm').submit();
|
||
} else {
|
||
showBubbleNotification('删除失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 渲染分页控件
|
||
function renderPagination(prefix, currentPage, pageSize, totalPages, totalCount) {
|
||
const pagination = $(`#${prefix}Pagination`);
|
||
const paginationInfo = $(`#${prefix}PaginationInfo`);
|
||
|
||
paginationInfo.text(`共 ${totalCount} 条记录,第 ${currentPage} / ${totalPages} 页`);
|
||
pagination.empty();
|
||
|
||
// 上一页
|
||
const prevLi = $('<li class="page-item"></li>');
|
||
const prevLink = $('<a class="page-link" href="#">上一页</a>');
|
||
if (currentPage === 1) {
|
||
prevLi.addClass('disabled');
|
||
} else {
|
||
prevLink.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, currentPage - 1);
|
||
});
|
||
}
|
||
prevLi.append(prevLink);
|
||
pagination.append(prevLi);
|
||
|
||
// 页码
|
||
if (totalPages <= 7) {
|
||
// 总页数较少,显示所有页码
|
||
for (let i = 1; i <= totalPages; i++) {
|
||
const li = $('<li class="page-item"></li>');
|
||
const link = $('<a class="page-link" href="#">' + i + '</a>');
|
||
if (i === currentPage) {
|
||
li.addClass('active');
|
||
} else {
|
||
link.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, i);
|
||
});
|
||
}
|
||
li.append(link);
|
||
pagination.append(li);
|
||
}
|
||
} else {
|
||
// 总页数较多,显示部分页码
|
||
// 显示第一页
|
||
const firstLi = $('<li class="page-item"></li>');
|
||
const firstLink = $('<a class="page-link" href="#">1</a>');
|
||
if (currentPage === 1) {
|
||
firstLi.addClass('active');
|
||
} else {
|
||
firstLink.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, 1);
|
||
});
|
||
}
|
||
firstLi.append(firstLink);
|
||
pagination.append(firstLi);
|
||
|
||
// 显示省略号
|
||
if (currentPage > 4) {
|
||
const ellipsis1 = $('<li class="page-item disabled"><a class="page-link" href="#">...</a></li>');
|
||
pagination.append(ellipsis1);
|
||
}
|
||
|
||
// 显示当前页附近的页码
|
||
const startPage = Math.max(2, currentPage - 2);
|
||
const endPage = Math.min(totalPages - 1, currentPage + 2);
|
||
|
||
for (let i = startPage; i <= endPage; i++) {
|
||
const li = $('<li class="page-item"></li>');
|
||
const link = $('<a class="page-link" href="#">' + i + '</a>');
|
||
if (i === currentPage) {
|
||
li.addClass('active');
|
||
} else {
|
||
link.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, i);
|
||
});
|
||
}
|
||
li.append(link);
|
||
pagination.append(li);
|
||
}
|
||
|
||
// 显示省略号
|
||
if (currentPage < totalPages - 3) {
|
||
const ellipsis2 = $('<li class="page-item disabled"><a class="page-link" href="#">...</a></li>');
|
||
pagination.append(ellipsis2);
|
||
}
|
||
|
||
// 显示最后一页
|
||
const lastLi = $('<li class="page-item"></li>');
|
||
const lastLink = $('<a class="page-link" href="#">' + totalPages + '</a>');
|
||
if (currentPage === totalPages) {
|
||
lastLi.addClass('active');
|
||
} else {
|
||
lastLink.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, totalPages);
|
||
});
|
||
}
|
||
lastLi.append(lastLink);
|
||
pagination.append(lastLi);
|
||
}
|
||
|
||
// 下一页
|
||
const nextLi = $('<li class="page-item"></li>');
|
||
const nextLink = $('<a class="page-link" href="#">下一页</a>');
|
||
if (currentPage === totalPages) {
|
||
nextLi.addClass('disabled');
|
||
} else {
|
||
nextLink.click(function(e) {
|
||
e.preventDefault();
|
||
loadPage(prefix, currentPage + 1);
|
||
});
|
||
}
|
||
nextLi.append(nextLink);
|
||
pagination.append(nextLi);
|
||
}
|
||
|
||
// 加载指定页码
|
||
function loadPage(prefix, page) {
|
||
if (prefix === 'labelReplace') {
|
||
const pageSize = getPageSize();
|
||
const sortBy = $('#sortBy').val();
|
||
const sortOrder = $('#sortOrder').val();
|
||
const billOfLadingNumber = $('#billOfLadingNumber').val();
|
||
const masterPackageNumber = $('#masterPackageNumber').val();
|
||
const referenceNumber = $('#referenceNumber').val();
|
||
const neutralWaybillNumber = $('#neutralWaybillNumber').val().trim().replace(/\s+/g, ','); // 将多行输入转换为逗号分隔的字符串
|
||
const finalMileTrackingNumber = $('#finalMileTrackingNumber').val();
|
||
const replaceStatus = $('#replaceStatus').val();
|
||
const customerId = $('#customerId').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-replace/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&billOfLadingNumber=' + billOfLadingNumber + '&masterPackageNumber=' + masterPackageNumber + '&referenceNumber=' + referenceNumber + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&replaceStatus=' + replaceStatus + '&customerId=' + customerId;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderLabelReplaceTable(response.data);
|
||
renderPagination('labelReplace', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
// 显示通知
|
||
$('#resultCount').text(response.totalCount);
|
||
const toast = new bootstrap.Toast($('#queryNotification'));
|
||
toast.show();
|
||
} else {
|
||
alert('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
alert('请求失败: ' + error);
|
||
}
|
||
});
|
||
} else if (prefix === 'labelScan') {
|
||
const pageSize = getScanPageSize();
|
||
const sortBy = $('#scanSortBy').val();
|
||
const sortOrder = $('#scanSortOrder').val();
|
||
const customerId = $('#scanCustomerId').val();
|
||
const neutralWaybillNumber = $('#scanNeutralWaybillNumber').val();
|
||
const finalMileTrackingNumber = $('#scanFinalMileTrackingNumber').val();
|
||
const result = $('#scanResult').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-scan/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&customerId=' + customerId + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&result=' + result;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderLabelScanTable(response.data);
|
||
renderPagination('labelScan', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
// 显示通知
|
||
$('#resultCount').text(response.totalCount);
|
||
const toast = new bootstrap.Toast($('#queryNotification'));
|
||
toast.show();
|
||
} else {
|
||
alert('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
alert('请求失败: ' + error);
|
||
}
|
||
});
|
||
} else if (prefix === 'arrivalBatch') {
|
||
const pageSize = getArrivalPageSize();
|
||
const sortBy = $('#arrivalSortBy').val();
|
||
const sortOrder = $('#arrivalSortOrder').val();
|
||
const trackingNumber = $('#trackingNumber').val().trim().replace(/\s+/g, ','); // 将多行输入转换为逗号分隔的字符串
|
||
|
||
const url = getBaseUrl() + '/api/arrival-batch/batch?page=' + page + '&pageSize=' + pageSize + '&sortBy=' + sortBy + '&sortOrder=' + sortOrder + '&trackingNumber=' + trackingNumber;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: 'jsonpCallback',
|
||
success: function(response) {
|
||
if (response.status === 'ok') {
|
||
renderArrivalBatchTable(response.data);
|
||
renderPagination('arrivalBatch', response.page, response.pageSize, response.totalPages, response.totalCount);
|
||
} else {
|
||
alert('查询失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
alert('请求失败: ' + error);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 重置标签替换请求表单
|
||
$('#resetLabelReplaceForm').click(function() {
|
||
$('#labelReplaceForm')[0].reset();
|
||
});
|
||
|
||
// 重置标签扫描记录表单
|
||
$('#resetLabelScanForm').click(function() {
|
||
$('#labelScanForm')[0].reset();
|
||
});
|
||
|
||
// 导出标签替换请求Excel
|
||
$('#exportExcelBtn').click(function() {
|
||
const billOfLadingNumber = $('#billOfLadingNumber').val();
|
||
const masterPackageNumber = $('#masterPackageNumber').val();
|
||
const referenceNumber = $('#referenceNumber').val();
|
||
const neutralWaybillNumber = $('#neutralWaybillNumber').val().trim().replace(/\s+/g, ','); // 将多行输入转换为逗号分隔的字符串
|
||
const finalMileTrackingNumber = $('#finalMileTrackingNumber').val();
|
||
const replaceStatus = $('#replaceStatus').val();
|
||
const customerId = $('#customerId').val();
|
||
const startCreatedAt = $('#startCreatedAt').val();
|
||
const endCreatedAt = $('#endCreatedAt').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-replace/export-excel?billOfLadingNumber=' + billOfLadingNumber + '&masterPackageNumber=' + masterPackageNumber + '&referenceNumber=' + referenceNumber + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&replaceStatus=' + replaceStatus + '&customerId=' + customerId + '&startCreatedAt=' + startCreatedAt + '&endCreatedAt=' + endCreatedAt;
|
||
|
||
// 打开新窗口下载Excel文件
|
||
window.open(url, '_blank');
|
||
});
|
||
|
||
// 导出标签扫描记录Excel
|
||
$('#exportScanExcelBtn').click(function() {
|
||
const customerId = $('#scanCustomerId').val();
|
||
const neutralWaybillNumber = $('#scanNeutralWaybillNumber').val();
|
||
const finalMileTrackingNumber = $('#scanFinalMileTrackingNumber').val();
|
||
const result = $('#scanResult').val();
|
||
|
||
const url = getBaseUrl() + '/api/Label/label-scan/export-excel?customerId=' + customerId + '&neutralWaybillNumber=' + neutralWaybillNumber + '&finalMileTrackingNumber=' + finalMileTrackingNumber + '&result=' + result;
|
||
|
||
// 打开新窗口下载Excel文件
|
||
window.open(url, '_blank');
|
||
});
|
||
|
||
// 导出Excel函数
|
||
function exportExcel(sheets, fileName) {
|
||
// 获取当前时间并格式化
|
||
const now = new Date();
|
||
const timeStr = now.getFullYear() + '-' +
|
||
(now.getMonth() + 1).toString().padStart(2, '0') + '-' +
|
||
now.getDate().toString().padStart(2, '0') + ' ' +
|
||
now.getHours().toString().padStart(2, '0') + '-' +
|
||
now.getMinutes().toString().padStart(2, '0') + '-' +
|
||
now.getSeconds().toString().padStart(2, '0');
|
||
|
||
// 创建一个新的工作簿
|
||
const wb = XLSX.utils.book_new();
|
||
|
||
// 为每个sheet添加数据
|
||
sheets.forEach(sheet => {
|
||
// 将JSON数据转换为工作表
|
||
const ws = XLSX.utils.json_to_sheet(sheet.data);
|
||
// 将工作表添加到工作簿
|
||
XLSX.utils.book_append_sheet(wb, ws, sheet.sheetName);
|
||
});
|
||
|
||
// 导出Excel文件,文件名包含导出时间
|
||
XLSX.writeFile(wb, fileName + ' ' + timeStr + '.xlsx');
|
||
}
|
||
|
||
// 编辑出货交接单
|
||
$('.edit-btn').click(function() {
|
||
const id = $(this).data('id');
|
||
// 获取出货交接单详情
|
||
const url = getBaseUrl() + '/api/shipping-handover/get/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
const form = response.data;
|
||
// 填充编辑表单
|
||
$('#editFormId').val(form.Id);
|
||
$('#editDeliveryTime').val(form.DeliveryTime ? new Date(form.DeliveryTime).toISOString().slice(0, 16) : '');
|
||
$('#editTimezone').val(form.TimeZone || 'America/New_York');
|
||
$('#editRemarks').val(form.Remarks || '');
|
||
// 显示模态框
|
||
$('#editShippingHandoverModal').modal('show');
|
||
} else {
|
||
showBubbleNotification('获取出货交接单详情失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('获取出货交接单详情失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
|
||
// 保存编辑
|
||
$('#saveEditBtn').click(function() {
|
||
const id = $('#editFormId').val();
|
||
const deliveryTime = $('#editDeliveryTime').val();
|
||
const remarks = $('#editRemarks').val();
|
||
const timezone = $('#editTimezone').val();
|
||
|
||
// 发送更新请求
|
||
const url = getBaseUrl() + '/api/shipping-handover/update/' + id;
|
||
|
||
$.ajax({
|
||
url: url,
|
||
type: 'GET',
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
data: {
|
||
DeliveryTime: deliveryTime,
|
||
Remarks: remarks,
|
||
TimeZone: timezone
|
||
},
|
||
success: function(response) {
|
||
if (response.code === 0) {
|
||
showBubbleNotification('编辑成功');
|
||
// 关闭模态框
|
||
$('#editShippingHandoverModal').modal('hide');
|
||
// 重新查询数据
|
||
$('#shippingHandoverForm').submit();
|
||
} else {
|
||
showBubbleNotification('编辑失败: ' + response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
showBubbleNotification('编辑失败: ' + error);
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<!-- 编辑出货交接单模态框 -->
|
||
<div class="modal fade" id="editShippingHandoverModal" tabindex="-1" aria-labelledby="editShippingHandoverModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="editShippingHandoverModalLabel">编辑出货交接单</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="editShippingHandoverForm">
|
||
<input type="hidden" id="editFormId">
|
||
<div class="mb-3">
|
||
<label for="editDeliveryTime" class="form-label">交货时间</label>
|
||
<input type="datetime-local" class="form-control" id="editDeliveryTime">
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editTimezone" class="form-label">时区</label>
|
||
<select class="form-select" id="editTimezone">
|
||
<option value="America/New_York">美国纽约 (东部时间 UTC-5)</option>
|
||
<option value="America/Chicago">美国芝加哥 (中部时间 UTC-6)</option>
|
||
<option value="America/Denver">美国丹佛 (山地时间 UTC-7)</option>
|
||
<option value="America/Los_Angeles">美国洛杉矶 (太平洋时间 UTC-8)</option>
|
||
<option value="America/Anchorage">美国安克雷奇 (阿拉斯加时间 UTC-9)</option>
|
||
<option value="America/Honolulu">美国檀香山 (夏威夷时间 UTC-10)</option>
|
||
<option value="Asia/Shanghai">中国标准时间 (UTC+8)</option>
|
||
<option value="UTC">协调世界时 (UTC)</option>
|
||
</select>
|
||
</div>
|
||
<div class="mb-3">
|
||
<label for="editRemarks" class="form-label">备注</label>
|
||
<textarea class="form-control" id="editRemarks" rows="3"></textarea>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
|
||
<button type="button" class="btn btn-primary" id="saveEditBtn">保存</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 订单导入脚本 -->
|
||
<script>
|
||
$(document).ready(function() {
|
||
// 初始化客户选择
|
||
initCustomerSelect();
|
||
|
||
// 订单导入表单提交
|
||
$('#orderImportForm').submit(function(e) {
|
||
e.preventDefault();
|
||
importOrders();
|
||
});
|
||
|
||
// 重置按钮
|
||
$('#resetOrderImportForm').click(function() {
|
||
$('#orderImportForm')[0].reset();
|
||
$('#importProgress').hide();
|
||
$('#importResult').hide();
|
||
});
|
||
|
||
// 下载模板按钮
|
||
$('#downloadTemplateBtn').click(function() {
|
||
downloadExcelTemplate();
|
||
});
|
||
|
||
// 客户选择变更事件
|
||
$('#importCustomerId').change(function() {
|
||
const customerId = $(this).val();
|
||
const customerCode = $(this).find('option:selected').text();
|
||
if (customerId) {
|
||
getCustomerApiKey(customerId, customerCode);
|
||
} else {
|
||
customerInfo = {
|
||
id: '',
|
||
code: '',
|
||
apiKey: ''
|
||
};
|
||
}
|
||
});
|
||
|
||
|
||
});
|
||
|
||
// 存储客户信息
|
||
let customerInfo = {
|
||
id: '',
|
||
code: '',
|
||
apiKey: ''
|
||
};
|
||
|
||
// 获取客户API密钥
|
||
function getCustomerApiKey(customerId, customerCode) {
|
||
// 存储客户代码
|
||
customerInfo.id = customerId;
|
||
customerInfo.code = customerCode;
|
||
|
||
const environment = $('#environment').val();
|
||
let apiUrl = '';
|
||
|
||
switch (environment) {
|
||
case 'local':
|
||
apiUrl = 'http://localhost:5002/api/Tag/customer-api';
|
||
break;
|
||
case 'test':
|
||
apiUrl = 'http://172.232.21.79:5002/api/Tag/customer-api';
|
||
break;
|
||
case 'production':
|
||
apiUrl = 'https://lr.tooexp.com/api/Tag/customer-api';
|
||
break;
|
||
default:
|
||
apiUrl = 'http://172.232.21.79:5002/api/Tag/customer-api';
|
||
}
|
||
|
||
// 使用JSONP进行跨域请求
|
||
const callbackName = 'customerApiCallback_' + Date.now();
|
||
window[callbackName] = function(response) {
|
||
if (response.status === 'ok' && response.data) {
|
||
customerInfo.apiKey = response.data.ApiKey;
|
||
console.log('Customer API key retrieved successfully');
|
||
} else {
|
||
customerInfo.apiKey = '';
|
||
console.error('Failed to retrieve customer API key:', response.message);
|
||
}
|
||
delete window[callbackName];
|
||
};
|
||
|
||
// 使用jQuery的JSONP请求
|
||
$.ajax({
|
||
url: apiUrl,
|
||
type: 'GET',
|
||
data: {
|
||
customerId: customerId
|
||
},
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: callbackName,
|
||
success: function(response) {
|
||
console.log('Customer API response:', response);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to get customer API key:', error);
|
||
customerInfo.apiKey = '';
|
||
}
|
||
});
|
||
}
|
||
|
||
// 初始化客户选择
|
||
function initCustomerSelect() {
|
||
// 调用现有的加载客户列表函数
|
||
loadCustomerList();
|
||
}
|
||
|
||
// 导入订单
|
||
function importOrders() {
|
||
const customerId = $('#importCustomerId').val();
|
||
const labelMapping = $('#labelFilenameMapping').val();
|
||
const fileInput = $('#excelFile')[0];
|
||
|
||
if (!customerId) {
|
||
alert('请选择客户');
|
||
return;
|
||
}
|
||
|
||
if (!fileInput.files || fileInput.files.length === 0) {
|
||
alert('请选择Excel文件');
|
||
return;
|
||
}
|
||
|
||
const file = fileInput.files[0];
|
||
const reader = new FileReader();
|
||
|
||
reader.onload = function(e) {
|
||
try {
|
||
const data = new Uint8Array(e.target.result);
|
||
const workbook = XLSX.read(data, { type: 'array' });
|
||
const firstSheetName = workbook.SheetNames[0];
|
||
const worksheet = workbook.Sheets[firstSheetName];
|
||
const jsonData = XLSX.utils.sheet_to_json(worksheet);
|
||
|
||
if (jsonData.length === 0) {
|
||
alert('Excel文件中没有数据');
|
||
return;
|
||
}
|
||
|
||
// 处理订单数据
|
||
const orders = processOrders(jsonData, labelMapping);
|
||
|
||
// 显示进度条
|
||
showProgress(orders.length);
|
||
|
||
// 调用API导入订单
|
||
importOrdersToApi(orders);
|
||
} catch (error) {
|
||
alert('解析Excel文件失败: ' + error.message);
|
||
}
|
||
};
|
||
|
||
reader.onerror = function() {
|
||
alert('读取文件失败');
|
||
};
|
||
|
||
reader.readAsArrayBuffer(file);
|
||
}
|
||
|
||
// 处理订单数据
|
||
function processOrders(jsonData, labelMapping) {
|
||
const orders = [];
|
||
const fixedDate = '20260302';
|
||
const maxUrlLength = 2048; // URL最大长度限制
|
||
|
||
jsonData.forEach(row => {
|
||
const order = {
|
||
BillOfLadingNumber: row.BillOfLadingNumber || null,
|
||
MasterPackageNumber: row.MasterPackageNumber || null,
|
||
NeutralWaybillNumber: row.NeutralWaybillNumber || '',
|
||
FinalMileTrackingNumber: row.FinalMileTrackingNumber || null,
|
||
Label: row.Label || null,
|
||
ReplaceStatus: 'Y'
|
||
};
|
||
|
||
// 生成标签URL
|
||
if (!order.Label && labelMapping !== 'none') {
|
||
let filename = '';
|
||
if (labelMapping === 'neutralWaybill' && order.NeutralWaybillNumber) {
|
||
filename = order.NeutralWaybillNumber;
|
||
} else if (labelMapping === 'finalMileTracking' && order.FinalMileTrackingNumber) {
|
||
filename = order.FinalMileTrackingNumber;
|
||
}
|
||
|
||
if (filename) {
|
||
// 生成URL
|
||
let url = `http://172.232.21.79/api-lable/pdf/${fixedDate}/${filename}.pdf`;
|
||
|
||
// 检查URL有效性和长度
|
||
if (isValidUrl(url) && url.length <= maxUrlLength) {
|
||
order.Label = url;
|
||
}
|
||
}
|
||
}
|
||
|
||
orders.push(order);
|
||
});
|
||
|
||
return orders;
|
||
}
|
||
|
||
// 验证URL有效性
|
||
function isValidUrl(url) {
|
||
try {
|
||
new URL(url);
|
||
return true;
|
||
} catch (error) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 显示进度条
|
||
function showProgress(total) {
|
||
$('#importProgress').show();
|
||
$('#importResult').hide();
|
||
$('#totalOrders').text(total);
|
||
$('#processedOrders').text('0');
|
||
$('#progressPercentage').text('0%');
|
||
$('.progress-bar').css('width', '0%').attr('aria-valuenow', '0');
|
||
$('#importStatus').text('准备导入...');
|
||
}
|
||
|
||
// 更新进度
|
||
function updateProgress(processed, total) {
|
||
const percentage = Math.round((processed / total) * 100);
|
||
$('#processedOrders').text(processed);
|
||
$('#progressPercentage').text(percentage + '%');
|
||
$('.progress-bar').css('width', percentage + '%').attr('aria-valuenow', percentage);
|
||
$('#importStatus').text(`正在导入... ${processed}/${total}`);
|
||
}
|
||
|
||
// 调用API导入订单
|
||
function importOrdersToApi(orders) {
|
||
// 使用从customer_apis表获取的API密钥
|
||
const apiKey = customerInfo.apiKey;
|
||
const customerCode = customerInfo.code;
|
||
|
||
// 验证API密钥和客户代码
|
||
if (!apiKey || !customerCode) {
|
||
// 尝试重新获取API密钥
|
||
const customerId = $('#importCustomerId').val();
|
||
const selectedCustomerCode = $('#importCustomerId').find('option:selected').text();
|
||
|
||
if (customerId) {
|
||
// 同步获取API密钥
|
||
$.ajax({
|
||
url: getApiUrlForCustomerApi(),
|
||
type: 'GET',
|
||
data: {
|
||
customerId: customerId
|
||
},
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
async: false,
|
||
success: function(response) {
|
||
if (response.status === 'ok' && response.data) {
|
||
customerInfo.apiKey = response.data.ApiKey;
|
||
customerInfo.code = selectedCustomerCode;
|
||
customerInfo.id = customerId;
|
||
console.log('Customer API key retrieved successfully');
|
||
} else {
|
||
customerInfo.apiKey = '';
|
||
console.error('Failed to retrieve customer API key:', response.message);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to get customer API key:', error);
|
||
customerInfo.apiKey = '';
|
||
}
|
||
});
|
||
|
||
// 再次检查
|
||
if (!customerInfo.apiKey || !customerInfo.code) {
|
||
alert('无法获取客户API密钥或客户代码,请重新选择客户');
|
||
return;
|
||
}
|
||
} else {
|
||
alert('请选择客户');
|
||
return;
|
||
}
|
||
}
|
||
|
||
const environment = $('#environment').val();
|
||
let apiUrl = '';
|
||
|
||
switch (environment) {
|
||
case 'local':
|
||
apiUrl = 'http://localhost:5002/api/tag/order-import';
|
||
break;
|
||
case 'test':
|
||
apiUrl = 'http://172.232.21.79:5002/api/tag/order-import';
|
||
break;
|
||
case 'production':
|
||
apiUrl = 'https://lr.tooexp.com/api/tag/order-import';
|
||
break;
|
||
default:
|
||
apiUrl = 'http://172.232.21.79:5002/api/tag/order-import';
|
||
}
|
||
|
||
// 分批处理订单,每批5个(减少URL长度)
|
||
const batchSize = 5;
|
||
const batches = [];
|
||
for (let i = 0; i < orders.length; i += batchSize) {
|
||
batches.push(orders.slice(i, i + batchSize));
|
||
}
|
||
|
||
// 存储所有批次的结果
|
||
const allResults = {
|
||
Status: 'ok',
|
||
TotalCount: 0,
|
||
SuccessCount: 0,
|
||
FailedCount: 0,
|
||
Results: []
|
||
};
|
||
|
||
let processedBatches = 0;
|
||
let processedOrders = 0;
|
||
const totalBatches = batches.length;
|
||
|
||
// 处理每个批次
|
||
batches.forEach(function(batch, batchIndex) {
|
||
// 使用JSONP进行跨域请求
|
||
const callbackName = 'jsonpCallback_' + Date.now() + '_' + batchIndex;
|
||
window[callbackName] = function(response) {
|
||
// 处理批次响应
|
||
if (response.Status === 'ok') {
|
||
allResults.TotalCount += response.TotalCount;
|
||
allResults.SuccessCount += response.SuccessCount;
|
||
allResults.FailedCount += response.FailedCount;
|
||
allResults.Results = allResults.Results.concat(response.Results);
|
||
}
|
||
|
||
processedBatches++;
|
||
processedOrders += batch.length;
|
||
|
||
// 更新进度
|
||
updateProgress(processedOrders, orders.length);
|
||
|
||
// 检查是否所有批次都已处理完成
|
||
if (processedBatches === totalBatches) {
|
||
displayImportResult(allResults);
|
||
}
|
||
|
||
delete window[callbackName];
|
||
};
|
||
|
||
// 构建请求数据
|
||
const requestData = {
|
||
Orders: batch
|
||
};
|
||
|
||
// 序列化数据
|
||
const dataString = JSON.stringify(requestData);
|
||
|
||
// 使用jQuery的JSONP请求
|
||
$.ajax({
|
||
url: apiUrl,
|
||
type: 'GET',
|
||
data: {
|
||
data: dataString,
|
||
customerCode: customerCode,
|
||
apiKey: apiKey
|
||
},
|
||
dataType: 'jsonp',
|
||
jsonp: 'callback',
|
||
jsonpCallback: callbackName,
|
||
success: function(response) {
|
||
console.log('Batch import response:', response);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('Failed to import batch:', error);
|
||
|
||
// 处理错误情况
|
||
allResults.Status = 'error';
|
||
allResults.Results.push({
|
||
BillOfLadingNumber: '',
|
||
MasterPackageNumber: '',
|
||
NeutralWaybillNumber: '',
|
||
FinalMileTrackingNumber: '',
|
||
Status: 'error',
|
||
Message: '导入失败: ' + error,
|
||
Label: ''
|
||
});
|
||
|
||
processedBatches++;
|
||
processedOrders += batch.length;
|
||
|
||
// 更新进度
|
||
updateProgress(processedOrders, orders.length);
|
||
|
||
// 检查是否所有批次都已处理完成
|
||
if (processedBatches === totalBatches) {
|
||
displayImportResult(allResults);
|
||
}
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
|
||
|
||
// 显示导入结果
|
||
function displayImportResult(response) {
|
||
$('#importProgress').hide();
|
||
$('#importResult').show();
|
||
|
||
if (response.Status === 'ok') {
|
||
$('#resultTotalCount').text(response.TotalCount);
|
||
$('#resultSuccessCount').text(response.SuccessCount);
|
||
$('#resultFailedCount').text(response.FailedCount);
|
||
|
||
const successRate = response.TotalCount > 0
|
||
? Math.round((response.SuccessCount / response.TotalCount) * 100)
|
||
: 0;
|
||
$('#resultSuccessRate').text(successRate + '%');
|
||
|
||
// 填充结果表格
|
||
const tbody = $('#importResultTableBody');
|
||
tbody.empty();
|
||
|
||
response.Results.forEach(item => {
|
||
const row = $('<tr></tr>');
|
||
row.append(`<td>${item.BillOfLadingNumber || '-'}</td>`);
|
||
row.append(`<td>${item.MasterPackageNumber || '-'}</td>`);
|
||
row.append(`<td>${item.NeutralWaybillNumber || '-'}</td>`);
|
||
row.append(`<td>${item.FinalMileTrackingNumber || '-'}</td>`);
|
||
|
||
const statusCell = $('<td></td>');
|
||
if (item.Status === 'ok') {
|
||
statusCell.addClass('text-success').text('成功');
|
||
} else {
|
||
statusCell.addClass('text-danger').text('失败');
|
||
}
|
||
row.append(statusCell);
|
||
|
||
row.append(`<td>${item.Message || '-'}</td>`);
|
||
row.append(`<td>${item.Label || '-'}</td>`);
|
||
tbody.append(row);
|
||
});
|
||
} else {
|
||
alert('导入失败: ' + (response.Message || response.message || '未知错误'));
|
||
}
|
||
}
|
||
|
||
// 获取客户API的URL
|
||
function getApiUrlForCustomerApi() {
|
||
const environment = $('#environment').val();
|
||
let apiUrl = '';
|
||
|
||
switch (environment) {
|
||
case 'local':
|
||
apiUrl = 'http://localhost:5002/api/Tag/customer-api';
|
||
break;
|
||
case 'test':
|
||
apiUrl = 'http://172.232.21.79:5002/api/Tag/customer-api';
|
||
break;
|
||
case 'production':
|
||
apiUrl = 'https://lr.tooexp.com/api/Tag/customer-api';
|
||
break;
|
||
default:
|
||
apiUrl = 'http://172.232.21.79:5002/api/Tag/customer-api';
|
||
}
|
||
|
||
return apiUrl;
|
||
}
|
||
|
||
// 下载Excel模板
|
||
function downloadExcelTemplate() {
|
||
// 创建工作簿
|
||
const wb = XLSX.utils.book_new();
|
||
|
||
// 创建工作表数据
|
||
const headers = [
|
||
'BillOfLadingNumber', // 提单号
|
||
'MasterPackageNumber', // 大包号
|
||
'NeutralWaybillNumber', // 中性面单单号(必填)
|
||
'FinalMileTrackingNumber', // 尾程单号
|
||
'Label' // 标签内容(可选)
|
||
];
|
||
|
||
// 创建工作表
|
||
const ws = XLSX.utils.aoa_to_sheet([headers]);
|
||
|
||
// 添加工作表到工作簿
|
||
XLSX.utils.book_append_sheet(wb, ws, '订单模板');
|
||
|
||
// 生成Excel文件并下载
|
||
XLSX.writeFile(wb, '订单导入模板.xlsx');
|
||
}
|
||
|
||
|
||
</script>
|
||
</div>
|
||
</body>
|
||
</html> |