license_info_distribution.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. // 显示分发模态框的函数
  2. function showDistributeModal(item) {
  3. const modal = document.getElementById('DistributeModal');
  4. // 显示模态框
  5. modal.style.display = 'flex';
  6. let usersInfo;
  7. // 获取用户信息并填充第一个用户输入框
  8. fetch(`http://${serverIP}:${serverPort}/api/admin/distributeLicenseByUserInfo`, {
  9. method: 'GET',
  10. headers: {
  11. 'Authorization': `Bearer ${authToken}`, // 确保autoToken是您获取的用户授权令牌
  12. 'Content-Type': 'application/json'
  13. }
  14. })
  15. .then(response => {
  16. if (!response.ok) {
  17. throw new Error('Network response was not ok');
  18. }
  19. return response.json();
  20. })
  21. .then(data => {
  22. usersInfo = data.data; // 假设 data 是返回的用户信息数组或对象
  23. console.log('用户信息:', usersInfo); // 打印用户信息
  24. // 调用处理上半部分(邮箱输入框)的函数
  25. handleEmailSection(item,usersInfo);
  26. // 调用处理下半部分(用户输入框)的函数
  27. handleUserSection(item, usersInfo);
  28. })
  29. .catch(error => {
  30. console.error('获取用户信息失败:', error);
  31. });
  32. // 绑定关闭事件
  33. const closeModalBtn = document.querySelector('.DistributeModal-close');
  34. closeModalBtn.addEventListener('click', closeDistributeModal);
  35. // 点击模态框外部关闭
  36. window.addEventListener('click', (event) => {
  37. if (event.target === modal) {
  38. closeDistributeModal();
  39. }
  40. });
  41. }
  42. function handleEmailSection(item, usersInfo) {
  43. console.log('调用邮箱处理');
  44. console.log('handleEmailSection 用户信息:', usersInfo);
  45. const emailInputs = document.getElementById('DistributeModal-email-inputs');
  46. emailInputs.innerHTML = ''; // 清空之前添加的邮箱输入框
  47. // 设置复选框标签内容
  48. const salesEmailLabel = document.getElementById('salesEmailCheckbox').parentElement;
  49. salesEmailLabel.innerHTML = `
  50. <input type="checkbox" id="salesEmailCheckbox" class="DistributeModal-checkbox">
  51. <span class="DistributeModal-checkbox-custom"></span>
  52. 销售邮箱 (${item.SalesPerson}: ${item.SalesEmail})
  53. `;
  54. const supportEmailLabel = document.getElementById('supportEmailCheckbox').parentElement;
  55. supportEmailLabel.innerHTML = `
  56. <input type="checkbox" id="supportEmailCheckbox" class="DistributeModal-checkbox">
  57. <span class="DistributeModal-checkbox-custom"></span>
  58. 运维邮箱 (${item.SupportPerson}: ${item.SupportEmail})
  59. `;
  60. // 防止重复绑定事件,先移除任何现有的点击事件监听器
  61. const addEmailBtn = document.getElementById('DistributeModal-add-email-btn');
  62. addEmailBtn.replaceWith(addEmailBtn.cloneNode(true));
  63. const newAddEmailBtn = document.getElementById('DistributeModal-add-email-btn');
  64. // 绑定点击事件,动态添加邮箱输入框
  65. newAddEmailBtn.addEventListener('click', () => {
  66. const emailWrapper = document.createElement('div');
  67. emailWrapper.className = 'DistributeModal-email-input-wrapper';
  68. const newEmailInput = document.createElement('input');
  69. newEmailInput.type = 'email';
  70. newEmailInput.placeholder = '输入分发邮箱';
  71. newEmailInput.className = 'DistributeModal-email-input';
  72. // 创建删除按钮
  73. const removeEmailBtn = document.createElement('button');
  74. removeEmailBtn.className = 'DistributeModal-remove-email-btn';
  75. removeEmailBtn.innerHTML = '&times;';
  76. removeEmailBtn.addEventListener('click', () => {
  77. emailWrapper.remove();
  78. });
  79. // 将输入框和删除按钮加入到 emailWrapper 中
  80. emailWrapper.appendChild(newEmailInput);
  81. emailWrapper.appendChild(removeEmailBtn);
  82. // 将 emailWrapper 加入到 emailInputs 容器中
  83. emailInputs.appendChild(emailWrapper);
  84. });
  85. // 内部函数:检查是否存在重复项
  86. function findDuplicates(arr) {
  87. const seen = new Set();
  88. const duplicates = [];
  89. arr.forEach((email) => {
  90. if (seen.has(email)) {
  91. duplicates.push(email);
  92. } else {
  93. seen.add(email);
  94. }
  95. });
  96. return duplicates;
  97. }
  98. // 绑定确认按钮点击事件前,先解除已有事件监听器
  99. const emailConfirmBtn = document.getElementById('DistributeModal-email-confirm-btn');
  100. emailConfirmBtn.replaceWith(emailConfirmBtn.cloneNode(true));
  101. const newEmailConfirmBtn = document.getElementById('DistributeModal-email-confirm-btn');
  102. newEmailConfirmBtn.addEventListener('click', () => {
  103. // 收集邮箱信息
  104. let emails = Array.from(document.querySelectorAll('.DistributeModal-email-input'))
  105. .map(input => input.value.trim())
  106. .filter(email => email); // 过滤掉空邮箱
  107. // 检查是否勾选销售邮箱或运维邮箱
  108. const isSalesEmailChecked = document.getElementById('salesEmailCheckbox').checked;
  109. const isSupportEmailChecked = document.getElementById('supportEmailCheckbox').checked;
  110. if (isSalesEmailChecked) {
  111. emails.push(item.SalesEmail);
  112. }
  113. if (isSupportEmailChecked) {
  114. emails.push(item.SupportEmail);
  115. }
  116. // 检查是否存在重复的邮箱
  117. const duplicateEmails = findDuplicates(emails);
  118. if (duplicateEmails.length > 0) {
  119. alert(`以下邮箱重复:\n${duplicateEmails.join('\n')}`);
  120. } else {
  121. if (confirm("确认发送这些邮件吗?")) {
  122. distributeEmails(item, [...new Set(emails)], usersInfo); // 使用 Set 去重
  123. closeDistributeModal(); // 关闭模态框
  124. }
  125. }
  126. });
  127. }
  128. function handleUserSection(item, usersInfo) {
  129. console.log('handleUserSection 用户信息:', usersInfo); // 打印用户信息
  130. const userInputs = document.getElementById('DistributeModal-user-inputs');
  131. userInputs.innerHTML = ''; // 清空之前添加的用户选择框
  132. // 过滤掉 admin 账户
  133. const filteredUsersInfo = usersInfo.filter(user => user.Username !== 'admin');
  134. // 用于存储已经选择的用户
  135. let selectedUsersSet = new Set();
  136. // 绑定新增下拉框按钮
  137. const addSelectBtn = document.getElementById('distributeUser-add-select-btn');
  138. addSelectBtn.replaceWith(addSelectBtn.cloneNode(true)); // 防止重复绑定
  139. const newAddSelectBtn = document.getElementById('distributeUser-add-select-btn');
  140. // 函数:更新所有下拉框中的可选项
  141. const updateSelectOptions = () => {
  142. Array.from(document.querySelectorAll('.distributeUser-select')).forEach(select => {
  143. const currentValue = select.value; // 当前选中的值
  144. select.innerHTML = ''; // 清空选项
  145. // 添加默认的空选项(必须手动选择)
  146. const defaultOption = document.createElement('option');
  147. defaultOption.value = ''; // 设置为空值
  148. defaultOption.textContent = '请选择用户';
  149. select.appendChild(defaultOption);
  150. filteredUsersInfo.forEach(user => {
  151. if (!selectedUsersSet.has(user.UniqueID) || user.UniqueID === currentValue) {
  152. const option = document.createElement('option');
  153. option.value = user.UniqueID;
  154. option.setAttribute('data-username', user.Username);
  155. option.setAttribute('data-account', user.Account);
  156. option.textContent = `${user.Username} (${user.Account})`;
  157. // 如果是当前选中的值,保持选中状态
  158. if (user.UniqueID === currentValue) {
  159. option.selected = true;
  160. }
  161. select.appendChild(option);
  162. }
  163. });
  164. });
  165. };
  166. newAddSelectBtn.addEventListener('click', () => {
  167. const selectWrapper = document.createElement('div');
  168. selectWrapper.className = 'distributeUser-select-wrapper'; // Flexbox 容器
  169. const select = document.createElement('select');
  170. select.className = 'distributeUser-select'; // 设置下拉框样式
  171. // 添加一个默认的空选项
  172. const defaultOption = document.createElement('option');
  173. defaultOption.value = '';
  174. defaultOption.textContent = '请选择用户'; // 这个选项提示用户选择
  175. defaultOption.selected = true; // 默认选中这个选项
  176. select.appendChild(defaultOption);
  177. // 初始更新下拉框
  178. updateSelectOptions();
  179. // 监听下拉框的变化
  180. select.addEventListener('change', () => {
  181. const previousValue = select.dataset.previousValue;
  182. // 如果之前有选中,移除旧值
  183. if (previousValue) {
  184. selectedUsersSet.delete(previousValue);
  185. }
  186. // 如果有新的选择,添加到 set 中
  187. if (select.value) {
  188. selectedUsersSet.add(select.value);
  189. select.dataset.previousValue = select.value; // 保存当前值为下次移除准备
  190. }
  191. // 更新其他下拉框的选项
  192. updateSelectOptions();
  193. });
  194. // 创建删除按钮,使用与关闭邮件输入框相同的样式
  195. const removeSelectBtn = document.createElement('button');
  196. removeSelectBtn.className = 'DistributeModal-remove-email-btn'; // 使用关闭邮件输入框的按钮样式
  197. removeSelectBtn.innerHTML = '&times;';
  198. removeSelectBtn.addEventListener('click', () => {
  199. const previousValue = select.dataset.previousValue;
  200. if (previousValue) {
  201. selectedUsersSet.delete(previousValue); // 删除时从选中集中移除
  202. }
  203. selectWrapper.remove(); // 删除下拉框
  204. updateSelectOptions(); // 更新其他下拉框的选项
  205. });
  206. // 将下拉框和删除按钮加入到 selectWrapper 中
  207. selectWrapper.appendChild(select);
  208. selectWrapper.appendChild(removeSelectBtn);
  209. // 将 selectWrapper 加入到 userInputs 容器中
  210. userInputs.appendChild(selectWrapper);
  211. // 初始更新其他下拉框
  212. updateSelectOptions();
  213. });
  214. // 点击下半部分的确认按钮
  215. const userConfirmBtn = document.getElementById('distributeUser-confirm-btn');
  216. userConfirmBtn.addEventListener('click', () => {
  217. // 收集用户信息,收集每个下拉框选中的值及其额外数据
  218. const selectedUsers = Array.from(document.querySelectorAll('.distributeUser-select'))
  219. .map(select => {
  220. if (select.value) {
  221. const selectedUserInfo = {
  222. uniqueID: select.value,
  223. username: select.options[select.selectedIndex].getAttribute('data-username'),
  224. account: select.options[select.selectedIndex].getAttribute('data-account')
  225. };
  226. return selectedUserInfo; // 返回用户的所有信息
  227. }
  228. })
  229. .filter(user => user !== undefined); // 过滤掉未选择的空值
  230. // 分别提取 uniqueID, username 和 account 数组
  231. const uniqueIDArray = selectedUsers.map(user => user.uniqueID);
  232. const usernameArray = selectedUsers.map(user => user.username);
  233. const accountArray = selectedUsers.map(user => user.account);
  234. console.log("Unique IDs: ", uniqueIDArray);
  235. console.log("Usernames: ", usernameArray);
  236. console.log("Accounts: ", accountArray);
  237. // 执行用户分发逻辑,传递用户详细信息到 distributeLicense
  238. distributeUser(item, uniqueIDArray, usernameArray, accountArray);
  239. closeDistributeModal(); // 关闭模态框
  240. });
  241. }
  242. // 关闭分发模态框的函数
  243. function closeDistributeModal() {
  244. const modal = document.getElementById('DistributeModal');
  245. modal.style.display = 'none'; // 隐藏模态框
  246. // 清空邮箱和用户输入区域
  247. const emailInputs = document.getElementById('DistributeModal-email-inputs');
  248. emailInputs.innerHTML = ''; // 清空动态生成的邮箱输入框
  249. const userInputs = document.getElementById('DistributeModal-user-inputs');
  250. userInputs.innerHTML = ''; // 清空动态生成的用户选择框
  251. }
  252. function distributeEmails(item, emails, usersInfo) {
  253. console.log('分发 distributeEmails', { item, emails, usersInfo });
  254. // 将 emails 数组转为以逗号分隔的字符串
  255. const emailsString = emails.join(',');
  256. // 从 usersInfo 中获取 currentUserInfo
  257. //const currentUserInfo = usersInfo.find(user => user.role === 'currentUser'); // 假设 currentUser 标识当前用户
  258. if (!currentUserInfo) {
  259. console.error('无法获取当前用户信息');
  260. return;
  261. }
  262. // 构建要发送的数据
  263. const postData = {
  264. emails: emailsString,
  265. LicenseUniqueID: item.UniqueID, // item 中的 UniqueID
  266. Oa_request_id: item.oa_request_id, // item 中的 oa_request_id
  267. OperatorUniqueID: currentUserInfo.UniqueID // currentUserInfo 中的 UniqueID
  268. };
  269. console.log('即将发送的数据:', postData);
  270. showLoadingModal("正在分发邮箱中...");
  271. // 发送 POST 请求到 DistributeLicenseToEmail 接口
  272. fetch(`http://${serverIP}:${serverPort}/api/admin/DistributeLicenseToEmail`, {
  273. method: 'POST',
  274. headers: {
  275. 'Authorization': `Bearer ${authToken}`, // 使用 authToken
  276. 'Content-Type': 'application/json'
  277. },
  278. body: JSON.stringify(postData) // 将数据转为 JSON 格式
  279. })
  280. .then(response => {
  281. if (!response.ok) {
  282. hideLoadingModal();
  283. throw new Error('Network response was not ok');
  284. }
  285. return response.json();
  286. })
  287. .then(data => {
  288. // 处理成功响应
  289. hideLoadingModal();
  290. console.log('邮件分发成功:', data);
  291. alert('邮件分发成功');
  292. })
  293. .catch(error => {
  294. // 处理错误
  295. hideLoadingModal();
  296. console.error('分发邮件失败:', error);
  297. alert('分发邮件失败:', error);
  298. });
  299. }
  300. // 执行分发的逻辑
  301. function distributeUser(item, uniqueIDArray, usernameArray, accountArray) {
  302. // 构建要发送的数据对象
  303. const postData = {
  304. Oa_request_id: item.oa_request_id,
  305. LicenseUniqueID: item.UniqueID,
  306. OperatorUniqueID: currentUserInfo.UniqueID, // currentUserInfo 中的 UniqueID
  307. UserUniqueIDs: uniqueIDArray,
  308. UserNames: usernameArray,
  309. UserAccounts: accountArray
  310. };
  311. console.log('Sending user data:', postData);
  312. showLoadingModal("正在分发用户中...");
  313. // 发送 POST 请求到 DistributeLicenseToUser 接口
  314. fetch(`http://${serverIP}:${serverPort}/api/admin/DistributeLicenseToUser`, {
  315. method: 'POST',
  316. headers: {
  317. 'Content-Type': 'application/json',
  318. 'Authorization': `Bearer ${authToken}` // 使用适当的 authToken
  319. },
  320. body: JSON.stringify(postData) // 将数据转换为 JSON 字符串发送
  321. })
  322. .then(response => {
  323. hideLoadingModal(); // 隐藏 loading 模态框
  324. if (!response.ok) {
  325. // 返回错误信息作为 Promise,以便 catch 块捕获
  326. return response.json().then(errorData => {
  327. // 检查服务器是否返回了特定的错误信息并抛出错误
  328. const errorMessage = errorData.error || '网络响应不正确';
  329. throw new Error(errorMessage);
  330. });
  331. }
  332. return response.json();
  333. })
  334. .then(data => {
  335. console.log('分发成功:', data);
  336. alert('分发成功!');
  337. })
  338. .catch(error => {
  339. hideLoadingModal(); // 在失败时隐藏 loading 模态框
  340. console.error('分发失败:', error.message); // 打印具体的错误信息
  341. alert('分发失败: ' + error.message); // 将错误信息展示给用户
  342. });
  343. }
  344. //--------------分发历史模态框------------------------
  345. // function showDistributionHistory(selectedRowData) {
  346. // fetch('http://${serverIP}:${serverPort}/api/admin/GetlicenseRecord', {
  347. // method: 'POST',
  348. // headers: {
  349. // 'Authorization': `Bearer ${authToken}`,
  350. // 'Content-Type': 'application/json'
  351. // },
  352. // body: JSON.stringify({ uniqueID: selectedRowData.UniqueID, oa_request_id: selectedRowData.oa_request_id })
  353. // })
  354. // .then(response => response.json())
  355. // .then(data => {
  356. // const userDistributionContent = document.getElementById('distributionHistory-user-content');
  357. // const emailDistributionContent = document.getElementById('distributionHistory-email-content');
  358. // // 检查 license_record_to_user 是否是数组,如果不是则默认为空数组
  359. // const userRecords = Array.isArray(data?.data?.license_record_to_user) ? data.data.license_record_to_user : [];
  360. // // 如果 license_record_to_emails 是 null,则设置为空数组
  361. // const emailRecords = Array.isArray(data?.data?.license_record_to_emails) ? data.data.license_record_to_emails : [];
  362. // // 显示用户分发记录
  363. // userDistributionContent.innerHTML = userRecords.length > 0
  364. // ? userRecords.map(record => `<p>已转发给用户: ${record.user_account} 时间: ${formatDateTime(record.up_time)}</p>`).join('')
  365. // : '<p>没有用户分发记录。</p>';
  366. // // 显示邮箱分发记录
  367. // emailDistributionContent.innerHTML = emailRecords.length > 0
  368. // ? emailRecords.map(record => `<p>已发给邮箱: ${record.emails} 时间: ${formatDateTime(record.up_time)}</p>`).join('')
  369. // : '<p>没有邮箱分发记录。</p>';
  370. // // 显示模态框
  371. // document.getElementById('distributionHistory-modal').style.display = 'block';
  372. // })
  373. // .catch(error => {
  374. // console.error('Error fetching distribution history:', error);
  375. // });
  376. // // 关闭模态框 (点击关闭按钮)
  377. // document.querySelector('.distributionHistory-modal-close').addEventListener('click', () => {
  378. // document.getElementById('distributionHistory-modal').style.display = 'none';
  379. // });
  380. // // 点击模态框外部关闭模态框
  381. // window.addEventListener('click', function(event) {
  382. // const modal = document.getElementById('distributionHistory-modal');
  383. // if (event.target === modal) { // 检查点击的是否是模态框背景
  384. // modal.style.display = 'none'; // 关闭模态框
  385. // }
  386. // });
  387. // }
  388. function showDistributionHistory(selectedRowData) {
  389. fetch(`http://${serverIP}:${serverPort}/api/admin/GetlicenseRecord`, {
  390. method: 'POST',
  391. headers: {
  392. 'Authorization': `Bearer ${authToken}`,
  393. 'Content-Type': 'application/json'
  394. },
  395. body: JSON.stringify({ uniqueID: selectedRowData.UniqueID, oa_request_id: selectedRowData.oa_request_id })
  396. })
  397. .then(response => response.json())
  398. .then(data => {
  399. console.log("showDistributionHistory", data);
  400. // 提取用户记录和邮箱记录
  401. const userRecords = data.data.license_record_to_user || [];
  402. const emailRecords = data.data.license_record_to_emails || [];
  403. // 按时间排序,最新的记录在前
  404. userRecords.sort((a, b) => new Date(b.up_time) - new Date(a.up_time));
  405. emailRecords.sort((a, b) => new Date(b.up_time) - new Date(a.up_time));
  406. // 分组函数
  407. function groupBy(records, key) {
  408. return records.reduce((result, record) => {
  409. const date = new Date(record.up_time).toLocaleDateString();
  410. if (!result[date]) {
  411. result[date] = [];
  412. }
  413. result[date].push(record);
  414. return result;
  415. }, {});
  416. }
  417. // 分组用户记录和邮箱记录
  418. const groupedUserRecords = groupBy(userRecords, 'up_time');
  419. const groupedEmailRecords = groupBy(emailRecords, 'up_time');
  420. // 动态生成用户记录的 HTML
  421. const userContent = Object.keys(groupedUserRecords).length > 0 ?
  422. Object.keys(groupedUserRecords).map(date => {
  423. const records = groupedUserRecords[date];
  424. const recordContent = records.map(user => `
  425. <div class="distributionHistoryModal-record">
  426. <div>用户名: ${user.user_account}</div>
  427. </div>
  428. `).join('');
  429. return `
  430. <div class="distributionHistoryModal-group">
  431. <div class="distributionHistoryModal-group-title">${date}</div>
  432. ${recordContent}
  433. </div>
  434. `;
  435. }).join('') :
  436. '<div class="distributionHistoryModal-no-record">没有用户分发记录</div>';
  437. // 动态生成邮箱记录的 HTML
  438. const emailContent = Object.keys(groupedEmailRecords).length > 0 ?
  439. Object.keys(groupedEmailRecords).map(date => {
  440. const records = groupedEmailRecords[date];
  441. const recordContent = records.map(email => `
  442. <div class="distributionHistoryModal-record">
  443. <div>邮箱: ${email.emails}</div>
  444. </div>
  445. `).join('');
  446. return `
  447. <div class="distributionHistoryModal-group">
  448. <div class="distributionHistoryModal-group-title">${date}</div>
  449. ${recordContent}
  450. </div>
  451. `;
  452. }).join('') :
  453. '<div class="distributionHistoryModal-no-record">没有邮箱分发记录</div>';
  454. // 将内容插入到模态框中的对应 div
  455. document.getElementById('distributionHistory-user-content').innerHTML = userContent;
  456. document.getElementById('distributionHistory-email-content').innerHTML = emailContent;
  457. // 显示模态框
  458. document.getElementById('distributionHistory-modal').style.display = 'block';
  459. })
  460. .catch(error => {
  461. console.error('Error fetching distribution history:', error);
  462. });
  463. // 关闭模态框 (点击关闭按钮)
  464. document.querySelector('.distributionHistory-modal-close').addEventListener('click', () => {
  465. document.getElementById('distributionHistory-modal').style.display = 'none';
  466. });
  467. // 点击模态框外部关闭模态框
  468. window.addEventListener('click', function(event) {
  469. const modal = document.getElementById('distributionHistory-modal');
  470. if (event.target === modal) {
  471. modal.style.display = 'none';
  472. }
  473. });
  474. }
  475. function formatDateTime(dateString) {
  476. const date = new Date(dateString);
  477. // 获取 UTC 时间
  478. const year = date.getUTCFullYear();
  479. const month = String(date.getUTCMonth() + 1).padStart(2, '0'); // 月份从0开始,所以+1
  480. const day = String(date.getUTCDate()).padStart(2, '0');
  481. const hours = String(date.getUTCHours()).padStart(2, '0');
  482. const minutes = String(date.getUTCMinutes()).padStart(2, '0');
  483. const seconds = String(date.getUTCSeconds()).padStart(2, '0');
  484. // 返回格式化后的字符串,格式为 YYYY-MM-DD HH:mm:ss
  485. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  486. }