修复编辑配置,保存和回显的问题
This commit is contained in:
@@ -129,7 +129,7 @@ FIELD_MAPPING = {
|
|||||||
# 订单完成信息
|
# 订单完成信息
|
||||||
'finish_type': '完成类型',
|
'finish_type': '完成类型',
|
||||||
'finish_code': '完成代码',
|
'finish_code': '完成代码',
|
||||||
'finish_msg': '完成消息',
|
'finish_msg': '结束原因',
|
||||||
'finish_time': '完成时间',
|
'finish_time': '完成时间',
|
||||||
|
|
||||||
# 取消信息
|
# 取消信息
|
||||||
|
|||||||
@@ -397,6 +397,18 @@ font-weight: 500;
|
|||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.field-key-name {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: Consolas, Monaco, monospace;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entity-selected-top {
|
||||||
|
border-left: 3px solid #4472C4;
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
.checkbox-item input[type="checkbox"] {
|
.checkbox-item input[type="checkbox"] {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ function showCreateModal() {
|
|||||||
document.getElementById('modal-title').textContent = '创建配置';
|
document.getElementById('modal-title').textContent = '创建配置';
|
||||||
document.getElementById('config-name').value = '';
|
document.getElementById('config-name').value = '';
|
||||||
document.getElementById('split-type').value = '';
|
document.getElementById('split-type').value = '';
|
||||||
|
// 清空已选实体
|
||||||
|
selectedEntityIds.clear();
|
||||||
// 清空实体列表
|
// 清空实体列表
|
||||||
document.getElementById('entity-list').innerHTML = '<div class="empty">请先选择拆分方式</div>';
|
document.getElementById('entity-list').innerHTML = '<div class="empty">请先选择拆分方式</div>';
|
||||||
document.getElementById('entity-search').value = '';
|
document.getElementById('entity-search').value = '';
|
||||||
@@ -141,7 +143,7 @@ function renderFields(selectedFields = [], sumFields = []) {
|
|||||||
${isSelected ? 'checked' : ''}
|
${isSelected ? 'checked' : ''}
|
||||||
${isRequired ? 'disabled checked' : ''}
|
${isRequired ? 'disabled checked' : ''}
|
||||||
onchange="onFieldCheckboxChange(this)">
|
onchange="onFieldCheckboxChange(this)">
|
||||||
<label>${field.display}${isRequired ? ' <span class="required-badge">必选</span>' : ''}</label>
|
<label>${field.display} <span class="field-key-name">(${field.key})</span>${isRequired ? ' <span class="required-badge">必选</span>' : ''}</label>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}).join('');
|
}).join('');
|
||||||
@@ -209,13 +211,13 @@ function refreshSelectedFieldsOrder(selectedFields, customNames = null) {
|
|||||||
return `
|
return `
|
||||||
<div class="selected-field-item" data-field="${fieldKey}">
|
<div class="selected-field-item" data-field="${fieldKey}">
|
||||||
<span class="field-index">#${index + 1}</span>
|
<span class="field-index">#${index + 1}</span>
|
||||||
<span class="field-name" title="${displayName}">${displayName}</span>
|
<span class="field-name" title="${displayName}">${displayName} <span class="field-key-name">(${fieldKey})</span></span>
|
||||||
<input type="text" class="field-custom-name" placeholder="自定义报表名头" value="${customName}"
|
<input type="text" class="field-custom-name" placeholder="自定义报表名头" value="${customName}"
|
||||||
onchange="updateFieldCustomName('${fieldKey}', this.value)"
|
onchange="updateFieldCustomName('${fieldKey}', this.value)"
|
||||||
style="flex: 1; min-width: 100px; padding: 4px 8px; font-size: 12px;">
|
style="flex: 1; min-width: 100px; padding: 4px 8px; font-size: 12px;">
|
||||||
<div class="field-actions">
|
<div class="field-actions">
|
||||||
<button type="button" class="btn-move" onclick="moveFieldUp(${index})" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
<button type="button" class="btn-move" onclick="moveFieldUp('${fieldKey}')" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
||||||
<button type="button" class="btn-move" onclick="moveFieldDown(${index})" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
<button type="button" class="btn-move" onclick="moveFieldDown('${fieldKey}')" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@@ -238,10 +240,12 @@ function getFieldCustomNames() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 字段上移
|
// 字段上移
|
||||||
function moveFieldUp(index) {
|
function moveFieldUp(fieldKey) {
|
||||||
if (index <= 0) return;
|
|
||||||
const orderList = document.getElementById('selected-fields-order');
|
const orderList = document.getElementById('selected-fields-order');
|
||||||
const items = Array.from(orderList.querySelectorAll('.selected-field-item'));
|
const items = Array.from(orderList.querySelectorAll('.selected-field-item'));
|
||||||
|
const index = items.findIndex(item => item.dataset.field === fieldKey);
|
||||||
|
if (index <= 0) return;
|
||||||
|
|
||||||
const item = items[index];
|
const item = items[index];
|
||||||
const prevItem = items[index - 1];
|
const prevItem = items[index - 1];
|
||||||
orderList.insertBefore(item, prevItem);
|
orderList.insertBefore(item, prevItem);
|
||||||
@@ -249,10 +253,12 @@ function moveFieldUp(index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 字段下移
|
// 字段下移
|
||||||
function moveFieldDown(index) {
|
function moveFieldDown(fieldKey) {
|
||||||
const orderList = document.getElementById('selected-fields-order');
|
const orderList = document.getElementById('selected-fields-order');
|
||||||
const items = Array.from(orderList.querySelectorAll('.selected-field-item'));
|
const items = Array.from(orderList.querySelectorAll('.selected-field-item'));
|
||||||
if (index >= items.length - 1) return;
|
const index = items.findIndex(item => item.dataset.field === fieldKey);
|
||||||
|
if (index < 0 || index >= items.length - 1) return;
|
||||||
|
|
||||||
const item = items[index];
|
const item = items[index];
|
||||||
const nextItem = items[index + 1];
|
const nextItem = items[index + 1];
|
||||||
orderList.insertBefore(nextItem, item);
|
orderList.insertBefore(nextItem, item);
|
||||||
@@ -297,7 +303,7 @@ function refreshSumFieldsList(selectedFields, currentSumFields) {
|
|||||||
<div class="checkbox-item ${currentSumFields.includes(field.key) ? 'checked' : ''}" onclick="toggleCheckboxItem(this)">
|
<div class="checkbox-item ${currentSumFields.includes(field.key) ? 'checked' : ''}" onclick="toggleCheckboxItem(this)">
|
||||||
<input type="checkbox" value="${field.key}"
|
<input type="checkbox" value="${field.key}"
|
||||||
${currentSumFields.includes(field.key) ? 'checked' : ''}>
|
${currentSumFields.includes(field.key) ? 'checked' : ''}>
|
||||||
<label>${field.display}</label>
|
<label>${field.display} <span class="field-key-name">(${field.key})</span></label>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
}
|
}
|
||||||
@@ -465,14 +471,43 @@ async function saveConfig() {
|
|||||||
// 处理多选:从 selectedEntityIds 获取选中的实体
|
// 处理多选:从 selectedEntityIds 获取选中的实体
|
||||||
const splitValue = Array.from(selectedEntityIds).join(',');
|
const splitValue = Array.from(selectedEntityIds).join(',');
|
||||||
|
|
||||||
// 获取选中实体的名称(需要从 DOM 中获取)
|
// 通过 API 查询所有已选实体的名称(确保翻页后也能正确获取)
|
||||||
const container = document.getElementById('entity-list');
|
let splitName = '';
|
||||||
const checkboxes = container.querySelectorAll('input[type="checkbox"]:checked');
|
if (selectedEntityIds.size > 0) {
|
||||||
const splitName = Array.from(checkboxes).map(cb => {
|
const entityType = splitType === 'company_id' ? 'company' :
|
||||||
const item = cb.closest('.checkbox-item');
|
splitType === 'user_id' ? 'user' : 'station';
|
||||||
const span = item.querySelector('span');
|
try {
|
||||||
return span ? span.textContent.trim() : '';
|
const response = await fetch('/api/entities/by_ids', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ type: entityType, ids: Array.from(selectedEntityIds) })
|
||||||
|
});
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.success && result.data) {
|
||||||
|
const idSet = new Set(Array.from(selectedEntityIds));
|
||||||
|
const sortedEntities = result.data.filter(e => {
|
||||||
|
const value = splitType === 'company_id' ? e.company_id :
|
||||||
|
splitType === 'user_id' ? e.user_id : e.station_id;
|
||||||
|
return idSet.has(String(value));
|
||||||
|
}).sort((a, b) => {
|
||||||
|
const aVal = splitType === 'company_id' ? a.company_id :
|
||||||
|
splitType === 'user_id' ? a.user_id : a.station_id;
|
||||||
|
const bVal = splitType === 'company_id' ? b.company_id :
|
||||||
|
splitType === 'user_id' ? b.user_id : b.station_id;
|
||||||
|
const aIdx = Array.from(selectedEntityIds).indexOf(String(aVal));
|
||||||
|
const bIdx = Array.from(selectedEntityIds).indexOf(String(bVal));
|
||||||
|
return aIdx - bIdx;
|
||||||
|
});
|
||||||
|
splitName = sortedEntities.map(e => {
|
||||||
|
if (splitType === 'company_id') return e.company_name;
|
||||||
|
if (splitType === 'user_id') return e.user_name;
|
||||||
|
return e.station_name;
|
||||||
}).join(',');
|
}).join(',');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('获取实体名称失败:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取字段顺序(从已选字段顺序列表获取)
|
// 获取字段顺序(从已选字段顺序列表获取)
|
||||||
const selectedFields = getSelectedFieldsOrder();
|
const selectedFields = getSelectedFieldsOrder();
|
||||||
@@ -747,8 +782,9 @@ async function loadEntitiesForEdit(splitType, selectedValues) {
|
|||||||
container.innerHTML = mergedEntities.map(item => {
|
container.innerHTML = mergedEntities.map(item => {
|
||||||
const isChecked = item.isSelected ? 'checked' : '';
|
const isChecked = item.isSelected ? 'checked' : '';
|
||||||
const checkedClass = item.isSelected ? 'checked' : '';
|
const checkedClass = item.isSelected ? 'checked' : '';
|
||||||
|
const topClass = item.isSelected ? 'entity-selected-top' : '';
|
||||||
return `
|
return `
|
||||||
<div class="checkbox-item ${checkedClass}" onclick="toggleEntityCheckbox(this, '${item.value}')">
|
<div class="checkbox-item ${checkedClass} ${topClass}" onclick="toggleEntityCheckbox(this, '${item.value}')">
|
||||||
<input type="checkbox" value="${item.value}" ${isChecked} onclick="event.stopPropagation()">
|
<input type="checkbox" value="${item.value}" ${isChecked} onclick="event.stopPropagation()">
|
||||||
<span>${item.name} ${item.typeLabel}</span>
|
<span>${item.name} ${item.typeLabel}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -882,6 +918,7 @@ async function moveConfig(configId, direction) {
|
|||||||
// 关闭模态框
|
// 关闭模态框
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
document.getElementById('config-modal').classList.remove('active');
|
document.getElementById('config-modal').classList.remove('active');
|
||||||
|
selectedEntityIds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -902,16 +939,6 @@ function setDefaultTimePeriods() {
|
|||||||
updateTimePeriodSummary();
|
updateTimePeriodSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拆分方式改变时加载实体列表
|
|
||||||
function onSplitTypeChange() {
|
|
||||||
const splitType = document.getElementById('split-type').value;
|
|
||||||
if (splitType) {
|
|
||||||
loadEntities(1, '');
|
|
||||||
} else {
|
|
||||||
document.getElementById('entity-list').innerHTML = '<div class="empty">请先选择拆分方式</div>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出配置
|
// 导出配置
|
||||||
function exportConfigs() {
|
function exportConfigs() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ async function loadEntities(page = 1, search = '') {
|
|||||||
if (entities.length === 0) {
|
if (entities.length === 0) {
|
||||||
container.innerHTML = '<div class="empty">无数据</div>';
|
container.innerHTML = '<div class="empty">无数据</div>';
|
||||||
} else {
|
} else {
|
||||||
container.innerHTML = entities.map(e => {
|
const selected = [];
|
||||||
|
const unselected = [];
|
||||||
|
entities.forEach(e => {
|
||||||
let value = '';
|
let value = '';
|
||||||
let name = '';
|
let name = '';
|
||||||
let typeLabel = '';
|
let typeLabel = '';
|
||||||
@@ -62,11 +64,23 @@ async function loadEntities(page = 1, search = '') {
|
|||||||
name = e.station_name;
|
name = e.station_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChecked = selectedEntityIds.has(String(value)) ? 'checked' : '';
|
const item = { value, name, typeLabel };
|
||||||
|
if (selectedEntityIds.has(String(value))) {
|
||||||
|
selected.push(item);
|
||||||
|
} else {
|
||||||
|
unselected.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortedEntities = [...selected, ...unselected];
|
||||||
|
|
||||||
|
container.innerHTML = sortedEntities.map(e => {
|
||||||
|
const isChecked = selectedEntityIds.has(String(e.value)) ? 'checked' : '';
|
||||||
|
const isSelectedTop = selectedEntityIds.has(String(e.value));
|
||||||
return `
|
return `
|
||||||
<div class="checkbox-item ${isChecked}" onclick="toggleEntityCheckbox(this, '${value}')">
|
<div class="checkbox-item ${isChecked} ${isSelectedTop ? 'entity-selected-top' : ''}" onclick="toggleEntityCheckbox(this, '${e.value}')">
|
||||||
<input type="checkbox" value="${value}" ${isChecked} onclick="event.stopPropagation()">
|
<input type="checkbox" value="${e.value}" ${isChecked} onclick="event.stopPropagation()">
|
||||||
<span>${name} ${typeLabel}</span>
|
<span>${e.name} ${e.typeLabel}</span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}).join('');
|
}).join('');
|
||||||
@@ -89,15 +103,45 @@ function toggleEntityCheckbox(item, value) {
|
|||||||
|
|
||||||
if (checkbox.checked) {
|
if (checkbox.checked) {
|
||||||
item.classList.add('checked');
|
item.classList.add('checked');
|
||||||
|
item.classList.add('entity-selected-top');
|
||||||
selectedEntityIds.add(String(value));
|
selectedEntityIds.add(String(value));
|
||||||
} else {
|
} else {
|
||||||
item.classList.remove('checked');
|
item.classList.remove('checked');
|
||||||
|
item.classList.remove('entity-selected-top');
|
||||||
selectedEntityIds.delete(String(value));
|
selectedEntityIds.delete(String(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelectedCount();
|
updateSelectedCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重新排序列表(已选的在前面)
|
||||||
|
function reorderEntityList() {
|
||||||
|
const container = document.getElementById('entity-list');
|
||||||
|
const items = Array.from(container.querySelectorAll('.checkbox-item'));
|
||||||
|
if (items.length === 0) return;
|
||||||
|
|
||||||
|
const selected = [];
|
||||||
|
const unselected = [];
|
||||||
|
|
||||||
|
items.forEach(item => {
|
||||||
|
const checkbox = item.querySelector('input[type="checkbox"]');
|
||||||
|
if (checkbox.checked) {
|
||||||
|
selected.push(item);
|
||||||
|
item.classList.add('entity-selected-top');
|
||||||
|
} else {
|
||||||
|
unselected.push(item);
|
||||||
|
item.classList.remove('entity-selected-top');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 用文档片段移动,避免 innerHTML 清空导致状态丢失
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
[...selected, ...unselected].forEach(item => {
|
||||||
|
fragment.appendChild(item);
|
||||||
|
});
|
||||||
|
container.appendChild(fragment);
|
||||||
|
}
|
||||||
|
|
||||||
// 更新已选数量显示
|
// 更新已选数量显示
|
||||||
function updateSelectedCount() {
|
function updateSelectedCount() {
|
||||||
const countSpan = document.getElementById('selected-count');
|
const countSpan = document.getElementById('selected-count');
|
||||||
@@ -125,6 +169,7 @@ function toggleSelectAllEntities() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
updateSelectedCount();
|
updateSelectedCount();
|
||||||
|
reorderEntityList();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新实体分页UI
|
// 更新实体分页UI
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>订单日报系统</title>
|
<title>订单日报系统</title>
|
||||||
<link rel="stylesheet" href="/public/static/css/style.css?v=2026071502">
|
<link rel="stylesheet" href="/public/static/css/style.css?v=2026071506">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -350,11 +350,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- JavaScript 文件 -->
|
<!-- JavaScript 文件 -->
|
||||||
<script src="/public/static/js/common.js?v=2026071502"></script>
|
<script src="/public/static/js/common.js?v=2026071506"></script>
|
||||||
<script src="/public/static/js/config.js?v=2026071502"></script>
|
<script src="/public/static/js/config.js?v=2026071506"></script>
|
||||||
<script src="/public/static/js/entity.js?v=2026071502"></script>
|
<script src="/public/static/js/entity.js?v=2026071506"></script>
|
||||||
<script src="/public/static/js/report.js?v=2026071502"></script>
|
<script src="/public/static/js/report.js?v=2026071506"></script>
|
||||||
<script src="/public/static/js/history.js?v=2026071502"></script>
|
<script src="/public/static/js/history.js?v=2026071506"></script>
|
||||||
<script src="/public/static/js/sum_data.js?v=2026071502"></script>
|
<script src="/public/static/js/sum_data.js?v=2026071506"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user