修复编辑配置,保存和回显的问题
This commit is contained in:
@@ -129,7 +129,7 @@ FIELD_MAPPING = {
|
||||
# 订单完成信息
|
||||
'finish_type': '完成类型',
|
||||
'finish_code': '完成代码',
|
||||
'finish_msg': '完成消息',
|
||||
'finish_msg': '结束原因',
|
||||
'finish_time': '完成时间',
|
||||
|
||||
# 取消信息
|
||||
|
||||
@@ -397,6 +397,18 @@ font-weight: 500;
|
||||
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"] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
@@ -62,6 +62,8 @@ function showCreateModal() {
|
||||
document.getElementById('modal-title').textContent = '创建配置';
|
||||
document.getElementById('config-name').value = '';
|
||||
document.getElementById('split-type').value = '';
|
||||
// 清空已选实体
|
||||
selectedEntityIds.clear();
|
||||
// 清空实体列表
|
||||
document.getElementById('entity-list').innerHTML = '<div class="empty">请先选择拆分方式</div>';
|
||||
document.getElementById('entity-search').value = '';
|
||||
@@ -141,7 +143,7 @@ function renderFields(selectedFields = [], sumFields = []) {
|
||||
${isSelected ? 'checked' : ''}
|
||||
${isRequired ? 'disabled checked' : ''}
|
||||
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>
|
||||
`;
|
||||
}).join('');
|
||||
@@ -209,13 +211,13 @@ function refreshSelectedFieldsOrder(selectedFields, customNames = null) {
|
||||
return `
|
||||
<div class="selected-field-item" data-field="${fieldKey}">
|
||||
<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}"
|
||||
onchange="updateFieldCustomName('${fieldKey}', this.value)"
|
||||
style="flex: 1; min-width: 100px; padding: 4px 8px; font-size: 12px;">
|
||||
<div class="field-actions">
|
||||
<button type="button" class="btn-move" onclick="moveFieldUp(${index})" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
||||
<button type="button" class="btn-move" onclick="moveFieldDown(${index})" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
||||
<button type="button" class="btn-move" onclick="moveFieldUp('${fieldKey}')" ${isFirst ? 'disabled' : ''} title="上移">↑</button>
|
||||
<button type="button" class="btn-move" onclick="moveFieldDown('${fieldKey}')" ${isLast ? 'disabled' : ''} title="下移">↓</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -238,10 +240,12 @@ function getFieldCustomNames() {
|
||||
}
|
||||
|
||||
// 字段上移
|
||||
function moveFieldUp(index) {
|
||||
if (index <= 0) return;
|
||||
function moveFieldUp(fieldKey) {
|
||||
const orderList = document.getElementById('selected-fields-order');
|
||||
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 prevItem = items[index - 1];
|
||||
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 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 nextItem = items[index + 1];
|
||||
orderList.insertBefore(nextItem, item);
|
||||
@@ -297,7 +303,7 @@ function refreshSumFieldsList(selectedFields, currentSumFields) {
|
||||
<div class="checkbox-item ${currentSumFields.includes(field.key) ? 'checked' : ''}" onclick="toggleCheckboxItem(this)">
|
||||
<input type="checkbox" value="${field.key}"
|
||||
${currentSumFields.includes(field.key) ? 'checked' : ''}>
|
||||
<label>${field.display}</label>
|
||||
<label>${field.display} <span class="field-key-name">(${field.key})</span></label>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
@@ -465,14 +471,43 @@ async function saveConfig() {
|
||||
// 处理多选:从 selectedEntityIds 获取选中的实体
|
||||
const splitValue = Array.from(selectedEntityIds).join(',');
|
||||
|
||||
// 获取选中实体的名称(需要从 DOM 中获取)
|
||||
const container = document.getElementById('entity-list');
|
||||
const checkboxes = container.querySelectorAll('input[type="checkbox"]:checked');
|
||||
const splitName = Array.from(checkboxes).map(cb => {
|
||||
const item = cb.closest('.checkbox-item');
|
||||
const span = item.querySelector('span');
|
||||
return span ? span.textContent.trim() : '';
|
||||
}).join(',');
|
||||
// 通过 API 查询所有已选实体的名称(确保翻页后也能正确获取)
|
||||
let splitName = '';
|
||||
if (selectedEntityIds.size > 0) {
|
||||
const entityType = splitType === 'company_id' ? 'company' :
|
||||
splitType === 'user_id' ? 'user' : 'station';
|
||||
try {
|
||||
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(',');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取实体名称失败:', err);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取字段顺序(从已选字段顺序列表获取)
|
||||
const selectedFields = getSelectedFieldsOrder();
|
||||
@@ -747,8 +782,9 @@ async function loadEntitiesForEdit(splitType, selectedValues) {
|
||||
container.innerHTML = mergedEntities.map(item => {
|
||||
const isChecked = item.isSelected ? 'checked' : '';
|
||||
const checkedClass = item.isSelected ? 'checked' : '';
|
||||
const topClass = item.isSelected ? 'entity-selected-top' : '';
|
||||
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()">
|
||||
<span>${item.name} ${item.typeLabel}</span>
|
||||
</div>
|
||||
@@ -882,6 +918,7 @@ async function moveConfig(configId, direction) {
|
||||
// 关闭模态框
|
||||
function closeModal() {
|
||||
document.getElementById('config-modal').classList.remove('active');
|
||||
selectedEntityIds.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -902,16 +939,6 @@ function setDefaultTimePeriods() {
|
||||
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() {
|
||||
try {
|
||||
|
||||
@@ -42,7 +42,9 @@ async function loadEntities(page = 1, search = '') {
|
||||
if (entities.length === 0) {
|
||||
container.innerHTML = '<div class="empty">无数据</div>';
|
||||
} else {
|
||||
container.innerHTML = entities.map(e => {
|
||||
const selected = [];
|
||||
const unselected = [];
|
||||
entities.forEach(e => {
|
||||
let value = '';
|
||||
let name = '';
|
||||
let typeLabel = '';
|
||||
@@ -62,11 +64,23 @@ async function loadEntities(page = 1, search = '') {
|
||||
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 `
|
||||
<div class="checkbox-item ${isChecked}" onclick="toggleEntityCheckbox(this, '${value}')">
|
||||
<input type="checkbox" value="${value}" ${isChecked} onclick="event.stopPropagation()">
|
||||
<span>${name} ${typeLabel}</span>
|
||||
<div class="checkbox-item ${isChecked} ${isSelectedTop ? 'entity-selected-top' : ''}" onclick="toggleEntityCheckbox(this, '${e.value}')">
|
||||
<input type="checkbox" value="${e.value}" ${isChecked} onclick="event.stopPropagation()">
|
||||
<span>${e.name} ${e.typeLabel}</span>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
@@ -89,15 +103,45 @@ function toggleEntityCheckbox(item, value) {
|
||||
|
||||
if (checkbox.checked) {
|
||||
item.classList.add('checked');
|
||||
item.classList.add('entity-selected-top');
|
||||
selectedEntityIds.add(String(value));
|
||||
} else {
|
||||
item.classList.remove('checked');
|
||||
item.classList.remove('entity-selected-top');
|
||||
selectedEntityIds.delete(String(value));
|
||||
}
|
||||
|
||||
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() {
|
||||
const countSpan = document.getElementById('selected-count');
|
||||
@@ -125,6 +169,7 @@ function toggleSelectAllEntities() {
|
||||
});
|
||||
|
||||
updateSelectedCount();
|
||||
reorderEntityList();
|
||||
}
|
||||
|
||||
// 更新实体分页UI
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<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>
|
||||
<body>
|
||||
<div class="container">
|
||||
@@ -350,11 +350,11 @@
|
||||
</div>
|
||||
|
||||
<!-- JavaScript 文件 -->
|
||||
<script src="/public/static/js/common.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/config.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/entity.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/report.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/history.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/sum_data.js?v=2026071502"></script>
|
||||
<script src="/public/static/js/common.js?v=2026071506"></script>
|
||||
<script src="/public/static/js/config.js?v=2026071506"></script>
|
||||
<script src="/public/static/js/entity.js?v=2026071506"></script>
|
||||
<script src="/public/static/js/report.js?v=2026071506"></script>
|
||||
<script src="/public/static/js/history.js?v=2026071506"></script>
|
||||
<script src="/public/static/js/sum_data.js?v=2026071506"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user