zhizhi/docs/js/approval-ui.js

231 lines
6.4 KiB
JavaScript
Raw Permalink Normal View History

/**
* 部署授权 UI · Phase 8
*
* 授权人在交互页面收到授权请求推送时展示授权弹窗
* 授权人必须主动点击确认不回应视为不通过
* 系统绝不自动跳过授权步骤
*
* 版权国作登字-2026-A-00037559
*/
/* global HOLOLAKE_ENV */
(function(window) {
'use strict';
var API_BASE = (typeof HOLOLAKE_ENV !== 'undefined' && HOLOLAKE_ENV === 'production')
? 'https://guanghulab.com/api' : '';
/**
* ApprovalUI 构造函数
*/
function ApprovalUI() {
this._pollTimer = null;
this._container = null;
}
/**
* 初始化开始轮询待授权请求
* @param {string} devId - 当前登录的开发者编号
* @param {string} token - 认证 token
*/
ApprovalUI.prototype.init = function(devId, token) {
this.devId = devId;
this.token = token;
this._ensureContainer();
this._startPolling();
};
/**
* 确保授权容器存在
*/
ApprovalUI.prototype._ensureContainer = function() {
if (this._container) return;
this._container = document.createElement('div');
this._container.id = 'approval-container';
this._container.className = 'approval-container';
document.body.appendChild(this._container);
};
/**
* 开始轮询待授权请求 30
*/
ApprovalUI.prototype._startPolling = function() {
var self = this;
if (!API_BASE) return;
var poll = function() {
self._fetchPendingApprovals();
};
poll();
this._pollTimer = setInterval(poll, 30000);
};
/**
* 停止轮询
*/
ApprovalUI.prototype.destroy = function() {
if (this._pollTimer) {
clearInterval(this._pollTimer);
this._pollTimer = null;
}
};
/**
* 获取待处理的授权请求
*/
ApprovalUI.prototype._fetchPendingApprovals = function() {
var self = this;
if (!API_BASE) return;
fetch(API_BASE + '/approval', {
headers: {
'x-dev-id': this.devId,
'Authorization': 'Bearer ' + this.token
}
})
.then(function(res) { return res.json(); })
.then(function(data) {
if (data.success && data.pending && data.pending.length > 0) {
self._showApprovalBadge(data.pending.length);
self._renderPendingList(data.pending);
} else {
self._hideApprovalBadge();
}
})
.catch(function() { /* 静默失败 */ });
};
/**
* 显示授权提醒徽章
*/
ApprovalUI.prototype._showApprovalBadge = function(count) {
var badge = document.getElementById('approval-badge');
if (!badge) {
badge = document.createElement('div');
badge.id = 'approval-badge';
badge.className = 'approval-badge';
document.body.appendChild(badge);
}
badge.textContent = '🔔 ' + count + ' 个待授权';
badge.style.display = 'block';
var self = this;
badge.onclick = function() { self._togglePanel(); };
};
/**
* 隐藏授权徽章
*/
ApprovalUI.prototype._hideApprovalBadge = function() {
var badge = document.getElementById('approval-badge');
if (badge) badge.style.display = 'none';
if (this._container) this._container.style.display = 'none';
};
/**
* 切换授权面板显示
*/
ApprovalUI.prototype._togglePanel = function() {
if (this._container) {
this._container.style.display =
this._container.style.display === 'none' ? 'block' : 'none';
}
};
/**
* 渲染待授权列表
*/
ApprovalUI.prototype._renderPendingList = function(pending) {
if (!this._container) return;
var html = '<div class="approval-panel">' +
'<div class="approval-panel-header">' +
'<span>📋 待授权请求</span>' +
'<button class="approval-close-btn" id="approval-close">×</button>' +
'</div>' +
'<div class="approval-panel-body">';
for (var i = 0; i < pending.length; i++) {
var item = pending[i];
html += '<div class="approval-item" data-id="' + item.id + '">' +
'<div class="approval-item-info">' +
'<strong>' + item.module + '</strong>' +
'<span class="approval-channel">' + item.channel + '</span>' +
'<span class="approval-time">' + new Date(item.createdAt).toLocaleString('zh-CN') + '</span>' +
'</div>' +
'<div class="approval-item-actions">' +
'<button class="approval-btn approve" data-id="' + item.id + '" data-action="approved">✅ 授权通过</button>' +
'<button class="approval-btn reject" data-id="' + item.id + '" data-action="rejected">❌ 拒绝</button>' +
'</div></div>';
}
html += '</div></div>';
this._container.innerHTML = html;
this._container.style.display = 'block';
// 绑定事件
var self = this;
var closeBtn = document.getElementById('approval-close');
if (closeBtn) {
closeBtn.onclick = function() { self._container.style.display = 'none'; };
}
var buttons = this._container.querySelectorAll('.approval-btn');
for (var j = 0; j < buttons.length; j++) {
buttons[j].addEventListener('click', function() {
var approvalId = this.getAttribute('data-id');
var action = this.getAttribute('data-action');
self._submitDecision(approvalId, action);
});
}
};
/**
* 提交授权决定
*/
ApprovalUI.prototype._submitDecision = function(approvalId, decision) {
var self = this;
if (!API_BASE) return;
fetch(API_BASE + '/approval/' + approvalId + '/decide', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-dev-id': this.devId,
'Authorization': 'Bearer ' + this.token
},
body: JSON.stringify({ decision: decision })
})
.then(function(res) { return res.json(); })
.then(function(data) {
if (data.reply) {
self._showNotification(data.reply);
}
// 刷新列表
self._fetchPendingApprovals();
})
.catch(function(err) {
self._showNotification('❌ 操作失败:' + err.message);
});
};
/**
* 显示通知消息
*/
ApprovalUI.prototype._showNotification = function(message) {
var notif = document.createElement('div');
notif.className = 'approval-notification';
notif.textContent = message;
document.body.appendChild(notif);
setTimeout(function() {
notif.classList.add('fade-out');
setTimeout(function() { notif.remove(); }, 500);
}, 4000);
};
// 导出到全局
window.ApprovalUI = ApprovalUI;
})(window);