优化付款交货待办展示并支持列表快捷登记
This commit is contained in:
@@ -130,6 +130,58 @@ table.grid tr.row-off .btn { opacity: .8; }
|
||||
.badge.track-partial { background: #e6f0ff; color: #14509b; }
|
||||
.badge.track-received, .badge.track-delivered, .badge.track-paid { background: #e8f6ee; color: #12703f; }
|
||||
.mobile-only { display: none; }
|
||||
/* Payment / delivery workspace: independent states, task-first rows. */
|
||||
.tracking-dashboard .card-head { align-items: flex-start; }
|
||||
.tracking-dashboard .card-head > a { flex-shrink: 0; white-space: nowrap; }
|
||||
.tracking-dashboard .card-head p { margin: 6px 0 0; }
|
||||
.tracking-focus .stat { position: relative; border-top: 3px solid #d99a30; padding-right: 28px; }
|
||||
.tracking-focus .focus-paid_undelivered { border-top-color: #1668dc; }
|
||||
.tracking-focus .focus-recheck { border-top-color: #a65d26; }
|
||||
.tracking-focus .stat.selected { background: #eef5ff; border-color: #1668dc; }
|
||||
.tracking-focus .stat .k { color: #42526a; }
|
||||
.stat-arrow { position: absolute; right: 12px; top: 24px; color: #697a91; }
|
||||
.tracking-board-head { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
|
||||
.tracking-board-head h3 { margin: 0; }
|
||||
.tracking-filter { margin: 0 0 10px; flex-wrap: nowrap; }
|
||||
.tracking-filter select { width: auto; max-width: 240px; }
|
||||
.tracking-filter label { white-space: nowrap; }
|
||||
.status-steps { display: flex; list-style: none; margin: 0; padding: 0; gap: 3px; }
|
||||
.status-steps li { flex: 1; white-space: nowrap; text-align: center; padding: 6px 3px; border: 1px solid #e2e6ea; border-radius: 4px; font-size: 11px; color: #7b8490; background: #f7f8fa; }
|
||||
.status-steps .current { font-weight: 600; border-color: currentColor; }
|
||||
.status-steps .track-unpaid, .status-steps .track-pending { background: #fff4e0; color: #935100; }
|
||||
.status-steps .track-partial { background: #e6f0ff; color: #14509b; }
|
||||
.status-steps .track-paid, .status-steps .track-delivered { background: #e8f6ee; color: #12703f; }
|
||||
.order-progress { min-width: 154px; }
|
||||
.order-progress .badge, .order-progress .tracking-warning { display: inline-block; margin-bottom: 5px; }
|
||||
.order-progress.is-stale .current { color: #777; background: #eef0f2; }
|
||||
.tracking-tasks { display: flex; flex-wrap: wrap; gap: 4px; margin: 5px 0 9px; }
|
||||
.task-tag { color: #586577; font-size: 12px; line-height: 1.6; }
|
||||
.task-tag + .task-tag::before { content: '·'; margin-right: 4px; }
|
||||
.task-prepayment, .task-invoice_due, .task-recheck { color: #935100; font-weight: 600; }
|
||||
.task-closed { color: #12703f; }
|
||||
.tracking-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
|
||||
.tracking-actions .btn { white-space: nowrap; }
|
||||
.tracking-detail-link { font-size: 12px; display: inline-block; padding: 4px 0; }
|
||||
.supplier-name { margin: 5px 0; overflow-wrap: anywhere; }
|
||||
.order-identity { max-width: 240px; }
|
||||
.tracking-table td, .orders-table td { padding-top: 12px !important; padding-bottom: 12px !important; }
|
||||
.tracking-completed-link { border-top: 1px solid #e2e6ea; margin-top: 12px; padding-top: 12px; font-size: 12px; }
|
||||
.completed-toggle { display: flex; align-items: center; gap: 4px; margin: 0; color: #555; }
|
||||
.tracking-panels { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin: 12px 0 20px; }
|
||||
.tracking-panel { padding: 16px; border: 1px solid #dfe5ec; border-radius: 6px; min-width: 0; }
|
||||
.tracking-panel h3 { margin: 0 0 12px; }
|
||||
.tracking-panel .status-steps li { font-size: 13px; padding: 9px 3px; }
|
||||
.follow-note { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.7; }
|
||||
.update-meta { color: #637187; font-size: 12px; margin-bottom: 0; }
|
||||
#tracking-dialog { width: 540px; max-width: calc(100% - 24px); max-height: calc(100% - 32px); padding: 0; border: 0; border-radius: 10px; box-shadow: 0 16px 60px #0004; }
|
||||
#tracking-dialog::backdrop { background: #15253b80; }
|
||||
#tracking-dialog .modal-head { position: sticky; top: 0; background: white; z-index: 1; }
|
||||
#tracking-dialog h3 { margin: 14px 0; font-size: 15px; }
|
||||
#tracking-reload { margin-bottom: 12px; }
|
||||
.editor-order { line-height: 1.8; margin: 0; overflow-wrap: anywhere; }
|
||||
.tracking-editor-page { max-width: 600px; }
|
||||
.btn:disabled { opacity: .55; cursor: wait; }
|
||||
[hidden] { display: none !important; }
|
||||
@media (max-width: 800px) {
|
||||
.topbar { height: auto; min-height: 52px; flex-wrap: wrap; gap: 12px; padding: 12px 16px; }
|
||||
.topbar .brand { width: 100%; }
|
||||
@@ -143,6 +195,24 @@ table.grid tr.row-off .btn { opacity: .8; }
|
||||
.stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
|
||||
.tracking-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.tracking-forms { grid-template-columns: minmax(0, 1fr); }
|
||||
.tracking-panels { grid-template-columns: minmax(0, 1fr); }
|
||||
table.grid.order-cards { display: block; min-width: 0; }
|
||||
table.order-cards thead { display: none; }
|
||||
table.order-cards tbody { display: block; }
|
||||
table.order-cards tr { display: block; border: 1px solid #dfe5ec; border-radius: 8px; padding: 10px 12px; margin-bottom: 12px; background: #fff; }
|
||||
table.order-cards td { display: flex; gap: 10px; align-items: center; justify-content: space-between; border: 0; padding: 7px 0 !important; text-align: left; min-width: 0; max-width: none; }
|
||||
table.order-cards td::before { content: attr(data-label); font-size: 12px; color: #637187; flex: 0 0 55px; }
|
||||
table.order-cards .order-identity { display: block; padding-bottom: 10px !important; border-bottom: 1px solid #edf0f4; margin-bottom: 5px; }
|
||||
table.order-cards .order-identity::before, table.order-cards .order-next::before { display: none; }
|
||||
table.order-cards .order-next { display: block; border-top: 1px solid #edf0f4; margin-top: 5px; padding-top: 10px !important; }
|
||||
table.order-cards .order-progress { flex: 1; min-width: 0; max-width: 320px; }
|
||||
table.order-cards .tracking-tasks { flex: 1; }
|
||||
table.order-cards td[data-label="收票 / 待办"] { flex-wrap: wrap; }
|
||||
table.order-cards .empty-row td { display: block; }
|
||||
.tracking-actions .btn { display: inline-flex; align-items: center; }
|
||||
.tracking-filter { width: 100%; }
|
||||
.tracking-filter select { flex: 1; max-width: none; min-width: 0; }
|
||||
.tracking-panel { padding: 12px; }
|
||||
table.grid { min-width: 680px; }
|
||||
table.approval-flow { min-width: 0; }
|
||||
.mobile-only { display: block; }
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/* Reuse server forms and existing permissions; keep edits on the current list. */
|
||||
(function () {
|
||||
'use strict';
|
||||
var dialog = document.getElementById('tracking-dialog');
|
||||
if (!dialog || typeof dialog.showModal !== 'function' || !window.fetch) return;
|
||||
var content = document.getElementById('tracking-dialog-content');
|
||||
var errorBox = document.getElementById('tracking-dialog-error');
|
||||
var reload = document.getElementById('tracking-reload');
|
||||
var close = dialog.querySelector('[data-tracking-close]');
|
||||
var editorUrl = '', serial = 0, saving = false, opener;
|
||||
|
||||
function showError(message) {
|
||||
errorBox.textContent = message;
|
||||
errorBox.hidden = false;
|
||||
reload.hidden = false;
|
||||
}
|
||||
function errorText(html) {
|
||||
var doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
var message = doc.querySelector('.wrap .card p, body > p');
|
||||
return message ? message.textContent : '暂时无法完成操作,请重新读取当前状态后再试。';
|
||||
}
|
||||
async function loadEditor() {
|
||||
var current = ++serial;
|
||||
errorBox.hidden = reload.hidden = true;
|
||||
content.textContent = '正在读取最新状态…';
|
||||
try {
|
||||
var response = await fetch(editorUrl + '?fragment=1', {cache: 'no-store', credentials: 'same-origin'});
|
||||
var html = await response.text();
|
||||
if (current !== serial || !dialog.open) return;
|
||||
if (response.redirected) { window.location.assign(response.url); return; }
|
||||
if (!response.ok) { content.textContent = ''; showError(errorText(html)); return; }
|
||||
content.innerHTML = html;
|
||||
var field = content.querySelector('select, input:not([type=hidden])');
|
||||
if (field) field.focus();
|
||||
} catch (error) {
|
||||
if (current === serial && dialog.open) { content.textContent = ''; showError('读取失败,请检查连接后重试。'); }
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', function (event) {
|
||||
var link = event.target.closest('[data-quick-tracking]');
|
||||
if (!link || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
|
||||
event.preventDefault();
|
||||
opener = link;
|
||||
editorUrl = link.href;
|
||||
dialog.showModal();
|
||||
loadEditor();
|
||||
});
|
||||
close.addEventListener('click', function () { if (!saving) dialog.close(); });
|
||||
dialog.addEventListener('cancel', function (event) { if (saving) event.preventDefault(); });
|
||||
dialog.addEventListener('close', function () {
|
||||
++serial;
|
||||
content.textContent = '';
|
||||
if (opener) opener.focus();
|
||||
});
|
||||
reload.addEventListener('click', loadEditor);
|
||||
dialog.addEventListener('submit', async function (event) {
|
||||
var form = event.target;
|
||||
event.preventDefault();
|
||||
if (saving) return;
|
||||
var data = new FormData(form);
|
||||
var submit = form.querySelector('[type=submit]');
|
||||
saving = true;
|
||||
close.disabled = reload.disabled = submit.disabled = true;
|
||||
errorBox.hidden = reload.hidden = true;
|
||||
var retry = true;
|
||||
try {
|
||||
var response = await fetch(form.action, {method: 'POST', body: data,
|
||||
credentials: 'same-origin', headers: {'X-Tracking-Modal': '1'}});
|
||||
if (response.redirected) { window.location.assign(response.url); return; }
|
||||
if (response.ok && (response.headers.get('Content-Type') || '').indexOf('application/json') >= 0) {
|
||||
var result = await response.json();
|
||||
if (result.ok) { window.location.reload(); return; }
|
||||
}
|
||||
retry = response.status === 400;
|
||||
showError(errorText(await response.text()));
|
||||
} catch (error) {
|
||||
retry = false;
|
||||
showError('连接中断,无法确认是否保存成功。请重新读取当前状态,核对后再操作。');
|
||||
} finally {
|
||||
saving = false;
|
||||
close.disabled = reload.disabled = false;
|
||||
submit.disabled = !retry;
|
||||
}
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user