Merge branch 'Wren' into shiy-login
This commit is contained in:
+27
-1
@@ -81,6 +81,7 @@ axiosInstance.interceptors.request.use(
|
||||
(config) => {
|
||||
// 检查是否在白名单中
|
||||
if (isInAuthWhitelist(config.url)) {
|
||||
console.log('🔓 [Request Interceptor] URL在白名单中,跳过Authorization:', config.url);
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -89,12 +90,24 @@ axiosInstance.interceptors.request.use(
|
||||
const token = localStorage.getItem('access_token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
console.log('🔑 [Request Interceptor] 添加Authorization头:', {
|
||||
url: config.url,
|
||||
method: config.method,
|
||||
hasToken: !!token,
|
||||
tokenPreview: token.substring(0, 20) + '...'
|
||||
});
|
||||
} else {
|
||||
console.warn('⚠️ [Request Interceptor] 没有找到access_token:', {
|
||||
url: config.url,
|
||||
localStorage: Object.keys(localStorage)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
console.error('❌ [Request Interceptor] 请求拦截器错误:', error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
@@ -114,9 +127,21 @@ export class AuthenticationError extends Error {
|
||||
*/
|
||||
axiosInstance.interceptors.response.use(
|
||||
(response) => {
|
||||
console.log('✅ [Response Interceptor] 请求成功:', {
|
||||
url: response.config.url,
|
||||
status: response.status,
|
||||
statusText: response.statusText
|
||||
});
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
console.error('❌ [Response Interceptor] 请求失败:', {
|
||||
url: error.config?.url,
|
||||
status: error.response?.status,
|
||||
statusText: error.response?.statusText,
|
||||
data: error.response?.data
|
||||
});
|
||||
|
||||
if (isAxiosError(error) && error.response?.status === 401) {
|
||||
// 检查是否在错误容忍白名单中
|
||||
const requestUrl = error.config?.url;
|
||||
@@ -442,7 +467,8 @@ export async function apiRequest<T>(
|
||||
|
||||
// 检查API返回的状态码
|
||||
const data = response.data;
|
||||
if (data && typeof data === 'object' && 'code' in data && data.code !== 0) {
|
||||
// 修复:支持code=0(PostgREST)和code=200(RBAC API)两种成功响应
|
||||
if (data && typeof data === 'object' && 'code' in data && data.code !== 0 && data.code !== 200) {
|
||||
const errorMessage = data.message || data.msg || '未知错误';
|
||||
console.error(`API请求失败: ${errorMessage} - ${url}`);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -505,6 +505,230 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================== 表单样式 ==================== */
|
||||
|
||||
.role-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-group label.required::after {
|
||||
content: ' *';
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-textarea,
|
||||
.form-select {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-textarea:focus,
|
||||
.form-select:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-primary);
|
||||
box-shadow: 0 0 0 2px rgba(0, 104, 74, 0.1);
|
||||
}
|
||||
|
||||
.form-input.error,
|
||||
.form-textarea.error,
|
||||
.form-select.error {
|
||||
border-color: var(--color-error);
|
||||
}
|
||||
|
||||
.form-input:disabled,
|
||||
.form-textarea:disabled,
|
||||
.form-select:disabled {
|
||||
background: #f5f7fa;
|
||||
cursor: not-allowed;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
font-size: 12px;
|
||||
color: var(--color-error);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.form-notice {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
background: #ecf5ff;
|
||||
border: 1px solid #b3d8ff;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.form-notice.warning {
|
||||
background: #fef0f0;
|
||||
border-color: #fbc4c4;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.form-notice i {
|
||||
font-size: 18px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.form-notice.warning i {
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
/* 分配用户模态框 */
|
||||
.assign-user-modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* 全选栏 */
|
||||
.select-all-bar {
|
||||
padding: 12px 16px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e4e7ed;
|
||||
}
|
||||
|
||||
.select-all-bar .user-checkbox-item {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.select-all-bar .user-checkbox-item:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.select-all-bar .user-name {
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 用户复选框列表 */
|
||||
.users-checkbox-list {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.user-checkbox-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.user-checkbox-item:hover {
|
||||
background: #e6e8eb;
|
||||
}
|
||||
|
||||
.user-checkbox-item input[type="checkbox"] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
cursor: pointer;
|
||||
accent-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.user-checkbox-item .user-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.user-checkbox-item .user-name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.user-checkbox-item .user-meta {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 搜索框 */
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 6px;
|
||||
background: white;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.search-box i {
|
||||
font-size: 18px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
flex: 1;
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.search-box input::placeholder {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
/* 无权限卡片 */
|
||||
.no-permission-card {
|
||||
max-width: 800px;
|
||||
margin: 60px auto;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.no-permission-card .empty-state {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-permission-card h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.no-permission-card p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ==================== 响应式布局 ==================== */
|
||||
|
||||
/* 响应式布局 */
|
||||
@media (max-width: 1200px) {
|
||||
.permissions-container {
|
||||
|
||||
Reference in New Issue
Block a user