ERP/frontend/js/components/shipments.js

324 lines
11 KiB
JavaScript
Raw Normal View History

Router.register('/upload/shipments', async () => {
setTimeout(() => {
const manualStatus = document.getElementById('ship-manual-status');
// 设置默认日期为今天
const dateInput = document.getElementById('ship-date');
if (dateInput && !dateInput.value) {
const today = new Date().toISOString().split('T')[0];
dateInput.value = today;
}
// 手动录入提交
const btn = document.getElementById('ship-upload');
btn?.addEventListener('click', async () => {
const date = document.getElementById('ship-date').value;
const qty = parseInt(document.getElementById('ship-qty').value || '0', 10);
const to = document.getElementById('ship-to').value;
const platform = document.getElementById('ship-manual-platform').value;
const boxNo = document.getElementById('ship-box-no').value.trim();
// 验证必填字段
if (!date) {
manualStatus.textContent = '✗ 请选择发货日期';
manualStatus.className = 'error';
return;
}
if (!platform) {
manualStatus.textContent = '✗ 请选择机种类型';
manualStatus.className = 'error';
return;
}
if (!to) {
manualStatus.textContent = '✗ 请输入接收方';
manualStatus.className = 'error';
return;
}
if (qty <= 0) {
manualStatus.textContent = '✗ 数量必须大于0';
manualStatus.className = 'error';
return;
}
try {
manualStatus.textContent = '提交中...';
manualStatus.className = '';
const payload = { date, qty, to, platform };
if (boxNo) {
payload.box_no = boxNo;
}
await API.uploadShipments(payload);
2025-12-15 01:38:42 +00:00
const platformName = {pdd: '拼多多', yt: '圆通', tx: '兔喜', mt: '美团', drf: '大润发', std: '标准版'}[platform] || platform;
manualStatus.textContent = `✓ 录入成功!机种:${platformName},数量:${qty}`;
manualStatus.className = 'success';
// 清空表单(保留日期和机种)
document.getElementById('ship-qty').value = '';
document.getElementById('ship-to').value = '';
document.getElementById('ship-box-no').value = '';
} catch(e) {
manualStatus.textContent = '✗ 录入失败:' + (e.message || '未知错误');
manualStatus.className = 'error';
}
});
const fileInput = document.getElementById('ship-file');
const validateBtn = document.getElementById('ship-validate');
const uploadFileBtn = document.getElementById('ship-upload-file');
const fileStatus = document.getElementById('ship-file-status');
fileInput?.addEventListener('change', () => {
fileStatus.textContent = '';
fileStatus.className = '';
});
validateBtn?.addEventListener('click', async () => {
const file = fileInput?.files?.[0];
if (!file) {
fileStatus.textContent = '请先选择文件';
fileStatus.className = 'error';
return;
}
const formData = new FormData();
formData.append('file', file);
try {
const res = await fetch('/api/validate/shipments-file', {
method: 'POST',
body: formData,
credentials: 'include'
});
if (!res.ok) {
const text = await res.text();
throw new Error(`HTTP ${res.status}: ${text}`);
}
const data = await res.json();
if (data.valid) {
fileStatus.textContent = '✓ ' + data.message;
fileStatus.className = 'success';
} else {
fileStatus.textContent = '✗ ' + data.message;
fileStatus.className = 'error';
}
} catch (e) {
fileStatus.textContent = '验证失败:' + e.message;
fileStatus.className = 'error';
}
});
uploadFileBtn?.addEventListener('click', async () => {
const file = fileInput?.files?.[0];
const platform = document.getElementById('ship-platform')?.value;
if (!platform) {
fileStatus.textContent = '✗ 请选择机种类型';
fileStatus.className = 'error';
return;
}
if (!file) {
fileStatus.textContent = '✗ 请先选择文件';
fileStatus.className = 'error';
return;
}
const formData = new FormData();
formData.append('file', file);
formData.append('platform', platform);
try {
fileStatus.textContent = '上传中...';
fileStatus.className = '';
const res = await fetch('/api/upload/shipments-file', {
method: 'POST',
body: formData,
credentials: 'include'
});
if (!res.ok) {
const text = await res.text();
throw new Error(`HTTP ${res.status}: ${text}`);
}
const data = await res.json();
if (data.ok) {
2025-12-15 01:38:42 +00:00
const platformName = {pdd: '拼多多', yt: '圆通', tx: '兔喜', mt: '美团', drf: '大润发', std: '标准版'}[platform] || platform;
fileStatus.textContent = `✓ 上传成功!机种:${platformName},共导入${data.count}个箱次,${data.total_qty}个SN`;
fileStatus.className = 'success';
fileInput.value = '';
document.getElementById('ship-platform').value = '';
} else {
fileStatus.textContent = '✗ ' + (data.error || '上传失败');
fileStatus.className = 'error';
}
} catch (e) {
fileStatus.textContent = '上传失败:' + e.message;
fileStatus.className = 'error';
}
});
}, 0);
2026-03-26 02:16:19 +00:00
return `
<style>
#shipments-page {
padding: 20px;
background: var(--bg);
}
#shipments-page .page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
#shipments-page h1 {
margin: 0;
font-size: 24px;
color: var(--text);
}
#shipments-page .content-area {
background: var(--surface);
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#shipments-page .section {
padding: 20px;
}
#shipments-page .section + .section {
border-top: 1px solid var(--border);
}
#shipments-page .section-title {
font-weight: 600;
font-size: 16px;
margin-bottom: 12px;
color: var(--text);
}
#shipments-page .section-desc {
font-size: 13px;
color: var(--text-2);
margin-bottom: 16px;
}
#shipments-page .format-requirements {
background: rgba(79,140,255,0.08);
border: 1px solid rgba(79,140,255,0.2);
border-radius: 8px;
padding: 12px;
margin-bottom: 16px;
font-size: 13px;
line-height: 1.6;
}
#shipments-page .row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16px;
margin-bottom: 16px;
}
@media (max-width: 768px) {
#shipments-page .row {
grid-template-columns: 1fr;
}
}
</style>
2026-03-26 02:16:19 +00:00
<div id="shipments-page">
<div class="page-header">
<h1>发货记录</h1>
</div>
2026-03-26 02:16:19 +00:00
<div class="content-area">
<div class="section">
<div class="section-title">手动录入</div>
<div class="section-desc">用于快速录入发货汇总信息不含详细SN</div>
<div class="row">
<div class="field">
<label>发货日期 <span style="color:var(--danger)">*</span></label>
<input id="ship-date" type="date" class="input" />
</div>
<div class="field">
<label>机种类型 <span style="color:var(--danger)">*</span></label>
<select id="ship-manual-platform" class="input">
<option value="">请选择机种</option>
<option value="pdd">拼多多</option>
<option value="yt">圆通</option>
<option value="tx">兔喜</option>
<option value="mt">美团</option>
<option value="drf">大润发</option>
<option value="std">标准版</option>
</select>
</div>
</div>
<div class="row">
<div class="field">
<label>接收方 <span style="color:var(--danger)">*</span></label>
<input id="ship-to" class="input" placeholder="客户名称" />
</div>
<div class="field">
<label>数量 <span style="color:var(--danger)">*</span></label>
<input id="ship-qty" type="number" min="1" class="input" placeholder="发货数量" />
</div>
</div>
<div class="field" style="margin-bottom:16px">
<label>箱号可选</label>
<input id="ship-box-no" class="input" placeholder="例如BOX001" />
</div>
<div id="ship-manual-status" style="margin:8px 0;font-size:13px"></div>
<div class="actions">
<button class="btn btn-primary" id="ship-upload">提交录入</button>
</div>
</div>
2026-03-26 02:16:19 +00:00
<div class="section">
<div class="section-title">详细记录批量导入</div>
<div class="format-requirements">
<div style="font-weight:600;margin-bottom:6px;color:var(--primary)">📋 文件格式要求</div>
<div style="color:var(--text)">
<div> 必需列出货日期箱号SN1SN2...SN20</div>
<div> 出货日期列支持合并单元格</div>
<div> 支持格式Excel (.xlsx, .xls) CSV</div>
</div>
</div>
<div class="field" style="margin-bottom:16px">
<label>机种类型 <span style="color:var(--danger)">*</span></label>
2026-03-26 02:16:19 +00:00
<select id="ship-platform" class="input">
<option value="">请选择机种</option>
<option value="pdd">拼多多</option>
<option value="yt">圆通</option>
<option value="tx">兔喜</option>
2025-12-15 01:38:42 +00:00
<option value="mt">美团</option>
<option value="drf">大润发</option>
<option value="std">标准版</option>
</select>
</div>
2026-03-26 02:16:19 +00:00
<div class="field" style="margin-bottom:16px">
<label>选择文件</label>
<input type="file" id="ship-file" accept=".xlsx,.xls,.csv" class="input" style="padding:6px" />
</div>
2026-03-26 02:16:19 +00:00
<div id="ship-file-status" style="margin:8px 0;font-size:13px"></div>
<div class="actions">
<button class="btn btn-secondary" id="ship-validate">验证文件</button>
<button class="btn btn-primary" id="ship-upload-file">导入数据</button>
</div>
</div>
</div>
</div>
2026-03-26 02:16:19 +00:00
`;
});