<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>License 分发管理</title> <link rel="stylesheet" href="./license_info.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script> <style> </style> </head> <body> <div class="sidebar" id="sidebar"> <button onclick="showTable()">License 管理</button> <button onclick="showUserManagement()">用户管理</button> <button onclick="showRoleManagement()">角色管理</button> </div> <div class="content" id="content"> <button class="toggle-sidebar" onclick="toggleSidebar()">←</button> <header> <h1>XUGU License 管理平台</h1> <div> <!-- <button class="upload-button" onclick="window.location.href='/static/upload_xlsx/index.html'" style="display: none;">Upload File</button> --> <!-- 默认隐藏 --> <button class="user-button" onclick="toggleUserInfo()" id="username">User</button> </div> </header> <div id="table-container"> <table id="applications-table"> <thead> <tr> <th>创建人</th> <th>申请日期 <button class="sort-button" onclick="sortTableByDate()">排序</button></th> <th>关联项目</th> <th>销售人员</th> <th>技服人员</th> <th>总节点数</th> <th>使用单位</th> <th>产品名称</th> <th>版本</th> <th>节点数</th> <th>License状态</th> </tr> </thead> <tbody> </tbody> </table> <div class="pagination"> <button id="prev-page">上一页</button> <button id="next-page">下一页</button> <select id="page-selector" class="flat-select"></select> <span id="pagination-info">第 1 页,共 0 页</span> <!-- 新增信息显示区域 --> <div id="capture-license-button-container"> <!-- 按钮将在这里插入 --> </div> <!-- <button class="CaptureLicenseOnce-button" onclick="CaptureLicenseOncefunc()">获取最新license</button> 动态插入按钮的容器 --> </div> </div> <!-- License 详细信息的模态框 --> <div id="detailsModal" class="modal"> <div class="modal-content"> <span class="close" onclick="closeModal('detailsModal')">×</span> <h3>License 详细信息</h3> <div id="detailsContent"></div> <button class="close-button" onclick="closeModal('detailsModal')">关闭</button> </div> </div> <!-- 用户管理的添加用户 --> <div id="user-management" style="display: none;"> <div style="display: flex; align-items: center; justify-content: space-between;"> <h2>用户管理</h2> <button id="addUserButton" class="create-role-button" style="display: none;">添加用户</button> <!-- 默认隐藏 --> </div> <table id="users-table"> <thead> <tr> <th>用户名</th> <th>电话</th> <th>邮箱</th> <th>权限</th> <th>账号</th> </tr> </thead> <tbody> </tbody> </table> </div> <!-- 新增的角色管理容器 --> <div id="role-management" style="display: none;"> <div style="display: flex; align-items: center; justify-content: space-between;"> <h2>角色管理</h2> <button id="createRoleButton" class="create-role-button">创建角色</button> </div> <div id="roles-container"></div> </div> </div> <!-- License 管理的弹出菜单 --> <div id="licenseActionModal" class="modal"> <div class="modal-content action-modal-content" id="licenseActionModalContent"> <span class="close" onclick="closeModal('licenseActionModal')">×</span> <!-- <button onclick="showExtraInfo()">查看额外信息</button> <button onclick="modifyLicenseInfo()">修改信息</button> 新增的修改信息按钮 --> <!-- <button onclick="showDistributionHistory()">分发历史</button> <button onclick="confirmDelete()">删除</button> --> </div> </div> <!-- 修改信息的表单框 --> <div id="modifyLicenseModal" class="modal"> <div class="modify-license-modal-content"> <span class="close" onclick="closeModal('modifyLicenseModal')">×</span> <h3>修改License信息</h3> <form id="modifyLicenseForm"> <label for="creator">创建人:</label> <input type="text" id="creator" name="creator" required><br><br> <label for="applicationDate">申请日期:</label> <input type="date" id="applicationDate" name="applicationDate" class="form-control" required><br><br> <label for="associatedProject">关联项目:</label> <input type="text" id="associatedProject" name="associatedProject" required><br><br> <label for="salesPerson">销售人员:</label> <input type="text" id="salesPerson" name="salesPerson" required><br><br> <label for="salesEmail">销售邮箱:</label> <input type="email" id="salesEmail" name="salesEmail" required><br><br> <label for="supportPerson">技服人员:</label> <input type="text" id="supportPerson" name="supportPerson" required><br><br> <label for="supportEmail">技服邮箱:</label> <input type="email" id="supportEmail" name="supportEmail" required><br><br> <label for="totalNodes">总节点数:</label> <input type="number" id="totalNodes" name="totalNodes" class="form-control" required><br><br> <label for="company">使用单位:</label> <input type="text" id="company" name="company" required><br><br> <label for="productName">产品名称:</label> <input type="text" id="productName" name="productName" required><br><br> <label for="version"> 数据库版本: </label> <input type="text" id="version" name="version" required><br><br> <label for="nodeCount">节点数:</label> <input type="number" id="nodeCount" name="nodeCount" class="form-control" required><br><br> <button type="button" onclick="saveLicenseChanges()">保存</button> </form> </div> </div> <!-- 用户管理的弹出菜单 --> <div id="userActionModal" class="modal"> <div class="modal-content action-modal-content" id="userActionModalContent"> <span class="close" onclick="closeModal('userActionModal')">×</span> <button onclick="showMoreUserInfo()">更多用户信息</button> <button onclick="showUserLicenseHistory()">查看license分发记录</button> <button onclick="modifyUser()">修改用户</button> </div> </div> <!-- 用户管理的添加用户 --> <div id="addUserModal" class="modal"> <div class="centered-modal-content" style="height: 50vh; overflow-y: auto;"> <span class="close" onclick="closeModal('addUserModal')">×</span> <h3>添加用户</h3> <form id="addUserForm"> <div class="form-group"> <label for="addUsername">用户名:</label> <input type="text" id="addUsername" name="username" class="flat-rounded-input" required> </div> <div class="form-group"> <label for="addPassword">密码:</label> <input type="password" id="addPassword" name="password" class="flat-rounded-input" required> </div> <div class="form-group"> <label for="addAccount">账号:</label> <input type="text" id="addAccount" name="account" class="flat-rounded-input" required> </div> <div class="form-group"> <label for="addTelephone">电话:</label> <input type="text" id="addTelephone" name="telephone" class="flat-rounded-input" required> </div> <div class="form-group"> <label for="addEmail">邮箱:</label> <input type="email" id="addEmail" name="email" class="flat-rounded-input" required> </div> <button type="button" onclick="saveNewUser()" class="flat-rounded-button">保存</button> </form> </div> </div> <!-- 邮箱和用户选择弹出框 --> <div id="emailModal" class="modal"> <div class="modal-content centered-modal-content" style="height: 45vh; overflow-y: auto;"> <span class="close" onclick="closeModal('emailModal')">×</span> <!-- 邮箱输入部分 --> <label for="emailInput1" class="email-modal-label">选中要发送的邮箱:</label> <div id="emailInputs"> <input type="text" id="emailInput1" class="email-modal-input"> </div> <br> <button onclick="addEmailInput()" class="add-email-button">添加邮箱</button> <!-- 用户选择部分 --> <label for="userSelect1" class="email-modal-label">选择要分发的用户:</label> <div id="userInputs"></div> <button onclick="addUserInput()" class="add-email-button">添加用户</button> <!-- 发送按钮 --> <button onclick="sendEmail()" class="ios-button">发送</button> </div> </div> <!-- 其他模态框不变 --> <div id="extraInfoModal" class="modal"> <div class="modal-content"> <span class="close" onclick="closeModal('extraInfoModal')">×</span> <div id="extraInfoContent" class="extra-info"></div> </div> </div> <div id="userModal" class="user-info"> <span class="close apple-close" onclick="closeUserInfo()">×</span> <!-- 关闭按钮 --> <div id="userInfoContent"></div> <br> <button class="apple-logout-button" onclick="logout()">退出</button> </div> <!-- license删除模态框--> <div id="confirmDeleteModal" class="modal"> <div class="centered-modal-content"> <span class="close" onclick="closeModal('confirmDeleteModal')">×</span> </div> </div> <div id="confirmGenerateModal" class="modal"> <div class="centered-modal-content" style="height: 15vh; overflow-y: auto;"> <span class="close" onclick="closeModal('confirmGenerateModal')">×</span> <p>确认生成License吗?</p> <button id="confirm-generate-button">确认</button> <button onclick="closeModal('confirmGenerateModal')">取消</button> </div> </div> <div id="distributionHistoryModal" class="modal"> <div class="centered-modal-content"> <span class="close" onclick="closeModal('distributionHistoryModal')">×</span> <h3>分发历史</h3> <!-- 分发给用户模块 --> <div id="userDistribution" class="extra-info"> <h4>分发给用户</h4> <div id="userDistributionContent" class="distribution-container">暂无分发记录。</div> </div> <!-- 分发为邮箱模块 --> <div id="emailDistribution" class="extra-info" style="margin-top: 20px;"> <h4>分发为邮箱</h4> <div id="emailDistributionContent" class="distribution-container">暂无分发记录。</div> </div> </div> </div> <!-- 加载进度条模态框,放在页面的最后 --> <div id="loadingModal" class="modal" style="display: none;"> <div class="modal-content apple-modal-content"> <h3>正在生成 License...</h3> <div class="progress-bar" style="width: 100%; height: 20px; background-color: #e0e0e0;"> <div class="progress" style="width: 50%; height: 100%; background-color: #007aff;" id="progress"></div> </div> </div> </div> <script> //翻页有关,还需优化 let currentPage = 1; let pageSize = 10; let LisOffset = 1; let totalPages = 0; // 存储总页数 let selectedPage =1; let nextPage =1; let prevPage = 10; //用户token const token = localStorage.getItem('Authorization'); //选中行的数据 let selectedRowData = null;//选中行的数据 let isAscending = true; let userMap = {}; // 用于存储用户名和用户ID的映射 let currentUserRole = ''; // 新增变量存储当前用户的权限 let currentUserName = ''; // 新增变量存储当前用户的名字 let userPermissions = [];// 全局变量,用于存储用户权限 let LicApplicationData = []; // 全局变量存储数据 let currentRolePermissions = []; // 这是您获取的当前角色的权限列表 function checkPermission(permission) { console.log(`检查权限: ${permission} - ${hasPermission ? '有权限' : '无权限'}`); return userPermissions.includes(permission); } async function initialize() { await fetchUsername(); // 确保 fetchUsername 完成 fetchApplications(1, 10); // 然后再调用 fetchApplications } //获取license展示信息 function fetchApplications(page, size) { fetch(`http://127.0.0.1:8080/api/admin/GetAllLicenseInfo?page=${page}&pageSize=${size}`, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { //selectedRowData = data.data; LicApplicationData = data.data; // 将接收到的数据存储到全局变量 // console.log("lic数据",data); // 输出获取的数据结构 // console.log("z该死的权限数组",userPermissions); const hasGeneratePermission = userPermissions.includes("generate_license"); const hasDistributePermission = userPermissions.includes("dispat_license"); // 更新总页数 //totalPages = Math.ceil(data.total / 10); // 在控制台打印权限结果 console.log(`hasGeneratePermission: ${hasGeneratePermission}, hasDistributePermission: ${hasDistributePermission}`); totalPages = Math.ceil(data.total / 10); const tableBody = document.querySelector('#applications-table tbody'); const tableHead = document.querySelector('#applications-table thead tr'); tableBody.innerHTML = ''; tableHead.innerHTML = ` <th></th> <!-- 添加一个空的表头用于放置下拉按钮 --> <th>创建人</th> <th>申请日期 </th> <!-- <th>申请日期 <button class="sort-button" onclick="sortTableByDate()">排序</button></th>--> <th>关联项目</th> <th>销售人员</th> <th>技服人员</th> <th>总节点数/集群</th> <th>使用单位</th> <th>操作</th> <!-- 新增的表头用于显示操作按钮 --> `; data.data.forEach(applicationArray => { const firstApplication = applicationArray[0]; let showGenerateButton = false; // 获取子行的数量 const childRowCount = applicationArray.length; // Check if any child row has LicenseFlage as "未生成" applicationArray.forEach(detail => { if (detail.LicenseFlage === "未生成" || detail.LicenseFlage === "已失效") { showGenerateButton = true; } }); // 创建主行 const row = document.createElement('tr'); const dropdownButton = document.createElement('button'); // 使用CSS创建一个箭头图标 dropdownButton.innerHTML = ''; dropdownButton.classList.add('arrow-icon'); dropdownButton.style.cursor = 'pointer'; row.innerHTML = ` <td></td> <!-- 空的单元格用于放置下拉按钮 --> <td>${createEllipsisText(firstApplication.Creator)}</td> <td>${createEllipsisText(firstApplication.ApplicationDate)} ${firstApplication.ApplicationTime}</td> <td>${createEllipsisText(firstApplication.GlxmName)}</td> <td>${createEllipsisText(firstApplication.SalesPerson)}</td> <td>${createEllipsisText(firstApplication.SupportPerson)}</td> <td>[共${firstApplication.TotalNodes}节点] - [${childRowCount}套]</td> <td>${createEllipsisText(firstApplication.Company)}</td> `; row.querySelector('td').appendChild(dropdownButton); // 添加 License 状态按钮 (父级行) if (hasGeneratePermission || hasDistributePermission) { const licenseStatusCell = document.createElement('td'); if (hasGeneratePermission && showGenerateButton) { licenseStatusCell.innerHTML += `<button class="license-status-btn generate" onclick="confirmGenerateLicense('${firstApplication.oa_request_id}', true)">生成</button>`; } else if (hasDistributePermission && firstApplication.LicenseFlage === "已生成") { // licenseStatusCell.innerHTML += `<button class="license-status-btn distribute" onclick="showEmailModal('${firstApplication.SupportEmail}','${firstApplication.SalesEmail}','','${firstApplication.oa_request_id}')">分发</button>`; licenseStatusCell.innerHTML += `<button class="license-status-btn distribute" onclick="distributeLicense('${firstApplication.oa_request_id}','${firstApplication.SupportEmail}', '${firstApplication.SalesEmail}','','${firstApplication.oa_request_id}')">分发</button>`; } // 添加一个分隔符 licenseStatusCell.innerHTML += `<span style="margin: 0 10px; display: inline-block; width: 1px; height: 20px; background-color: #ccc;"></span>`; // 在这里添加“查看详情”按钮 licenseStatusCell.innerHTML += `<button class="license-status-btn view-details" onclick="showDetailsModal('${firstApplication.UniqueID}', false)">查看详情</button>`; row.appendChild(licenseStatusCell); } tableBody.appendChild(row); // 多行内容及表头 (子行) const detailRow = document.createElement('tr'); const detailCell = document.createElement('td'); detailCell.colSpan = 11; // 占满所有列 detailCell.style.display = 'none'; const detailTable = document.createElement('table'); // 添加表头 const detailTableHeader = document.createElement('tr'); detailTableHeader.innerHTML = ` <th>产品信息(名称和版本)</th> <th>节点数</th> <th>处理器</th> <th>操作系统</th> <th>主MAC地址</th> <th>副MAC地址</th> <th> 查看</th> `; detailTable.appendChild(detailTableHeader); // 添加详细信息行 (子行) applicationArray.forEach(detail => { const detailInnerRow = document.createElement('tr'); detailInnerRow.innerHTML = ` <td> <strong>名称:</strong> ${createEllipsisText(detail.ProductName)}<br> <strong>版本:</strong> ${createEllipsisText(detail.ProductVersion)} </td> <td>${detail.NodeCount}</td> <td>${createEllipsisText(detail.oa_cpu)}</td> <td>${createEllipsisText(detail.oa_operating_system)}</td> <td>${createEllipsisText(detail.oa_main_mac)}</td> <td>${createEllipsisText(detail.oa_second_mac)}</td> `; //保留这里的代码,涉及到子行的单独申请 // 添加 License 状态按钮 (子行) // if (hasGeneratePermission || hasDistributePermission) { // const licenseStatusDetailCell = document.createElement('td'); // if (hasGeneratePermission && detail.LicenseFlage === "未生成") { // // 子行点击生成按钮时,传递 UniqueID 和 false 表示这是子行 // licenseStatusDetailCell.innerHTML = `<button class="license-status-btn generate" onclick="confirmGenerateLicense('${detail.UniqueID}', false)">生成</button>`; // } else if (hasDistributePermission && detail.LicenseFlage === "已生成") { // // 子行点击分发按钮时,传递 UniqueID 用于分发操作 // licenseStatusDetailCell.innerHTML = `<button class="license-status-btn distribute" onclick="showEmailModal('${detail.SupportEmail}', '${detail.SalesEmail}', '${detail.UniqueID}','')">分发</button>`; // } // detailInnerRow.appendChild(licenseStatusDetailCell); // } detailTable.appendChild(detailInnerRow); // 添加“查看详情”按钮 (子行) // const viewDetailsCell = document.createElement('td'); // viewDetailsCell.innerHTML = `<button class="license-status-btn view-details" onclick="showDetailsModal('${detail.UniqueID}', true)">查看详情</button>`; // detailInnerRow.appendChild(viewDetailsCell); // detailTable.appendChild(detailInnerRow); // 仅当主行状态为“分发”时添加“下载lic”按钮 // 创建一个新的单元格用于放置按钮 const actionCell = document.createElement('td'); // 创建按钮容器 const buttonContainer = document.createElement('div'); buttonContainer.classList.add('button-container'); // 创建“查看详情”按钮 (子行) // const viewDetailsButton = document.createElement('button'); // viewDetailsButton.classList.add('license-status-btn', 'view-details'); // viewDetailsButton.textContent = '查看详情'; // viewDetailsButton.onclick = () => showDetailsModal(detail.UniqueID, true); // // 将“查看详情”按钮添加到按钮容器 // buttonContainer.appendChild(viewDetailsButton); // 仅当主行状态为“已生成”时添加“下载lic”按钮 if (firstApplication.LicenseFlage === "已生成") { const downloadLicButton = document.createElement('button'); downloadLicButton.classList.add('license-status-btn', 'download-lic'); downloadLicButton.textContent = '下载lic'; // 绑定当前行的 lic1 和 lic2 数据 downloadLicButton.onclick = () => downloadLicenseFiles(detail.lic1, detail.lic2); // 将“下载lic”按钮添加到按钮容器 buttonContainer.appendChild(downloadLicButton); }else if (detail.LicenseFlage === "未生成") { // 如果 LicenseFlage 是 "未生成",则显示"未生成"文本 const statusSpan = document.createElement('span'); statusSpan.textContent = '未生成'; statusSpan.style.color = 'red'; // 将"未生成"状态添加到按钮容器 buttonContainer.appendChild(statusSpan); }else if (detail.LicenseFlage === "已失效") { // 如果 LicenseFlage 是 "已失效",则显示"已失效"文本 const statusSpan = document.createElement('span'); statusSpan.textContent = '已失效'; statusSpan.style.color = 'red'; // 将"未生成"状态添加到按钮容器 buttonContainer.appendChild(statusSpan); } // 将按钮容器添加到actionCell actionCell.appendChild(buttonContainer); // 将actionCell添加到当前子行 detailInnerRow.appendChild(actionCell); // 将子行添加到详细信息表格 detailTable.appendChild(detailInnerRow); // 为每个详细信息行添加点击事件 (子行) detailInnerRow.addEventListener('click', (event) => { if (!event.target.closest('button')) { openActionModal(event, detail, 'licenseActionModal'); } }); detailInnerRow.addEventListener('contextmenu', (event) => { event.preventDefault(); if (!event.target.closest('button')) { openActionModal(event, detail, 'licenseActionModal'); } }); }); detailCell.appendChild(detailTable); detailRow.appendChild(detailCell); tableBody.appendChild(detailRow); // 主行的点击事件,用于切换下拉菜单的显示隐藏 // row.addEventListener('click', (event) => { // if (!event.target.closest('button')) { // 如果点击的不是按钮 // detailCell.style.display = detailCell.style.display === 'none' ? 'table-cell' : 'none'; // } // }); // // 点击下拉按钮切换显示隐藏 // dropdownButton.addEventListener('click', (event) => { // event.stopPropagation(); // 阻止事件冒泡到行点击事件 // detailCell.style.display = detailCell.style.display === 'none' ? 'table-cell' : 'none'; // }); row.addEventListener('click', (event) => { if (!event.target.closest('button')) { // 如果点击的不是按钮 // const isExpanded = detailCell.style.display === 'table-cell'; // detailCell.style.display = isExpanded ? 'none' : 'table-cell'; // row.classList.toggle('expanded-row', !isExpanded); // dropdownButton.classList.toggle('rotate-arrow', !isExpanded); // 旋转箭头图标 if (!event.target.closest('button')) { const isExpanded = detailCell.style.display === 'table-cell'; // 收回其他行 closeAllExpandedRows(); // 展开/收起当前行 detailCell.style.display = isExpanded ? 'none' : 'table-cell'; row.classList.toggle('expanded-row', !isExpanded); dropdownButton.classList.toggle('rotate-arrow', !isExpanded); } } }); dropdownButton.addEventListener('click', (event) => { // event.stopPropagation(); // 阻止事件冒泡到行点击事件 // const isExpanded = detailCell.style.display === 'table-cell'; // detailCell.style.display = isExpanded ? 'none' : 'table-cell'; // row.classList.toggle('expanded-row', !isExpanded); // dropdownButton.classList.toggle('rotate-arrow', !isExpanded); // 旋转箭头图标 event.stopPropagation(); // 阻止事件冒泡到行点击事件 const isExpanded = detailCell.style.display === 'table-cell'; // 收回其他行 closeAllExpandedRows(); // 展开/收起当前行 detailCell.style.display = isExpanded ? 'none' : 'table-cell'; row.classList.toggle('expanded-row', !isExpanded); dropdownButton.classList.toggle('rotate-arrow', !isExpanded); }); }); // 分页和其他控制逻辑 // 更新分页信息 // totalPages = Math.ceil(data.total / pageSize); document.getElementById('pagination-info').textContent = `第 ${currentPage} 页,共 ${totalPages} 页`; document.getElementById('prev-page').disabled = currentPage <= 1; document.getElementById('next-page').disabled = currentPage >= totalPages; const pageSelector = document.getElementById('page-selector'); pageSelector.innerHTML = ''; for (let i = 1; i <= totalPages; i++) { const option = document.createElement('option'); option.value = i; option.text = i; if (i === selectedPage) { option.selected = true; document.getElementById('pagination-info').textContent = `第 ${selectedPage} 页,共 ${totalPages} 页`; // LisOffset = selectedPage // pageSize = LisOffset + 10; // document.getElementById('prev-page').disabled = currentPage <= 1; // document.getElementById('next-page').disabled = currentPage >= totalPages; } pageSelector.appendChild(option); } }); } function checkCaptureLicensePermission() { // 获取插入按钮的容器元素 const container = document.getElementById('capture-license-button-container'); if (container) { // 确保容器元素存在 if (userPermissions.includes('capture_license_once_to_db')) { // 如果有权限,插入按钮 const CaptureLicensebuttonHtml = `<button class="CaptureLicenseOnce-button" onclick="CaptureLicenseOncefunc()">获取最新license</button>`; container.innerHTML = CaptureLicensebuttonHtml; } else { // 如果没有权限,确保不显示按钮 container.innerHTML = ''; // 清空容器 } } else { console.error('找不到 capture-license-button-container 元素'); } } let currentOffset = 1; const itemsPerPage = 10; // 添加页数选择框的事件监听器 document.getElementById('page-selector').addEventListener('change', (event) => { selectedPage = parseInt(event.target.value, 10); const startRecord = (selectedPage - 1) * 10 + 1; const endRecord = startRecord + 10; LisOffset = selectedPage pageSize = LisOffset* 10; currentPage = selectedPage currentOffset = startRecord endOffset = endRecord fetchApplications(startRecord, endRecord); }); // 分页按钮事件监听器 document.getElementById('prev-page').addEventListener('click', () => { if (currentPage > 1) { currentPage--; selectedPage-- currentOffset -= itemsPerPage; const startOffset = currentOffset; const endOffset = currentOffset + itemsPerPage - 1; fetchApplications(startOffset, endOffset); } }); document.getElementById('next-page').addEventListener('click', () => { if (currentPage < totalPages) { currentPage++ selectedPage++ LisOffset += pageSize-LisOffset; pageSize += 10; // 增加页数时,增加 pageSize,规则可自定义 currentOffset += itemsPerPage; const startOffset = currentOffset; const endOffset = currentOffset + itemsPerPage - 1; fetchApplications(startOffset, endOffset); } }); // 页面加载时默认调用第一页的数据 //fetchApplications(1); // 页面初始化时调用 fetchUsername 函数 //fetchApplications(LisOffset,pageSize); //排序 // function sortTableByDate() { // applicationData.sort((a, b) => { // const dateTimeA = `${a[0].ApplicationDate} ${a[0].ApplicationTime}`; // const dateTimeB = `${b[0].ApplicationDate} ${b[0].ApplicationTime}`; // return isAscending ? dateTimeA.localeCompare(dateTimeB) : dateTimeB.localeCompare(dateTimeA); // }); // renderTable(applicationData); // 排序后重新渲染表格 // isAscending = !isAscending; // 切换排序顺序 // } // 关闭所有已经展开的行 function closeAllExpandedRows() { const allExpandedRows = document.querySelectorAll('.expanded-row'); allExpandedRows.forEach(expandedRow => { const detailCell = expandedRow.nextElementSibling.querySelector('td'); if (detailCell && detailCell.style.display === 'table-cell') { detailCell.style.display = 'none'; expandedRow.classList.remove('expanded-row'); const dropdownButton = expandedRow.querySelector('.arrow-icon'); if (dropdownButton) { dropdownButton.classList.remove('rotate-arrow'); } } }); } // 创建带省略号的文本,并在鼠标悬停时显示完整内容 function createEllipsisText(text) { const maxLength = 20; // 最大显示字符数 if (text == null || typeof text !== 'string') { return ''; // 如果 text 是 null、undefined 或不是字符串,返回空字符串 } if (text.length > maxLength) { const span = document.createElement('span'); span.textContent = text.substring(0, maxLength) + '...'; span.title = text; // 鼠标悬停时显示完整内容 return span.outerHTML; } return text; } //生成licensestr function confirmGenerateLicense(id, isParentRow) { const confirmGenerateModal = document.getElementById('confirmGenerateModal'); confirmGenerateModal.style.display = 'block'; document.getElementById('confirm-generate-button').onclick = function() { // 开始生成时显示加载进度条 const loadingModal = document.getElementById('loadingModal'); loadingModal.style.display = 'block'; generateLicense(id, isParentRow); }; } function generateLicense(id, isParentRow) { const payload = isParentRow ? { oa_request_id: id } : { uniqueID: id }; fetch('http://127.0.0.1:8080/api/admin/GenerateLicense', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }) .then(response => response.json()) .then(data => { // 显示加载进度条并设置动态提示信息 showLoadingModal('正在生成 License...'); if (data.success) { // 隐藏加载进度条 hideLoadingModal(); alert('License 生成成功!'); fetchApplications(currentOffset, currentOffset + itemsPerPage - 1); } else { // 请求失败时隐藏加载进度条 hideLoadingModal(); alert('License 生成失败:' + data.error); } closeModal('confirmGenerateModal'); }) .catch(error => { // 请求失败时隐藏加载进度条 hideLoadingModal(); alert('生成过程中出现错误,请稍后再试。'); }); } //主动抓取一次Licen数据 function CaptureLicenseOncefunc() { // 显示加载模态框 const loadingModal = document.createElement('div'); loadingModal.classList.add('modal-content', 'apple-modal-content'); loadingModal.innerHTML = ` <h3>正在获取 License 信息...</h3> <div class="progress-bar" style="width: 100%; height: 20px; background-color: #e0e0e0;"> <div class="progress" style="width: 50%; height: 100%; background-color: #007aff;"></div> </div> `; document.body.appendChild(loadingModal); // 定义超时函数 const timeoutPromise = new Promise((_, reject) => { setTimeout(() => { reject(new Error('获取超时')); }, 10000); // 10秒超时 }); // 发起 GET 请求的 Promise const fetchPromise = fetch('http://127.0.0.1:8080/api/admin/GetCaptureLicenseOnce', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }).then(response => response.json()); // 使用 Promise.race 来竞争两个 Promise,哪个先返回就使用哪个 Promise.race([fetchPromise, timeoutPromise]) .then(data => { // 先关闭进度条 document.body.removeChild(loadingModal); // 显示成功或失败提示 if (data.success) { alert('License 获取成功!'); } else { alert('获取失败:' + data.error); } }) .catch(error => { // 先关闭进度条 document.body.removeChild(loadingModal); // 显示错误提示 alert(error.message); // 如果超时或请求失败 }); } function downloadLicenseFiles(lic1, lic2) { // 下载license.dat文件 if (lic1) { const blob1 = new Blob([lic1], { type: 'text/plain' }); const link1 = document.createElement('a'); link1.href = URL.createObjectURL(blob1); link1.download = 'license.dat'; link1.click(); } // 如果lic2不为空,下载license2.dat文件 if (lic2) { const blob2 = new Blob([lic2], { type: 'text/plain' }); const link2 = document.createElement('a'); link2.href = URL.createObjectURL(blob2); link2.download = 'license2.dat'; link2.click(); } } //查看lic所有信息 // 查看lic所有信息 function showDetailsModal(uniqueID, isChildRow = false) { console.log("当前 uniqueID:", uniqueID); console.log("当前 isChildRow:", isChildRow); let selectedData = null; let sortedApplicationArray; // 查找主行和子行数据 console.log("查找主行和子行数据"); let selectedApplicationArray = null; for (let applicationArray of LicApplicationData) { if (applicationArray.some(data => data.UniqueID === uniqueID)) { selectedApplicationArray = applicationArray; break; } } if (!selectedApplicationArray) { console.error('未找到对应的记录,UniqueID:', uniqueID); alert('未找到对应的记录,请检查数据'); return; } let detailsHtml = `<table class="table" style="width:100%;">`; // 如果是子行,直接显示该子行的信息 if (isChildRow) { const childData = selectedApplicationArray.find(data => data.UniqueID === uniqueID); if (childData) { detailsHtml += ` <tr> <th style="width: 50px;">序号</th><th>产品名称</th><th>版本</th><th>节点数</th><th>处理器</th> <th>操作系统</th><th>主MAC地址</th><th>副MAC地址</th><th>License状态</th> <!-- 新增 License 状态列 --> </tr> <tr> <td style="width: 50px;">${childData.oa_id}</td><td>${childData.ProductName}</td><td>${childData.ProductVersion}</td><td>${childData.NodeCount}</td> <td>${childData.oa_cpu}</td><td>${childData.oa_operating_system}</td><td>${childData.oa_main_mac}</td><td>${childData.oa_second_mac}</td> <td>${childData.LicenseFlage}</td> <!-- 显示 License 状态 --> </tr> `; } else { detailsHtml += `<tr><td colspan="9">未找到对应的子行记录。</td></tr>`; } } else { // 如果是主行,显示主行信息(不使用表格) const firstData = selectedApplicationArray[0]; const childRowCount = selectedApplicationArray.length; // 按 oa_id 对子行数据进行排序(升序) sortedApplicationArray = selectedApplicationArray.slice(0).sort((a, b) => a.oa_id - b.oa_id); console.log("当前 sortedApplicationArray:", sortedApplicationArray); // 计算 TotalNodes 除以子行数的值 detailsHtml += ` <div style="margin-bottom: 20px; font-family: Arial, sans-serif; line-height: 1.6; padding: 10px; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);"> <p style="margin: 0; padding: 5px 0;"><strong>创建人:</strong> ${firstData.Creator}</p> <p style="margin: 0; padding: 5px 0;"><strong>申请日期:</strong> ${firstData.ApplicationDate}</p> <p style="margin: 0; padding: 5px 0;"><strong>关联项目:</strong> ${firstData.GlxmName}</p> <p style="margin: 0; padding: 5px 0;"><strong>销售人员:</strong> ${firstData.SalesPerson}</p> <p style="margin: 0; padding: 5px 0;"><strong>技服人员:</strong> ${firstData.SupportPerson}</p> <p style="margin: 0; padding: 5px 0;"><strong>总节点数:</strong> [${firstData.TotalNodes}] 节点 = <strong> 集群:</strong> [${childRowCount}] 套</p> <p style="margin: 0; padding: 5px 0;"><strong>使用单位:</strong> ${firstData.Company}</p> <button id="download-all-licenses">打包下载全部license.dat</button> </div> `; // 添加一个分隔符(例如水平线) detailsHtml += ` <hr style="border: none; border-top: 2px solid #ccc; margin: 20px 0;"> `; // 显示子行信息(使用表格方式) detailsHtml += ` <table class="table" style="width:100%;"> <tr> <th style="width: 50px;">序号</th><th>产品名称</th><th>版本</th><th>节点数</th><th>处理器</th> <th>操作系统</th><th>主MAC地址</th><th>副MAC地址</th><th>License状态</th> <!-- 新增 License 状态列 --> </tr> `; sortedApplicationArray.forEach((data, index) => { detailsHtml += ` <tr> <td style="width: 50px;">${index + 1}</td><td>${data.ProductName}</td><td>${data.ProductVersion}</td><td>${data.NodeCount}</td> <td>${data.oa_cpu}</td><td>${data.oa_operating_system}</td><td>${data.oa_main_mac}</td><td>${data.oa_second_mac}</td> <td>${data.LicenseFlage}</td> <!-- 显示 License 状态 --> </tr> `; }); detailsHtml += `</table>`; document.getElementById('detailsContent').innerHTML = detailsHtml; document.getElementById('detailsModal').style.display = 'block'; } detailsHtml += `</table>`; document.getElementById('detailsContent').innerHTML = detailsHtml; document.getElementById('detailsModal').style.display = 'block'; // 等内容插入 DOM 后,获取按钮并绑定 onclick 事件 //下载全部license.dat const downloadButton = document.getElementById('download-all-licenses'); if (downloadButton) { downloadButton.onclick = function() { downloadAllLicenses(sortedApplicationArray); }; } else { console.error("无法找到下载按钮"); } } // 用户管理菜单栏 function openUserActionModal(event, data, modalId) { selectedRowData = data; let modal = document.getElementById(modalId); const modalContent = modal.querySelector('.modal-content'); // 清空之前的内容 modalContent.innerHTML = ` <span class="close" onclick="closeModal('${modalId}')">×</span> `; // 动态生成更多用户信息按钮 if (userPermissions.includes('read_user')) { modalContent.innerHTML += `<button onclick="showMoreUserInfo(); closeModal('${modalId}');">更多用户信息</button>`; } // 检查是否有 `update_user` 权限,决定是否显示修改用户按钮 if (userPermissions.includes('update_user')) { modalContent.innerHTML += `<button onclick="modifyUser(); closeModal('${modalId}');">修改用户</button>`; } // 检查是否有 `delete_user` 权限,决定是否显示删除按钮 if (userPermissions.includes('delete_user')) { modalContent.innerHTML += `<button onclick="confirmDeleteUser('${data.UniqueID}'); closeModal('${modalId}');">删除用户</button>`; } // 显示菜单位置 modalContent.style.top = `${event.clientY}px`; modalContent.style.left = `${event.clientX}px`; modal.style.display = 'block'; } // 为用户管理界面的每一行添加点击和右键事件监听器 function fetchUsers() { fetch('http://127.0.0.1:8080/api/admin/userInfoAll', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { const tableBody = document.querySelector('#users-table tbody'); tableBody.innerHTML = ''; data.data.forEach(user => { // 如果 ACCOUNT 字段为 'admin',则跳过这一行 if (user.Account === 'admin') { return; } const row = document.createElement('tr'); row.innerHTML = ` <td>${user.Username}</td> <td>${user.Telephone}</td> <td>${user.Email}</td> <td>${user.Role}</td> <td>${user.Account}</td> `; row.addEventListener('click', (event) => { if (!event.target.classList.contains('ios-button')) { openUserActionModal(event, user, 'userActionModal'); } }); row.addEventListener('contextmenu', (event) => { event.preventDefault(); if (!event.target.classList.contains('ios-button')) { openUserActionModal(event, user, 'userActionModal'); } }); tableBody.appendChild(row); }); }); } //查看用户lic历史 function showUserLicenseHistory() { fetch(`http://127.0.0.1:8080/api/admin/GetlicenseRecordInfoByUser`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ Id: selectedRowData.Id, UserName: selectedRowData.Username, Page: 1, PageSize: 10 }) }) .then(response => response.json()) .then(data => { const extraInfoContent = document.getElementById('extraInfoContent'); extraInfoContent.innerHTML = `<h3>License 分发记录</h3>`; if (data.data && data.data.length > 0) { const table = document.createElement('table'); table.style.width = '100%'; table.style.borderCollapse = 'collapse'; table.style.marginTop = '10px'; const thead = document.createElement('thead'); const headerRow = document.createElement('tr'); const headers = ['分发日期', '关联项目', '产品名称', '版本', '节点数', 'Company']; headers.forEach(headerText => { const th = document.createElement('th'); th.textContent = headerText; th.style.border = '1px solid #ddd'; th.style.padding = '8px'; th.style.backgroundColor = '#f1f1f1'; headerRow.appendChild(th); }); thead.appendChild(headerRow); table.appendChild(thead); const tbody = document.createElement('tbody'); data.data.forEach(record => { const row = document.createElement('tr'); const cells = [ record.up_time.Time, record.AssociatedProject, record.ProductName, record.Version, record.NodeCount, record.Company ]; cells.forEach(cellText => { const td = document.createElement('td'); td.textContent = cellText; td.style.border = '1px solid #ddd'; td.style.padding = '8px'; row.appendChild(td); }); tbody.appendChild(row); }); table.appendChild(tbody); extraInfoContent.appendChild(table); } else { extraInfoContent.innerHTML += `<p>没有找到分发记录。</p>`; } document.getElementById('extraInfoModal').style.display = 'block'; }); } //用户菜单栏 function openActionModal(event, data, modalId) { selectedRowData = data; let modal = document.getElementById(modalId); const modalContent = modal.querySelector('.modal-content'); // 清空之前的内容 modalContent.innerHTML = ` <span class="close" onclick="closeModal('${modalId}')">×</span> `; // 动态生成查看分发记录 if (userPermissions.includes('read_license_record')) { modalContent.innerHTML += ` <button onclick="showDistributionHistory(); closeModal('${modalId}');">查看分发记录</button> `; } // 动态生成查看额外信息 if (userPermissions.includes('read_license')) { modalContent.innerHTML += ` <button onclick="showExtraInfo(); closeModal('${modalId}');">查看额外信息</button> `; } // 检查是否有 `update_license` 权限,决定是否显示修改信息按钮 if (userPermissions.includes('update_license')) { modalContent.innerHTML += `<button onclick="modifyLicenseInfo(); closeModal('${modalId}');">修改信息</button>`; } // 检查是否有 `delete_license` 权限,决定是否显示删除按钮 if (userPermissions.includes('delete_license')) { modalContent.innerHTML += `<button onclick="confirmDelete(); closeModal('${modalId}');">删除</button>`; } // 显示菜单位置 modalContent.style.top = `${event.clientY}px`; modalContent.style.left = `${event.clientX}px`; modal.style.display = 'block'; } function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; } // function closeUserInfo() { // document.getElementById('userModal').style.display = 'none'; // } //删除一行lic信息 function confirmDelete() { const confirmDeleteModal = document.getElementById('confirmDeleteModal'); confirmDeleteModal.innerHTML = ` <div class="centered-modal-content"> <span class="close" onclick="closeModal('confirmDeleteModal')" style="font-size: 24px; font-weight: bold; color: #555; cursor: pointer;">×</span> <div style="margin-bottom: 15px; border: 1px solid #ddd; padding: 10px; border-radius: 10px;"> <p><strong>申请日期:</strong> ${selectedRowData.ApplicationDate}</p> <p><strong>关联项目:</strong> ${selectedRowData.AssociatedProject}</p> <p><strong>使用单位:</strong> ${selectedRowData.Company}</p> </div> <p>确认删除此行数据吗?</p> <button class="flat-rounded-button" onclick="deleteRow()">确认</button> <button class="flat-rounded-button" onclick="closeModal('confirmDeleteModal')">取消</button> </div> `; confirmDeleteModal.style.display = 'block'; } function deleteRow() { fetch(`http://127.0.0.1:8080/api/admin/deleteLicRow`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ uniqueID: selectedRowData.UniqueID }) }).then(response => { if (response.ok) { alert('删除成功'); closeModal('confirmDeleteModal'); // fetchApplications(LisOffset, pageSize); const startOffset = currentOffset; // 当前的起始位置 const endOffset = startOffset + itemsPerPage - 1; // 计算结束位置 fetchApplications(startOffset, endOffset); // 传入计算好的起始和结束位置 } else { alert('删除失败'); } }); } //添加用户 document.getElementById('addUserButton').addEventListener('click', function() { document.getElementById('addUserModal').style.display = 'block'; }); //添加用户 function saveNewUser() { const username = document.getElementById('addUsername').value.trim(); const password = document.getElementById('addPassword').value.trim(); const account = document.getElementById('addAccount').value.trim(); const telephone = document.getElementById('addTelephone').value.trim(); const email = document.getElementById('addEmail').value.trim(); // 验证每个字段都不能为空 if (!username || !password || !account || !telephone || !email) { alert('有空选项未填写'); return; } // 验证电话是否为11位数字 const phonePattern = /^\d{11}$/; if (!phonePattern.test(telephone)) { alert('电话必须是11位数字'); return; } // 验证密码长度是否至少为6位 if (password.length < 6) { alert('密码长度必须至少为6位'); return; } // 验证邮箱是否包含@符号 if (!email.includes('@')) { alert('邮箱必须包含@符号'); return; } // 验证账号长度是否至少为3位 if (account.length < 3) { alert('账号长度必须至少为3位'); return; } const newUser = { Username: username, Password: password, Account: account, Telephone: telephone, Email: email }; fetch('http://127.0.0.1:8080/api/register', { // 修改为实际的API路径 method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(newUser) }) .then(response => response.json()) .then(data => { if (data.success) { alert('用户创建成功!'); fetchUsers(); // 重新加载用户列表 closeModal('addUserModal'); // 关闭模态框 } else { alert('用户创建失败:' + data.error); } }); } function deleteUser(uniqueID) { fetch('http://127.0.0.1:8080/api/admin/deleteUser', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ UniqueID: uniqueID }) }) .then(response => response.json()) .then(data => { if (data.success) { alert('用户删除成功!'); fetchUsers(); // 重新加载用户列表 } else { alert('用户删除失败:' + data.error); } }) .catch(error => { console.error('Error deleting user:', error); alert('删除用户时发生错误,请稍后再试。'); }); } function confirmDeleteUser(uniqueID) { const confirmed = confirm("确认删除此用户吗?"); if (confirmed) { deleteUser(uniqueID); } } // 分发按钮点击事件处理函数 function distributeLicense(oa_id,supportEmail, salesEmail, uniqueID,oa_request_id) { // 显示加载进度条并设置动态提示信息 showLoadingModal('正在分发...'); // 将数据作为查询参数传递给 GET 请求 const url = `http://127.0.0.1:8080/api/admin/GetDistributeButtenCheckController?oa_request_id=${oa_id}`; // 向后端发送 GET 请求 fetch(url, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { // 隐藏加载进度条 hideLoadingModal(); if (data.success) { // 请求成功,弹出模态框 showEmailModal(supportEmail, salesEmail, uniqueID,oa_request_id); } else { // 请求失败,弹出错误提示 alert(`分发失败: ${data.error}`); } }) .catch(error => { // 请求失败时隐藏加载进度条 hideLoadingModal(); alert(`请求出错: ${error}`); }); } // 分发模态框 function showEmailModal(supportEmail, salesEmail, uniqueID,oa_request_id) { // 清空并设置默认值 document.getElementById('emailInputs').innerHTML = ` <div> <input type="checkbox" id="supportEmailCheckbox" value="${supportEmail}" > <label for="supportEmailCheckbox"> 运维邮箱: ${supportEmail}</label> </div> <div> <input type="checkbox" id="salesEmailCheckbox" value="${salesEmail}" > <label for="salesEmailCheckbox"> 销售邮箱: ${salesEmail}</label> </div> `; document.getElementById('userInputs').innerHTML = ''; // 清空用户输入 // 获取用户信息并填充第一个用户输入框 fetch('http://127.0.0.1:8080/api/admin/distributeLicenseByUserInfo', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { const userSelect = document.createElement('select'); userSelect.id = 'userSelect1'; userSelect.className = 'email-modal-input'; data.data.forEach(user => { userMap[user.Username] = {// 存储用户名和用户ID的映射 Account: user.Account, UniqueID: user.UniqueID, Username: user.Username, Email: user.Email, Role: user.Role, Telephone:user.Telephone }; const option = document.createElement('option'); option.value = user.Username; option.textContent = user.Username; userSelect.appendChild(option); }); //document.getElementById('userInputs').appendChild(userSelect); }); document.getElementById('emailModal').style.display = 'block'; selectedRowData = { ...selectedRowData, UniqueID: uniqueID ,Oa_request_id: oa_request_id}; } function addEmailInput() { const emailInputs = document.getElementById('emailInputs'); const newInputDiv = document.createElement('div'); newInputDiv.style.display = 'flex'; newInputDiv.style.alignItems = 'center'; newInputDiv.style.marginBottom = '10px'; const newInput = document.createElement('input'); newInput.type = 'text'; newInput.className = 'email-modal-input'; newInput.style.flexGrow = '1'; newInputDiv.appendChild(newInput); const deleteButton = document.createElement('button'); deleteButton.textContent = '✕'; deleteButton.style.background = 'none'; deleteButton.style.border = 'none'; deleteButton.style.color = '#007aff'; deleteButton.style.cursor = 'pointer'; deleteButton.style.fontSize = '12px'; /* 再次缩小字体大小 */ deleteButton.style.padding = '0'; /* 移除内边距 */ deleteButton.style.marginLeft = '3px'; /* 减少与输入框的间距 */ deleteButton.style.width = '20px'; /* 限制按钮宽度 */ deleteButton.style.height = '20px'; /* 限制按钮高度 */ deleteButton.onclick = () => { newInputDiv.remove(); }; newInputDiv.appendChild(deleteButton); emailInputs.appendChild(newInputDiv); } function addUserInput() { const userInputs = document.getElementById('userInputs'); const newUserDiv = document.createElement('div'); newUserDiv.className = 'user-select-container'; newUserDiv.style.display = 'flex'; newUserDiv.style.alignItems = 'center'; newUserDiv.style.marginBottom = '10px'; const newUserSelect = document.createElement('select'); newUserSelect.className = 'email-modal-input'; newUserSelect.style.flexGrow = '1'; newUserSelect.style.marginRight = '5px'; // 添加一个默认的空白选项 const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = '请选择用户'; newUserSelect.appendChild(defaultOption); // 获取当前已选择的用户 const selectedValues = Array.from(document.querySelectorAll('.user-select-container select')) .map(select => select.value); // 获取用户列表并填充到选择框中 fetch('http://127.0.0.1:8080/api/admin/distributeLicenseByUserInfo', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { data.data.forEach(user => { // 仅显示未被选中的用户,并且过滤掉admin用户 if (!selectedValues.includes(user.Username) && user.Username !== 'admin') { const option = document.createElement('option'); option.value = user.Username; option.textContent = user.Username; newUserSelect.appendChild(option); } }); }); const deleteButton = document.createElement('button'); deleteButton.textContent = '✕'; deleteButton.style.background = 'none'; deleteButton.style.border = 'none'; deleteButton.style.color = '#007aff'; deleteButton.style.cursor = 'pointer'; deleteButton.style.fontSize = '12px'; deleteButton.style.padding = '0'; deleteButton.style.marginLeft = '3px'; deleteButton.style.width = '20px'; deleteButton.style.height = '20px'; deleteButton.onclick = () => { newUserDiv.remove(); updateUserOptions(); // 更新其他下拉框中的选项 }; newUserSelect.addEventListener('change', updateUserOptions); newUserDiv.appendChild(newUserSelect); newUserDiv.appendChild(deleteButton); userInputs.appendChild(newUserDiv); // 设置空白选项为默认选项 newUserSelect.selectedIndex = 0; } function updateUserOptions() { const selectedValues = Array.from(document.querySelectorAll('.user-select-container select')) .map(select => select.value); document.querySelectorAll('.user-select-container select').forEach(select => { const currentValue = select.value; select.innerHTML = ''; // 清空现有选项 // 添加一个默认的空白选项 const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = '请选择用户'; select.appendChild(defaultOption); fetch('http://127.0.0.1:8080/api/admin/userInfoAll', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { data.data.forEach(user => { if (!selectedValues.includes(user.Username) || user.Username === currentValue) { if (user.Username !== 'admin') { // 过滤掉admin用户 const option = document.createElement('option'); option.value = user.Username; option.textContent = user.Username; select.appendChild(option); } } }); select.value = currentValue; }); }); } // 打开修改信息表单框 function modifyLicenseInfo() { const form = document.getElementById('modifyLicenseForm'); // 将选中的行数据填充到表单中 form.creator.value = selectedRowData.Creator; form.applicationDate.value = selectedRowData.ApplicationDate; form.associatedProject.value = selectedRowData.GlxmName; form.salesPerson.value = selectedRowData.SalesPerson; form.salesEmail.value = selectedRowData.SalesEmail; form.supportPerson.value = selectedRowData.SupportPerson; form.supportEmail.value = selectedRowData.SupportEmail; form.totalNodes.value = selectedRowData.TotalNodes; form.company.value = selectedRowData.Company; form.productName.value = selectedRowData.ProductName; form.version.value = selectedRowData.ProductVersion; form.nodeCount.value = selectedRowData.NodeCount; document.getElementById('modifyLicenseModal').style.display = 'block'; } // 保存修改后的数据 function saveLicenseChanges() { const form = document.getElementById('modifyLicenseForm'); const updatedData = { UniqueID: selectedRowData.UniqueID, Creator: form.creator.value, ApplicationDate: form.applicationDate.value, AssociatedProject: form.associatedProject.value, SalesPerson: form.salesPerson.value, SalesEmail: form.salesEmail.value, SupportPerson: form.supportPerson.value, SupportEmail: form.supportEmail.value, TotalNodes: parseInt(form.totalNodes.value, 10), // 将 TotalNodes 转换为整数 Company: form.company.value, ProductName: form.productName.value, Version: form.version.value, NodeCount: parseInt(form.nodeCount.value, 10), // 将 NodeCount 转换为整数 }; fetch(`http://127.0.0.1:8080/api/admin/UpdateLicense`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(updatedData) }) .then(response => response.json()) .then(data => { if (data.success) { alert('License信息更新成功!'); // fetchApplications(LisOffset, pageSize); const startOffset = currentOffset; // 当前的起始位置 const endOffset = startOffset + itemsPerPage - 1; // 计算结束位置 fetchApplications(startOffset, endOffset); // 传入计算好的起始和结束位置 closeModal('modifyLicenseModal'); } else { alert('License信息更新失败:' + data.error); } }); } function updateUserOptions() { const selectedValues = Array.from(document.querySelectorAll('.user-select-container select')) .map(select => select.value); document.querySelectorAll('.user-select-container select').forEach(select => { const currentValue = select.value; // 保留当前选择值 select.innerHTML = ''; // 清空现有选项 fetch('http://127.0.0.1:8080/api/admin/distributeLicenseByUserInfo', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { data.data.forEach(user => { // 保留当前值,并排除已经在其他下拉框中选中的值 if (!selectedValues.includes(user.Username) || user.Username === currentValue) { const option = document.createElement('option'); option.value = user.Username; option.textContent = user.Username; if (user.Username === currentValue) { option.selected = true; // 保持当前选择 } select.appendChild(option); } }); }); }); } //lic分发给用户 与邮件 function sendEmail() { console.log('Send button clicked'); // 显示加载进度条并设置动态提示信息 showLoadingModal('正在分发 License...'); const emailInputs = document.querySelectorAll('.email-modal-input[type="text"]'); let emails = Array.from(emailInputs) .map(input => input.value.trim()) .filter(email => email && email.includes('@')) .join(','); const supportEmailChecked = document.getElementById('supportEmailCheckbox').checked; const salesEmailChecked = document.getElementById('salesEmailCheckbox').checked; const emailArray = emails ? [emails] : []; if (supportEmailChecked) { emailArray.push(document.getElementById('supportEmailCheckbox').value); } if (salesEmailChecked) { emailArray.push(document.getElementById('salesEmailCheckbox').value); } emails = emailArray.join(','); // if (!emails) { // alert('请至少选择一个邮箱地址。'); // return; // } console.log('Emails to send:', emails); const userInputs = document.querySelectorAll('select.email-modal-input'); console.log('userMap:', userMap); const users = Array.from(userInputs) .map(select => userMap[select.value].Account) .join(','); const userIds = Array.from(userInputs) .map(select => userMap[select.value].UniqueID) .join(','); const userNames = Array.from(userInputs) .map(select => userMap[select.value].Username); const operatorUniqueID = userMap[currentUserName].UniqueID; console.log('User IDs:', userIds); console.log('Users:', users); console.log(' selectedRowData.UniqueID:', selectedRowData.UniqueID); if (!userIds) { alert('请至少选择一个用户。'); // 请求完成后隐藏加载进度条 hideLoadingModal(); return; } const requestData = { LicenseUniqueID: selectedRowData.UniqueID, Oa_request_id: selectedRowData.Oa_request_id, UserUniqueIDs: userIds.split(','), UserAccounts: users.split(','), Emails: emails, UserNames: userNames, OperatorUniqueID: operatorUniqueID }; console.log('requestData:', requestData); fetch('http://127.0.0.1:8080/api/admin/distributeLicense', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(requestData) }) .then(response => { console.log('Response received'); return response.json(); }) .then(data => { // 请求完成后隐藏加载进度条 hideLoadingModal(); if (data.success) { alert('分发成功!'); closeModal('emailModal'); } else { // 检查是否有 error 字段,并提示用户详细的错误信息 const errorMessage = data.error || '分发失败。'; alert(`分发失败: ${errorMessage}`); } }) .catch(error => { // 请求失败时隐藏加载进度条 hideLoadingModal(); console.error('Error occurred during email distribution:', error); alert('分发失败,请检查网络或后端服务。'); }); } function showDistributionHistory() { fetch('http://127.0.0.1:8080/api/admin/GetlicenseRecord', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ uniqueID: selectedRowData.UniqueID, oa_request_id: selectedRowData.oa_request_id }) }) .then(response => response.json()) .then(data => { const userDistributionContent = document.getElementById('userDistributionContent'); const emailDistributionContent = document.getElementById('emailDistributionContent'); const { license_record_to_user, license_record_to_emails } = data.data; const userRecords = Array.isArray(license_record_to_user) ? license_record_to_user : []; const emailRecords = Array.isArray(license_record_to_emails) ? license_record_to_emails : []; // 手动格式化日期时间为 YYYY-MM-DD HH:mm:ss 格式,保持 UTC 时间不变 function formatDateTime(dateString) { const date = new Date(dateString); // 使用 UTC 时间,而不是本地时间 const year = date.getUTCFullYear(); const month = String(date.getUTCMonth() + 1).padStart(2, '0'); // 月份从0开始,所以+1 const day = String(date.getUTCDate()).padStart(2, '0'); const hours = String(date.getUTCHours()).padStart(2, '0'); const minutes = String(date.getUTCMinutes()).padStart(2, '0'); const seconds = String(date.getUTCSeconds()).padStart(2, '0'); // 返回格式化后的字符串 YYYY-MM-DD HH:mm:ss return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } // 显示用户分发记录 if (userRecords.length > 0) { const userHistoryHtml = userRecords.map(record => ` <div class="distribution-item"> <p><strong>已转发给用户:</strong> ${record.user_account}</p> <p><strong>分发时间:</strong> ${formatDateTime(record.up_time)}</p> </div> `).join(''); userDistributionContent.innerHTML = userHistoryHtml; } else { userDistributionContent.innerHTML = '<p>没有用户分发记录。</p>'; } // 显示邮箱分发记录 if (emailRecords.length > 0) { const emailHistoryHtml = emailRecords.map(record => ` <div class="distribution-item"> <p><strong>已发给邮箱:</strong> ${record.emails}</p> <p><strong>分发时间:</strong> ${formatDateTime(record.up_time)}</p> </div> `).join(''); emailDistributionContent.innerHTML = emailHistoryHtml; } else { emailDistributionContent.innerHTML = '<p>没有邮箱分发记录。</p>'; } // 显示模态框 const distributionHistoryModal = document.getElementById('distributionHistoryModal'); distributionHistoryModal.style.display = 'block'; }) .catch(error => { console.error('Error fetching distribution history:', error); }); } function showMoreUserInfo() { const extraInfoContent = document.getElementById('extraInfoContent'); extraInfoContent.innerHTML = ` <p><strong>用户名:</strong> ${selectedRowData.Username}</p> <p><strong>电话:</strong> ${selectedRowData.Telephone}</p> <p><strong>邮箱:</strong> ${selectedRowData.Email}</p> <p><strong>权限:</strong> ${selectedRowData.Role}</p> `; document.getElementById('extraInfoModal').style.display = 'block'; } function modifyUser() { const userInfoContent = document.getElementById('extraInfoContent'); userInfoContent.innerHTML = ` <p><strong>用户名:</strong> ${selectedRowData.Username}</p> <p><strong>电话:</strong> ${selectedRowData.Telephone}</p> <p><strong>邮箱:</strong> ${selectedRowData.Email}</p> <p><strong>权限:</strong> ${selectedRowData.Role}</p> <button onclick="showEditUserForm()">编辑用户信息</button> `; document.getElementById('extraInfoModal').style.display = 'block'; } //查看额外信息 function showExtraInfo() { const extraInfoContent = document.getElementById('extraInfoContent'); // 清空之前的内容 extraInfoContent.innerHTML = ''; // 使用预定义的字段名和中文翻译 const fieldTranslations = { id: "ID", user_id: "用户ID", up_user: "上传用户", up_time: "上传时间", del_time: "删除时间", License1: "License 1", License2: "License 2", LicenseFlage: "License 状态", UniqueID: "唯一标识符", Creator: "创建人", ApplicationDate: "申请日期", AssociatedProject: "关联项目", SalesPerson: "销售人员", SalesEmail: "销售邮箱", SupportPerson: "支持人员", SupportEmail: "支持邮箱", TotalNodes: "总节点数", Company: "公司", ProductName: "产品名称", Version: "版本", NodeCount: "节点数", Processor: "处理器", OperatingSystem: "操作系统", MasterMacAddress: "主MAC地址", SecondaryMasterMacAddress: "备用主MAC地址" }; // 使用指定的字段进行展示 const fieldsToShow = [ "id", "user_id", "up_user", "up_time", "del_time", "License1", "License2", "LicenseFlage", "UniqueID", "Creator", "ApplicationDate", "AssociatedProject", "SalesPerson", "SalesEmail", "SupportPerson", "SupportEmail", "TotalNodes", "Company", "ProductName", "Version", "NodeCount", "Processor", "OperatingSystem", "MasterMacAddress", "SecondaryMasterMacAddress" ]; fieldsToShow.forEach(key => { if (selectedRowData.hasOwnProperty(key)) { let value = selectedRowData[key]; // 特殊处理 up_time 和 del_time if (key === 'up_time' || key === 'del_time') { if (value.Valid) { value = new Date(value.Time).toLocaleString(); // 格式化日期时间 } else { value = '无'; } } // 处理 License1 和 License2,提取字符串字段 if (key === 'License1' || key === 'License2') { // 假设 License 对象包含一个名为 'Details' 的字符串字段 value = value.String || '[无数据]'; } // 处理 MasterMacAddress 和 SecondaryMasterMacAddress,提取字符串字段 // if (key === 'MasterMacAddress' || key === 'SecondaryMasterMacAddress') { // // 假设 License 对象包含一个名为 'Details' 的字符串字段 // value = value.String || '[无数据]'; // } const infoElement = document.createElement('p'); infoElement.innerHTML = `<strong>${fieldTranslations[key]}:</strong> ${value}`; extraInfoContent.appendChild(infoElement); } }); // 显示 modal document.getElementById('extraInfoModal').style.display = 'block'; } function showRoleManagement() { document.getElementById('table-container').style.display = 'none'; document.getElementById('user-management').style.display = 'none'; // 隐藏用户管理页面 document.getElementById('role-management').style.display = 'block';; fetchRoles(); } function fetchRoles() { fetch('http://127.0.0.1:8080/api/admin/GetRoles', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ Name: " " }) // 发送空的 Name 参数 }) .then(response => response.json()) .then(data => { const roleContainer = document.getElementById('roles-container'); roleContainer.innerHTML = ''; // 清空之前的内容 const permissionMap = { 'generate_license': '生成许可证', 'upload_license': '上传许可证(废弃)', 'read_license': '读取许可证', 'read_license_record': '读取许可证分发记录', 'update_license': '修改许可证(废弃)', 'delete_license': '删除许可证(废弃)', 'dispat_license': '分发许可证', 'create_user': '创建用户', 'read_user': '读取用户', 'update_user': '更新用户', 'delete_user': '删除用户', 'create_role': '创建角色', 'delete_role': '删除角色', 'update_role': '更新角色', 'get_role': '获取角色' }; // 检查用户是否有 create_role 权限 const hasCreateRolePermission = userPermissions.includes('create_role'); // 如果有权限则显示“创建角色”按钮 if (hasCreateRolePermission) { document.getElementById('createRoleButton').style.display = 'block'; } else { document.getElementById('createRoleButton').style.display = 'none'; } // 处理置顶角色和其他角色的渲染(代码不变) const topRoles = ['admin', 'guest', 'supportRole']; topRoles.forEach(role => { if (data.data[role]) { renderRole(roleContainer, data.data[role], permissionMap, true); } }); Object.keys(data.data).forEach(role => { if (!topRoles.includes(role)) { renderRole(roleContainer, data.data[role], permissionMap, false); } }); }); } function renderRole(container, roleInfo, permissionMap, isTopRole) { const roleDiv = document.createElement('div'); roleDiv.className = 'role-item'; roleDiv.style.position = 'relative'; // 确保弹出菜单能够正确定位 if (isTopRole) { roleDiv.classList.add('top-role'); // 应用置顶角色的样式 } let permissions = roleInfo.Permissions.map(permission => permissionMap[permission]); let permissionsHtml = permissions.join(','); // 使用逗号分隔并合并为一行 roleDiv.innerHTML = ` <h3>${roleInfo.Name}</h3> <p>${permissionsHtml}</p> `; container.appendChild(roleDiv); // 添加事件监听器,处理点击和右键点击弹出菜单 roleDiv.addEventListener('click', function(event) { event.stopPropagation(); // 阻止事件冒泡 event.preventDefault(); // 阻止默认行为 showRoleActionMenu(event, roleInfo.Name); }); roleDiv.addEventListener('contextmenu', function(event) { event.preventDefault(); showRoleActionMenu(event, roleInfo.Name); }); } function showRoleActionMenu(event, roleName) { const existingMenu = document.getElementById('role-action-menu'); if (existingMenu) { existingMenu.remove(); } const menu = document.createElement('div'); menu.id = 'role-action-menu'; menu.style.position = 'absolute'; menu.style.top = `${event.clientY}px`; menu.style.left = `${event.clientX}px`; menu.style.backgroundColor = '#fff'; menu.style.border = '1px solid #ccc'; menu.style.borderRadius = '5px'; menu.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)'; menu.style.padding = '10px'; menu.style.zIndex = '1000'; const topRoles = ['admin', 'guest', 'support']; if (topRoles.includes(roleName)) { // 为 admin, guest, supportRole 设置灰色和不可点击样式 const disabledButton = document.createElement('button'); disabledButton.textContent = '不可操作'; disabledButton.style.display = 'block'; disabledButton.style.width = '100%'; disabledButton.style.padding = '10px 20px'; disabledButton.style.border = 'none'; disabledButton.style.borderRadius = '15px'; disabledButton.style.cursor = 'not-allowed'; disabledButton.style.backgroundColor = '#d3d3d3'; // 灰色背景 disabledButton.style.color = '#999'; // 灰色文字 menu.appendChild(disabledButton); } else { // 检查用户是否有 update_role 和 delete_role 权限 const hasUpdateRolePermission = userPermissions.includes('update_role'); const hasDeleteRolePermission = userPermissions.includes('delete_role'); // 创建和添加修改角色按钮 if (hasUpdateRolePermission) { const modifyButton = document.createElement('button'); modifyButton.textContent = '修改角色'; modifyButton.style.display = 'block'; modifyButton.style.marginBottom = '10px'; modifyButton.style.width = '100%'; modifyButton.style.padding = '10px 20px'; modifyButton.style.border = 'none'; modifyButton.style.borderRadius = '15px'; modifyButton.style.cursor = 'pointer'; modifyButton.style.transition = 'background-color 0.3s, color 0.3s'; modifyButton.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)'; modifyButton.style.backgroundColor = '#007aff'; modifyButton.style.color = '#fff'; modifyButton.addEventListener('mouseenter', function () { modifyButton.style.backgroundColor = '#005bb5'; }); modifyButton.addEventListener('mouseleave', function () { modifyButton.style.backgroundColor = '#007aff'; }); modifyButton.addEventListener('click', function () { modifyRole(roleName); menu.remove(); // 点击按钮后,关闭菜单栏 }); menu.appendChild(modifyButton); } // 创建和添加删除角色按钮 if (hasDeleteRolePermission) { const deleteButton = document.createElement('button'); deleteButton.textContent = '删除角色'; deleteButton.style.display = 'block'; deleteButton.style.width = '100%'; deleteButton.style.padding = '10px 20px'; deleteButton.style.border = 'none'; deleteButton.style.borderRadius = '15px'; deleteButton.style.cursor = 'pointer'; deleteButton.style.transition = 'background-color 0.3s, color 0.3s'; deleteButton.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)'; deleteButton.style.backgroundColor = '#ff3b30'; deleteButton.style.color = '#fff'; deleteButton.addEventListener('mouseenter', function () { deleteButton.style.backgroundColor = '#c23321'; }); deleteButton.addEventListener('mouseleave', function () { deleteButton.style.backgroundColor = '#ff3b30'; }); deleteButton.addEventListener('click', function () { deleteRole(roleName); menu.remove(); // 点击按钮后,关闭菜单栏 }); menu.appendChild(deleteButton); } // 如果用户没有修改或删除权限,则显示没有选项的提示 if (!hasUpdateRolePermission && !hasDeleteRolePermission) { const noOption = document.createElement('div'); noOption.textContent = '没有可用的操作'; noOption.style.textAlign = 'center'; noOption.style.color = '#999'; menu.appendChild(noOption); } } document.body.appendChild(menu); document.addEventListener('click', function closeMenu(event) { if (!menu.contains(event.target)) { menu.remove(); document.removeEventListener('click', closeMenu); } }); } //修改角色信息 function modifyRole(roleName) { console.log(`modifyRole called with roleName: ${roleName}`); fetchRoleInfo(roleName, function(roleInfo) { console.log(`fetchRoleInfo returned:`, roleInfo); if (!roleInfo) { console.error('Role info is undefined or null'); return; } const extraInfoContent = document.getElementById('extraInfoContent'); if (!extraInfoContent) { console.error('Element with id "extraInfoContent" not found'); return; } extraInfoContent.innerHTML = ` <h3>修改角色: ${roleInfo.Name}</h3> <label for="roleName">角色名称:</label> <input type="text" id="roleName" value="${roleInfo.Name}" required><br><br> <label for="permissions">权限:</label><br> <div id="permissions"> <div> <input type="checkbox" id="license" name="permissions" value="license" onchange="toggleSubPermissions('license', this)"> <label for="license">许可证</label> <div id="licenseSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="generate_license" name="permissions" value="generate_license"> <label for="generate_license">生成许可证</label><br> <input type="checkbox" id="upload_license" name="permissions" value="upload_license"> <label for="upload_license">上传许可证</label><br> <input type="checkbox" id="read_license" name="permissions" value="read_license"> <label for="read_license">读取许可证</label><br> <input type="checkbox" id="update_license" name="permissions" value="update_license"> <label for="update_license">更新许可证</label><br> <input type="checkbox" id="delete_license" name="permissions" value="delete_license"> <label for="delete_license">删除许可证</label><br> </div> </div> <div> <input type="checkbox" id="user" name="permissions" value="user" onchange="toggleSubPermissions('user', this)"> <label for="user">用户</label> <div id="userSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="create_user" name="permissions" value="create_user"> <label for="create_user">创建用户</label><br> <input type="checkbox" id="read_user" name="permissions" value="read_user"> <label for="read_user">读取用户</label><br> <input type="checkbox" id="update_user" name="permissions" value="update_user"> <label for="update_user">更新用户</label><br> <input type="checkbox" id="delete_user" name="permissions" value="delete_user"> <label for="delete_user">删除用户</label><br> </div> </div> <div> <input type="checkbox" id="role" name="permissions" value="role" onchange="toggleSubPermissions('role', this)"> <label for="role">角色</label> <div id="roleSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="create_role" name="permissions" value="create_role"> <label for="create_role">创建角色</label><br> <input type="checkbox" id="delete_role" name="permissions" value="delete_role"> <label for="delete_role">删除角色</label><br> <input type="checkbox" id="update_role" name="permissions" value="update_role"> <label for="update_role">更新角色</label><br> <input type="checkbox" id="get_role" name="permissions" value="get_role"> <label for="get_role">获取角色</label><br> </div> </div> </div><br><br> <button onclick="saveRoleChanges('${roleInfo.Id}')">保存</button> `; console.log('Form content added to extraInfoContent'); const checkboxes = document.querySelectorAll('#permissions input[type="checkbox"]'); // 遍历所有复选框 checkboxes.forEach(checkbox => { if (roleInfo.Permissions.includes(checkbox.value)) { checkbox.checked = true; // 如果当前权限在roleInfo.Permissions中,则勾选 } }); const extraInfoModal = document.getElementById('extraInfoModal'); if (!extraInfoModal) { console.error('Element with id "extraInfoModal" not found'); return; } extraInfoModal.style.display = 'block'; // 强制显示模态框 console.log('Modal should be visible now'); }); } function getCheckboxOptions(selectedPermissions) { const permissionMap = { 'generate_license': '生成许可证', 'upload_license': '上传许可证(废弃)', 'read_license': '读取许可证', 'update_license': '修改许可证(废弃)', 'delete_license': '删除许可证(废弃)', 'dispat_license': '分发许可证', 'read_license_record': '读取许可证分发记录', // 'get_user_info': '获取用户信息', 'create_user': '创建用户', 'read_user': '读取用户', 'update_user': '更新用户', 'delete_user': '删除用户', 'create_role': '创建角色', 'delete_role': '删除角色', 'update_role': '更新角色', 'get_role': '获取角色' }; return Object.keys(permissionMap).map(permission => ` <div> <input type="checkbox" id="${permission}" name="permissions" value="${permission}" ${selectedPermissions.includes(permission) ? 'checked' : ''}> <label for="${permission}">${permissionMap[permission]}</label> </div> `).join(''); } function fetchRoleInfo(roleName, callback) { console.log(`fetchRoleInfo called with roleName: ${roleName}`); fetch('http://127.0.0.1:8080/api/admin/GetRoles', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ Name: roleName }) }) .then(response => { console.log('fetchRoleInfo response received', response); return response.json(); }) .then(data => { console.log('fetchRoleInfo data received', data); // 直接从 data.data 获取角色信息 if (data && data.data) { console.log('Role info found:', data.data); callback(data.data); // 直接返回 data.data 而不是 data.data[roleName] } else { console.error('Role not found or unexpected data structure', data); callback(null); // 如果角色信息未找到,返回 null } }) .catch(error => { console.error('Error in fetchRoleInfo:', error); callback(null); // 捕获异常情况 }); } function getPermissionsOptions(selectedPermissions) { const permissionMap = { 'generate_license': '生成许可证(废弃)', 'upload_license': '上传许可证', 'read_license': '读取许可证', 'update_license': '修改许可证(废弃)', 'delete_license': '删除许可证(废弃)', 'dispat_license': '分发许可证', 'read_license_record': '读取许可证分发记录', //'get_user_info': '获取用户信息', 'create_user': '创建用户', 'read_user': '读取用户', 'update_user': '更新用户', 'delete_user': '删除用户', 'create_role': '创建角色', 'delete_role': '删除角色', 'update_role': '更新角色', 'get_role': '获取角色' }; return Object.keys(permissionMap).map(permission => ` <option value="${permission}" ${selectedPermissions.includes(permission) ? 'selected' : ''}> ${permissionMap[permission]} </option> `).join(''); } function saveRoleChanges(roleId) { const updatedRoleName = document.getElementById('roleName').value.trim(); const selectedPermissions = Array.from(document.querySelectorAll('#permissions input[type="checkbox"]:checked')) .map(checkbox => checkbox.value) .filter(value => !['license', 'user', 'role'].includes(value)); // 过滤掉一级分类 if (!updatedRoleName) { alert('角色名称不能为空!'); return; } const updateRole = { Id: parseInt(roleId, 10), // 确保 roleId 被传递并转换为整数 Name: updatedRoleName, Permissions: selectedPermissions }; fetch('http://127.0.0.1:8080/api/admin/UpdateRole', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(updateRole) }) .then(response => response.json()) .then(data => { if (data.success) { alert('角色更新成功!'); fetchRoles(); // 刷新角色列表 closeModal('extraInfoModal'); // 关闭信息栏 } else { alert('角色更新失败:' + data.error); } }); } //删除角色 function deleteRole(roleName) { console.log(`deleteRole called for role: ${roleName}`); const confirmed = confirm(`确认删除角色: ${roleName} 吗?`); if (!confirmed) { return; } fetch('http://127.0.0.1:8080/api/admin/DeleteRole', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: roleName // 将角色名称传递给后端 }) }) .then(response => response.json()) .then(data => { if (data.success) { alert('角色删除成功!'); fetchRoles(); // 刷新角色列表 } else { alert('角色删除失败:' + data.error); } }) .catch(error => { console.error('Error deleting role:', error); alert('删除角色时发生错误,请稍后再试。'); }); } document.getElementById('createRoleButton').addEventListener('click', function() { const extraInfoContent = document.getElementById('extraInfoContent'); extraInfoContent.innerHTML = ` <h3>创建新角色</h3> <label for="newRoleName">角色名称:</label> <input type="text" id="newRoleName" required><br><br> <label for="newPermissions">权限:</label><br> <div id="newPermissions"> <div> <input type="checkbox" id="license" name="permissions" value="license" onchange="toggleSubPermissions('license', this)"> <label for="license">许可证</label> <div id="licenseSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="generate_license" name="permissions" value="generate_license"> <label for="generate_license">生成许可证</label><br> <input type="checkbox" id="upload_license" name="permissions" value="upload_license"> <label for="upload_license">上传许可证(废弃)</label><br> <input type="checkbox" id="read_license" name="permissions" value="read_license"> <label for="read_license">读取许可证</label><br> <input type="checkbox" id="update_license" name="permissions" value="update_license"> <label for="update_license">更新许可证(废弃)</label><br> <input type="checkbox" id="delete_license" name="permissions" value="delete_license"> <label for="delete_license">删除许可证(废弃)</label><br> </div> </div> <div> <input type="checkbox" id="user" name="permissions" value="user" onchange="toggleSubPermissions('user', this)"> <label for="user">用户</label> <div id="userSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="create_user" name="permissions" value="create_user"> <label for="create_user">创建用户</label><br> <input type="checkbox" id="read_user" name="permissions" value="read_user"> <label for="read_user">读取用户</label><br> <input type="checkbox" id="update_user" name="permissions" value="update_user"> <label for="update_user">更新用户</label><br> <input type="checkbox" id="delete_user" name="permissions" value="delete_user"> <label for="delete_user">删除用户</label><br> </div> </div> <div> <input type="checkbox" id="role" name="permissions" value="role" onchange="toggleSubPermissions('role', this)"> <label for="role">角色</label> <div id="roleSubPermissions" style="margin-left: 20px;"> <input type="checkbox" id="create_role" name="permissions" value="create_role"> <label for="create_role">创建角色</label><br> <input type="checkbox" id="delete_role" name="permissions" value="delete_role"> <label for="delete_role">删除角色</label><br> <input type="checkbox" id="update_role" name="permissions" value="update_role"> <label for="update_role">更新角色</label><br> <input type="checkbox" id="get_role" name="permissions" value="get_role"> <label for="get_role">获取角色</label><br> </div> </div> </div><br><br> <button onclick="createNewRole()">创建</button> </div> `; document.getElementById('extraInfoModal').style.display = 'block'; }); function toggleSubPermissions(category, checkbox) { const subPermissions = document.querySelectorAll(`#${category}SubPermissions input[type="checkbox"]`); subPermissions.forEach(subCheckbox => { subCheckbox.checked = checkbox.checked; }); } function createNewRole() { const newRoleName = document.getElementById('newRoleName').value.trim(); const selectedPermissions = Array.from(document.querySelectorAll('#newPermissions input[type="checkbox"]:checked')) .map(checkbox => checkbox.value) .filter(value => !['license', 'user', 'role'].includes(value)); // 过滤掉一级分类 if (!newRoleName) { alert('角色名称不能为空!'); return; } const newRole = { Name: newRoleName, Permissions: selectedPermissions }; fetch('http://127.0.0.1:8080/api/admin/CreateRole', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(newRole) }) .then(response => response.json()) .then(data => { if (data.success) { alert('角色创建成功!'); fetchRoles(); // 刷新角色列表 closeModal('extraInfoModal'); // 关闭信息栏 } else { alert('角色创建失败:' + data.error); } }); } //显示用户信息 function showEditUserForm() { const extraInfoContent = document.getElementById('extraInfoContent'); // 清空之前的内容 extraInfoContent.innerHTML = ''; // 创建表单 const form = document.createElement('form'); form.id = 'editUserForm'; form.style.width = '400px'; // 增加表单宽度 form.innerHTML = ` <div style="display: flex; align-items: center; margin-bottom: 15px;"> <label for="username" style="flex: 0 0 80px;">用户名:</label> <input type="text" id="username" name="username" value="${selectedRowData.Username}" style="flex: 1;" required> </div> <div style="display: flex; align-items: center; margin-bottom: 15px;"> <label for="telephone" style="flex: 0 0 80px;">电话:</label> <input type="text" id="telephone" name="telephone" value="${selectedRowData.Telephone}" style="flex: 1;" required> </div> <div style="display: flex; align-items: center; margin-bottom: 15px;"> <label for="email" style="flex: 0 0 80px;">邮箱:</label> <input type="email" id="email" name="email" value="${selectedRowData.Email}" style="flex: 1;" required> </div> `; // 检查用户是否有 'update_role' 权限,如果有,则显示权限选择框 if (userPermissions.includes('update_role')) { const roleSelectDiv = document.createElement('div'); roleSelectDiv.style = 'display: flex; align-items: center; margin-bottom: 15px;'; roleSelectDiv.innerHTML = ` <label for="role" style="flex: 0 0 80px;">权限:</label> <select id="role" name="role" style="flex: 1;" required></select> `; form.appendChild(roleSelectDiv); // 获取角色列表并填充到选择框中 fetch('http://127.0.0.1:8080/api/admin/GetRoleNames', { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { const roleSelect = document.getElementById('role'); data.roles.forEach(role => { const option = document.createElement('option'); option.value = role; option.textContent = role; if (selectedRowData.Role === role) { option.selected = true; } roleSelect.appendChild(option); }); }) .catch(error => console.error('获取角色列表时出错:', error)); } // 将表单添加到弹出框内容中 extraInfoContent.appendChild(form); // 添加保存按钮 const saveButton = document.createElement('button'); saveButton.type = 'button'; saveButton.onclick = saveUserChanges; saveButton.style = 'width: 100%; background-color: #007bff; color: white; border: none; padding: 10px; border-radius: 5px;'; saveButton.textContent = '保存'; form.appendChild(saveButton); } function saveUserChanges() { const form = document.getElementById('editUserForm'); const formData = new FormData(form); const updatedUser = { Username: formData.get('username'), Telephone: formData.get('telephone'), Email: formData.get('email'), Role: formData.get('role') }; fetch(`http://127.0.0.1:8080/api/admin/updateUser`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ ...updatedUser, Id: selectedRowData.Id }) }) .then(response => response.json()) .then(data => { if (data.success) { alert('用户信息更新成功!'); fetchUsers(); closeModal('extraInfoModal'); } else { alert('用户信息更新失败:' + data.error); } }); } //用户个人信息 function toggleUserInfo() { const userModal = document.getElementById('userModal'); const userButton = document.getElementById('username'); const rect = userButton.getBoundingClientRect(); const modalWidth = 300; // 信息栏的宽度 const windowWidth = window.innerWidth; // 浏览器窗口的宽度 if (userModal.style.display === 'none' || userModal.style.display === '') { fetch(`http://127.0.0.1:8080/api/admin/userInfo`, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { const userInfoContent = document.getElementById('userInfoContent'); let power; switch (data.data.Role) { case 'admin': power = '至高无上的主'; break; case 'supportRole': power = '运维'; break; case 'guest': power = '访客'; break; default: power = data.data.Role; } userInfoContent.innerHTML = ` <h2> 个人信息</h2> <div class="apple-modal-content"> <p class="apple-modal-text"><strong>用户名:</strong> ${data.data.Username}</p> <p class="apple-modal-text"><strong>账号:</strong> ${data.data.Account}</p> <p class="apple-modal-text"><strong>邮箱:</strong> ${data.data.Email}</p> <p class="apple-modal-text"><strong>电话:</strong> ${data.data.Telephone}</p> <p class="apple-modal-text"><strong>权限:</strong> ${power}</p> </div> `; // 设置模态框位置 userModal.style.top = `${rect.bottom + window.scrollY + 10}px`; const leftPosition = rect.right + window.scrollX + 20; // 右侧位置 const rightEdge = leftPosition + modalWidth; if (rightEdge > windowWidth) { const leftEdge = rect.left + window.scrollX - modalWidth - 20; userModal.style.left = `${Math.max(20, leftEdge)}px`; } else { userModal.style.left = `${leftPosition}px`; } userModal.style.display = 'block'; userModal.style.opacity = '0'; // 先设置透明度为0 setTimeout(() => { userModal.style.opacity = '1'; // 然后慢慢显示 }, 0); // 延迟一帧显示 userModal.style.transition = 'opacity 0.3s ease, top 0.3s ease, left 0.3s ease'; // 添加全局点击监听器 document.addEventListener('click', handleClickOutsideModal); }); } else { closeUserInfo(); } } function closeUserInfo() { const userModal = document.getElementById('userModal'); userModal.style.opacity = '0'; // 先设置透明度为0 setTimeout(() => { userModal.style.display = 'none'; // 然后隐藏 }, 300); // 延迟0.3秒,等待过渡结束 // 移除全局点击监听器 document.removeEventListener('click', handleClickOutsideModal); } function closeUserInfo() { const userModal = document.getElementById('userModal'); userModal.style.opacity = '0'; // 先设置透明度为0 setTimeout(() => { userModal.style.display = 'none'; // 然后隐藏 }, 300); // 延迟0.3秒,等待过渡结束 // 移除全局点击监听器 document.removeEventListener('click', handleClickOutsideModal); } function handleClickOutsideModal(event) { const userModal = document.getElementById('userModal'); if (!userModal.contains(event.target) && event.target.id !== 'username') { closeUserInfo(); } } //用户退出 function logout() { localStorage.removeItem('Authorization'); window.location.href = '/'; } function showUserManagement() { document.getElementById('table-container').style.display = 'none'; document.getElementById('role-management').style.display = 'none'; // 隐藏角色管理页面 document.getElementById('user-management').style.display = 'block'; // 检查用户是否有 create_user 权限 const hasCreateUserPermission = userPermissions.includes('create_user'); // 获取添加用户按钮元素 const addUserButton = document.getElementById('addUserButton'); // 根据权限显示或隐藏添加用户按钮 if (hasCreateUserPermission) { addUserButton.style.display = 'block'; } else { addUserButton.style.display = 'none'; } // 加载用户列表 fetchUsers(); } function showTable() { document.getElementById('user-management').style.display = 'none'; document.getElementById('role-management').style.display = 'none'; // 隐藏角色管理页面 document.getElementById('table-container').style.display = 'block'; } function toggleSidebar() { const sidebar = document.getElementById('sidebar'); const content = document.getElementById('content'); sidebar.classList.toggle('hidden'); content.classList.toggle('expanded'); const toggleButton = document.querySelector('.toggle-sidebar'); if (sidebar.classList.contains('hidden')) { toggleButton.innerHTML = '>'; // 当侧边栏隐藏时,显示右箭头 } else { toggleButton.innerHTML = '<'; // 当侧边栏显示时,显示左箭头 } } function fetchUsername() { fetch(`http://127.0.0.1:8080/api/admin/userInfo`, { method: 'GET', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { document.getElementById('username').textContent = data.data.Username; currentUserRole = data.data.Role; // 存储当前用户的角色 currentUserName = data.data.Username // 使用获取到的角色,调用获取权限的接口 fetchPermissionsByRole(currentUserRole) .then(() => { //fetchApplications(LisOffset, pageSize); // 确保在权限获取之后才调用 fetchApplications const startOffset = currentOffset; // 当前的起始位置 const endOffset = startOffset + itemsPerPage - 1; // 计算结束位置 fetchApplications(startOffset, endOffset); // 传入计算好的起始和结束位置 // 检查用户是否有 upload_license 权限 const hasUploadLicensePermission = userPermissions.includes('upload_license'); // 获取上传按钮元素 const uploadButton = document.querySelector('.upload-button'); // 根据权限显示或隐藏上传按钮 // if (hasUploadLicensePermission) { // uploadButton.style.display = 'inline-block'; // 显示按钮 // } else { // uploadButton.style.display = 'none'; // 隐藏按钮 // } // 是否生成主动抓取lic按钮 checkCaptureLicensePermission(); // 检查是否有 capture_license_once_to_db 权限 }); }); } function fetchPermissionsByRole(role) { return fetch(`http://127.0.0.1:8080/api/admin/GetSelfRoles`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: role }) }) .then(response => response.json()) .then(data => { userPermissions = data.data.Permissions; // 获取用户的权限数组 console.log('userPermissions:', userPermissions); // 定义权限类别 const licensePermissions = ['upload_license', 'read_license']; const userPermissionsCheck = [ 'create_user', 'read_user', 'update_user', 'delete_user']; const rolePermissions = ['create_role', 'delete_role', 'update_role', 'get_role']; const hasLicenseAccess = licensePermissions.some(permission => userPermissions.includes(permission)); const hasUserManagementAccess = userPermissionsCheck.some(permission => userPermissions.includes(permission)); const hasRoleManagementAccess = rolePermissions.some(permission => userPermissions.includes(permission)); // 根据权限渲染菜单并显示初始页面 renderMenuAndInitialPage(hasLicenseAccess, hasUserManagementAccess, hasRoleManagementAccess); }); } function renderMenuAndInitialPage(hasLicenseAccess, hasUserManagementAccess, hasRoleManagementAccess) { const sidebar = document.querySelector('.sidebar'); // 清空现有菜单项 sidebar.innerHTML = ''; let initialPageShown = false; // 动态添加菜单项并确定初始显示的页面 if (hasLicenseAccess) { const licenseButton = document.createElement('button'); licenseButton.textContent = 'License 管理'; licenseButton.onclick = showTable; sidebar.appendChild(licenseButton); if (!initialPageShown) { showTable(); // 如果有License权限,先显示License页面 initialPageShown = true; } } if (hasUserManagementAccess) { const userManagementButton = document.createElement('button'); userManagementButton.textContent = '用户管理'; userManagementButton.onclick = showUserManagement; sidebar.appendChild(userManagementButton); if (!initialPageShown) { showUserManagement(); // 如果没有License权限,但有用户管理权限,显示用户管理页面 initialPageShown = true; } } if (hasRoleManagementAccess) { const roleManagementButton = document.createElement('button'); roleManagementButton.textContent = '角色管理'; roleManagementButton.onclick = showRoleManagement; sidebar.appendChild(roleManagementButton); if (!initialPageShown) { showRoleManagement(); // 如果没有License和用户管理权限,但有角色管理权限,显示角色管理页面 initialPageShown = true; } } if (!initialPageShown && sidebar.firstChild) { sidebar.firstChild.click(); // 如果没有优先的权限页面,则显示菜单中的第一个页面 } } // 显示加载模态框并动态设置提示信息 function showLoadingModal(message) { const loadingModal = document.getElementById('loadingModal'); const loadingMessage = loadingModal.querySelector('h3'); // 获取提示信息元素 loadingMessage.textContent = message; // 动态设置提示信息 loadingModal.style.display = 'block'; // 显示模态框 } // 隐藏加载模态框 function hideLoadingModal() { const loadingModal = document.getElementById('loadingModal'); loadingModal.style.display = 'none'; // 隐藏模态框 } function downloadAllLicenses(sortedApplicationArray) { const zip = new JSZip(); console.log("传进来的 sortedApplicationArray:", sortedApplicationArray); // 初始化计数器,从1开始 let idCounter = 1; let Project = sortedApplicationArray[0].Project; console.log("Project", Project); // 遍历 sortedApplicationArray,下载 lic1 和 lic2 数据 sortedApplicationArray.forEach(row => { if (row.LicenseFlage === "已生成") { // 替换 oa_main_mac 和 oa_second_mac 中的冒号为点 const mainMac = row.oa_main_mac.replace(/:/g, '.'); const secondMac = row.oa_second_mac.replace(/:/g, '.'); // 使用递增的 idCounter 替换 row.oa_id if (row.lic1) { const filename1 = `${idCounter}_license.dat_1_${mainMac}`; zip.file(filename1, row.lic1); } if (row.lic2) { const filename2 = `${idCounter}_license.dat_2_${secondMac}`; zip.file(filename2, row.lic2); } // 每次循环后递增计数器 idCounter++; } }); // 生成 ZIP 文件并触发下载 zip.generateAsync({ type: "blob" }).then(content => { const link = document.createElement('a'); link.href = URL.createObjectURL(content); //link.download = "selected_license.zip"; link.download = `${Project}_license` link.click(); }); } // 添加到每个模态框的 JavaScript 部分 document.addEventListener('DOMContentLoaded', function() { // 获取所有模态框 const modals = document.querySelectorAll('.modal'); // 为每个模态框添加点击事件监听器 modals.forEach(modal => { modal.addEventListener('click', function(event) { // 如果点击的是模态框背景而不是模态框内容,关闭模态框 if (event.target === modal) { modal.style.display = 'none'; } }); }); }); // 页面初始化时调用 fetchUsername 函数 fetchUsername(); //fetchApplications(currentPage, pageSize); </script> </body> </html>