Files
2026-01-31 00:01:19 +08:00

411 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
(function () {
'use strict';
// ---------- 状态 ----------
var isLoggedIn = false; // 页面1 登录态,静态演示默认未登录
var currentView = 'list'; // list | detail
var currentRole = 'market'; // market | admin | engineer
var currentProjectId = null; // 当前详情/编辑的项目 ID,null 表示新建
var projects = [];
var listFiltered = [];
// ---------- Mock 数据 ----------
function getMockProjects() {
return [
{
id: '1',
name: '城东 110kV 输变电工程',
contractCode: 'HT-2024-001',
progress: '进行中',
costStatus: '正常',
ownerUnit: '市供电公司',
},
{
id: '2',
name: '高新区配电改造项目',
contractCode: 'HT-2024-002',
progress: '已竣工',
costStatus: '正常',
ownerUnit: '高新区管委会',
},
{
id: '3',
name: '西区 35kV 线路迁改',
contractCode: 'HT-2024-003',
progress: '筹备中',
costStatus: '节余',
ownerUnit: '西区建设局',
},
];
}
function getMockLogs(projectId) {
return [
{ operator: '张三', time: '2025-01-28 14:30', summary: '修改合同信息' },
{ operator: '李四', time: '2025-01-27 10:00', summary: '修改成本控制' },
{ operator: '王五', time: '2025-01-26 16:45', summary: '修改应收款' },
];
}
// ---------- DOM ----------
var roleSelect = document.getElementById('roleSelect');
var btnNewProject = document.getElementById('btnNewProject');
var viewList = document.getElementById('view-list');
var viewDetail = document.getElementById('view-detail');
var searchType = document.getElementById('searchType');
var searchInput = document.getElementById('searchInput');
var btnSearch = document.getElementById('btnSearch');
var filterProgress = document.getElementById('filterProgress');
var filterCost = document.getElementById('filterCost');
var listLoading = document.getElementById('listLoading');
var listEmpty = document.getElementById('listEmpty');
var projectTable = document.getElementById('projectTable');
var projectTableBody = document.getElementById('projectTableBody');
var pagination = document.getElementById('pagination');
var btnBack = document.getElementById('btnBack');
var detailTitle = document.getElementById('detailTitle');
var detailLoading = document.getElementById('detailLoading');
var detailContent = document.getElementById('detailContent');
var btnViewLog = document.getElementById('btnViewLog');
var btnSave = document.getElementById('btnSave');
var logOverlay = document.getElementById('logOverlay');
var logDrawer = document.getElementById('logDrawer');
var logDrawerClose = document.getElementById('logDrawerClose');
var logLoading = document.getElementById('logLoading');
var logEmpty = document.getElementById('logEmpty');
var logList = document.getElementById('logList');
var toast = document.getElementById('toast');
var navList = document.getElementById('navList');
var viewLogin = document.getElementById('view-login');
var appMain = document.getElementById('appMain');
var loginForm = document.getElementById('loginForm');
var loginError = document.getElementById('loginError');
var btnLoginSubmit = document.getElementById('btnLoginSubmit');
var btnLogout = document.querySelector('.btn-logout');
// ---------- 页面1:登录 / 退出 ----------
function showLogin() {
isLoggedIn = false;
if (viewLogin) viewLogin.classList.remove('hidden');
if (appMain) appMain.style.display = 'none';
}
function showApp() {
isLoggedIn = true;
if (viewLogin) viewLogin.classList.add('hidden');
if (appMain) appMain.style.display = 'flex';
}
if (loginForm) {
loginForm.addEventListener('submit', function (e) {
e.preventDefault();
var account = document.getElementById('loginAccount');
var password = document.getElementById('loginPassword');
if (!account || !password) return;
if (loginError) loginError.style.display = 'none';
if (btnLoginSubmit) btnLoginSubmit.disabled = true;
// 静态演示:任意非空账号密码视为成功;可改为模拟失败(如 password === 'fail'
setTimeout(function () {
if (btnLoginSubmit) btnLoginSubmit.disabled = false;
if (password.value === 'fail') {
if (loginError) {
loginError.textContent = '账号或密码错误,请重试';
loginError.style.display = 'block';
}
return;
}
showApp();
renderList();
}, 400);
});
}
if (btnLogout) {
btnLogout.addEventListener('click', function () {
showLogin();
});
}
// ---------- 权限:是否市场部 ----------
function isMarketRole() {
return currentRole === 'market';
}
function updateRoleUI() {
if (btnNewProject) btnNewProject.style.display = isMarketRole() ? '' : 'none';
}
if (roleSelect) {
roleSelect.addEventListener('change', function () {
currentRole = roleSelect.value;
updateRoleUI();
});
}
// ---------- 视图切换 ----------
function showList() {
currentView = 'list';
if (viewList) viewList.classList.add('active');
if (viewDetail) viewDetail.classList.remove('active');
document.querySelectorAll('.nav-item').forEach(function (n) { n.classList.remove('active'); });
if (navList) navList.classList.add('active');
}
function showDetail(projectId) {
currentView = 'detail';
currentProjectId = projectId;
if (viewList) viewList.classList.remove('active');
if (viewDetail) viewDetail.classList.add('active');
document.querySelectorAll('.nav-item').forEach(function (n) { n.classList.remove('active'); });
if (detailTitle) detailTitle.textContent = projectId ? '项目详情' : '新建项目';
if (detailLoading) detailLoading.style.display = 'block';
if (detailContent) detailContent.style.display = 'none';
if (projectId) {
// 模拟加载详情
setTimeout(function () {
if (detailLoading) detailLoading.style.display = 'none';
if (detailContent) detailContent.style.display = 'block';
fillDetailForm(projectId);
}, 400);
} else {
if (detailLoading) detailLoading.style.display = 'none';
if (detailContent) detailContent.style.display = 'block';
clearDetailForm();
}
}
function fillDetailForm(projectId) {
var p = projects.find(function (x) { return x.id === projectId; });
if (!p) return;
var nameInput = detailContent.querySelector('input[name="projectName"]');
if (nameInput) nameInput.value = p.name || '';
var codeInput = detailContent.querySelector('input[name="contractCode"]');
if (codeInput) codeInput.value = p.contractCode || '';
var ownerInput = detailContent.querySelector('input[name="ownerUnit"]');
if (ownerInput) ownerInput.value = p.ownerUnit || '';
}
function clearDetailForm() {
var inputs = detailContent ? detailContent.querySelectorAll('input, select, textarea') : [];
inputs.forEach(function (el) {
if (el.type === 'checkbox' || el.type === 'radio') el.checked = false;
else el.value = '';
});
}
// ---------- Tab 切换 ----------
function bindTabs() {
var tabs = document.querySelectorAll('.tab');
var panels = document.querySelectorAll('.tab-panel');
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
var t = tab.getAttribute('data-tab');
tabs.forEach(function (x) { x.classList.remove('active'); });
panels.forEach(function (p) {
var pid = p.id;
if (pid === 'panel-' + t) p.classList.add('active');
else p.classList.remove('active');
});
tab.classList.add('active');
});
});
}
// ---------- 列表:渲染 ----------
function filterList() {
var type = searchType && searchType.value ? searchType.value : 'name';
var keyword = (searchInput && searchInput.value || '').trim().toLowerCase();
var progressVal = filterProgress && filterProgress.value ? filterProgress.value : '';
var costVal = filterCost && filterCost.value ? filterCost.value : '';
listFiltered = projects.filter(function (p) {
if (keyword) {
var name = (p.name || '').toLowerCase();
var code = (p.contractCode || '').toLowerCase();
if (type === 'name' && name.indexOf(keyword) === -1) return false;
if (type === 'code' && code.indexOf(keyword) === -1) return false;
}
if (progressVal) {
if ((p.progressKey || '').toLowerCase() !== progressVal.toLowerCase()) return false;
}
if (costVal) {
if ((p.costKey || '').toLowerCase() !== costVal.toLowerCase()) return false;
}
return true;
});
}
function mapProgressToKey(p) {
var map = { '筹备中': 'planning', '进行中': 'ongoing', '已竣工': 'completed', '已结算': 'settled' };
p.progressKey = map[p.progress] || p.progress;
return p;
}
function mapCostToKey(p) {
var map = { '正常': 'normal', '超支': 'over', '节余': 'under' };
p.costKey = map[p.costStatus] || p.costStatus;
return p;
}
function renderList() {
if (listLoading) listLoading.style.display = 'block';
if (listEmpty) listEmpty.style.display = 'none';
if (projectTable) projectTable.style.visibility = 'hidden';
setTimeout(function () {
filterList();
if (listLoading) listLoading.style.display = 'none';
if (listFiltered.length === 0) {
if (listEmpty) listEmpty.style.display = 'flex';
if (projectTable) projectTable.style.visibility = 'hidden';
} else {
if (listEmpty) listEmpty.style.display = 'none';
if (projectTable) projectTable.style.visibility = 'visible';
var html = listFiltered.map(function (p) {
return (
'<tr>' +
'<td>' + (p.name || '—') + '</td>' +
'<td>' + (p.contractCode || '—') + '</td>' +
'<td>' + (p.progress || '—') + '</td>' +
'<td>' + (p.costStatus || '—') + '</td>' +
'<td>' + (p.ownerUnit || '—') + '</td>' +
'<td class="cell-actions">' +
'<button type="button" class="link-action" data-id="' + p.id + '">查看</button> ' +
'<button type="button" class="link-action" data-id="' + p.id + '">编辑</button>' +
'</td>' +
'</tr>'
);
}).join('');
if (projectTableBody) projectTableBody.innerHTML = html;
projectTableBody.querySelectorAll('.link-action').forEach(function (btn) {
btn.addEventListener('click', function () {
var id = btn.getAttribute('data-id');
showDetail(id);
});
});
}
var totalEl = pagination && pagination.querySelector('.pagination-info');
if (totalEl) totalEl.textContent = '共 ' + listFiltered.length + ' 条';
}, 300);
}
// ---------- 搜索与筛选 ----------
if (btnSearch) btnSearch.addEventListener('click', renderList);
if (searchInput) searchInput.addEventListener('keydown', function (e) { if (e.key === 'Enter') renderList(); });
if (filterProgress) filterProgress.addEventListener('change', renderList);
if (filterCost) filterCost.addEventListener('change', renderList);
// ---------- 新建项目 ----------
if (btnNewProject) {
btnNewProject.addEventListener('click', function () {
showDetail(null);
});
}
// ---------- 返回列表 ----------
if (btnBack) {
btnBack.addEventListener('click', function () {
showList();
});
}
if (navList) {
navList.addEventListener('click', function (e) {
e.preventDefault();
showList();
});
}
// ---------- 保存 ----------
if (btnSave) {
btnSave.addEventListener('click', function () {
var textSpan = btnSave.querySelector('.btn-text');
var loadingSpan = btnSave.querySelector('.btn-loading');
if (loadingSpan && loadingSpan.style.display === 'inline') return;
if (textSpan) textSpan.style.display = 'none';
if (loadingSpan) loadingSpan.style.display = 'inline';
btnSave.disabled = true;
setTimeout(function () {
if (textSpan) textSpan.style.display = 'inline';
if (loadingSpan) loadingSpan.style.display = 'none';
btnSave.disabled = false;
showToast('保存成功', 'success');
}, 800);
});
}
// ---------- 操作日志抽屉 ----------
function openLogDrawer() {
if (logOverlay) logOverlay.classList.add('visible');
if (logDrawer) logDrawer.classList.add('visible');
if (logOverlay) logOverlay.setAttribute('aria-hidden', 'false');
if (logLoading) logLoading.style.display = 'block';
if (logEmpty) logEmpty.style.display = 'none';
if (logList) logList.innerHTML = '';
setTimeout(function () {
if (logLoading) logLoading.style.display = 'none';
var logs = getMockLogs(currentProjectId);
if (logs.length === 0) {
if (logEmpty) logEmpty.style.display = 'flex';
} else {
logList.innerHTML = logs.map(function (l) {
return (
'<li class="log-item">' +
'<div class="log-meta">' + l.operator + ' · ' + l.time + '</div>' +
'<div class="log-desc">' + l.summary + '</div>' +
'</li>'
);
}).join('');
}
}, 400);
}
function closeLogDrawer() {
if (logOverlay) logOverlay.classList.remove('visible');
if (logDrawer) logDrawer.classList.remove('visible');
if (logOverlay) logOverlay.setAttribute('aria-hidden', 'true');
}
if (btnViewLog) btnViewLog.addEventListener('click', openLogDrawer);
if (logDrawerClose) logDrawerClose.addEventListener('click', closeLogDrawer);
if (logOverlay) logOverlay.addEventListener('click', closeLogDrawer);
// ---------- Toast ----------
function showToast(message, type) {
if (!toast) return;
toast.textContent = message;
toast.className = 'toast visible' + (type ? ' ' + type : '');
clearTimeout(toast._tid);
toast._tid = setTimeout(function () {
toast.classList.remove('visible');
}, 2500);
}
// ---------- 初始化 ----------
projects = getMockProjects().map(function (p) {
mapProgressToKey(p);
mapCostToKey(p);
return p;
});
bindTabs();
updateRoleUI();
// 未登录时只显示登录页;已登录则显示主应用(可通过 hash 或 localStorage 模拟,此处默认显示登录页)
if (viewLogin && appMain) {
showLogin();
} else {
renderList();
}
})();