feat: 1. 本地化思源黑体的字体包并优先使用。
2. 添加权限映射表和全局查看权限的hook,便于路由控制不同权限按钮显示/隐藏。 3. 删除评查点分组的部分旧api方法。 4. 对接评查点分组接口,文档类型接口, 提示词管理接口, 入口模块管理的接口。 5. 优化角色权限管理的接口,完善不用地区的访问权限认证。 6. 优化主页交叉评查和设置的入口样式和布局。 7. 优化评查点分组,评查规则的功能权限校验。
This commit is contained in:
+82
-56
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate, Form, useLoaderData } from '@remix-run/react';
|
||||
import { type MetaFunction, type ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
|
||||
import styles from "~/styles/pages/home.css?url";
|
||||
@@ -52,6 +52,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
// 🔑 检查用户是否有系统设置权限
|
||||
let hasSettingsAccess = false;
|
||||
let hasCrossCheckingAccess = false;
|
||||
let hasChatLLMAccess = false;
|
||||
let settingsChildren: { path: string; title: string }[] = [];
|
||||
|
||||
if (userRole && frontendJWT) {
|
||||
@@ -74,14 +75,19 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
||||
|
||||
// 检查是否存在顶级路由 '/cross-checking'
|
||||
hasCrossCheckingAccess = routesResult.data.some(route => route.path === '/cross-checking');
|
||||
|
||||
// 检查是否存在顶级路由 '/chat-with-llm'
|
||||
hasChatLLMAccess = routesResult.data.some(route => route.path === '/chat-with-llm');
|
||||
|
||||
// console.log(`🔑 [Index Loader] 用户${hasSettingsAccess ? '有' : '没有'}系统设置权限`);
|
||||
// console.log(`🔑 [Index Loader] 系统设置子路由数量: ${settingsChildren.length}`);
|
||||
// console.log(`🔑 [Index Loader] 用户${hasCrossCheckingAccess ? '有' : '没有'}交叉评查权限`);
|
||||
// console.log(`🔑 [Index Loader] 用户${hasChatLLMAccess ? '有' : '没有'}智慧法务大模型权限`);
|
||||
}
|
||||
}
|
||||
|
||||
// 返回用户信息、入口模块和权限给客户端
|
||||
return Response.json({ userRole, userInfo, entryModules, hasSettingsAccess, hasCrossCheckingAccess, settingsChildren });
|
||||
return Response.json({ userRole, userInfo, entryModules, hasSettingsAccess, hasCrossCheckingAccess, hasChatLLMAccess, settingsChildren });
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
@@ -310,6 +316,17 @@ export default function Index() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="user-info">
|
||||
{/* 系统设置按钮 - 只在有权限时显示 */}
|
||||
{loaderData.hasSettingsAccess && (
|
||||
<button
|
||||
onClick={handleEnterSettings}
|
||||
className="settings-button"
|
||||
aria-label="系统设置"
|
||||
title="系统设置"
|
||||
>
|
||||
<i className="ri-settings-4-line"></i>
|
||||
</button>
|
||||
)}
|
||||
<span className="datetime">{currentDateTime.date} {currentDateTime.time}</span>
|
||||
<div className="user">
|
||||
{(() => {
|
||||
@@ -340,67 +357,76 @@ export default function Index() {
|
||||
<div className="index-main-content-container">
|
||||
<h1 className="welcome-text">- 欢迎来到智慧法务平台 -</h1>
|
||||
|
||||
{/* 模块网格区域 */}
|
||||
<div className="modules-container">
|
||||
{/* 动态渲染入口模块 */}
|
||||
{loaderData.entryModules && loaderData.entryModules.length > 0 ? (
|
||||
<>
|
||||
{loaderData.entryModules.map((module) => (
|
||||
<div
|
||||
key={module.id}
|
||||
className="module-card"
|
||||
onClick={() => handleModuleClick(module)}
|
||||
onKeyDown={(e) => handleKeyDown(module, e)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={module.name}
|
||||
>
|
||||
<img
|
||||
src={getModuleIcon(module)}
|
||||
alt={module.name}
|
||||
className="w-12 h-12 mx-1"
|
||||
/>
|
||||
<span className="module-name">{module.name}</span>
|
||||
</div>
|
||||
))}
|
||||
{loaderData.entryModules.map((module) => {
|
||||
// 判断是否为智慧法务大模型,如果是且有交叉评查权限,则在其之前插入交叉评查卡片
|
||||
const isLLMModule = module.name === '智慧法务大模型';
|
||||
|
||||
{/* 🔑 交叉评查入口 - 只有有权限的用户才能看到 */}
|
||||
{loaderData.hasCrossCheckingAccess && (
|
||||
<div
|
||||
className="module-card"
|
||||
onClick={handleEnterCrossChecking}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleEnterCrossChecking();
|
||||
}
|
||||
}}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label="交叉评查"
|
||||
>
|
||||
<i className="ri-shuffle-line text-5xl text-primary"></i>
|
||||
<span className="module-name">交叉评查</span>
|
||||
</div>
|
||||
)}
|
||||
// 🔑 如果是智慧法务大模型且用户没有访问权限,则不渲染该模块
|
||||
if (isLLMModule && !loaderData.hasChatLLMAccess) {
|
||||
return null;
|
||||
}
|
||||
|
||||
{/* 🔑 系统设置入口 - 只有有权限的用户才能看到 */}
|
||||
{loaderData.hasSettingsAccess && (
|
||||
<div
|
||||
className="module-card"
|
||||
onClick={handleEnterSettings}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleEnterSettings();
|
||||
}
|
||||
}}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label="系统设置"
|
||||
>
|
||||
<i className="ri-settings-4-line text-5xl text-primary"></i>
|
||||
<span className="module-name">系统设置</span>
|
||||
</div>
|
||||
)}
|
||||
return (
|
||||
<React.Fragment key={module.id}>
|
||||
{/* 在智慧法务大模型之前插入交叉评查入口 */}
|
||||
{isLLMModule && loaderData.hasCrossCheckingAccess && (
|
||||
<div
|
||||
className="module-card"
|
||||
onClick={handleEnterCrossChecking}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
handleEnterCrossChecking();
|
||||
}
|
||||
}}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label="交叉评查"
|
||||
>
|
||||
<img
|
||||
src="/images/icon_cross_checking.png"
|
||||
alt="交叉评查"
|
||||
className="w-12 h-12 mx-1"
|
||||
onError={(e) => {
|
||||
// 如果图片加载失败,使用 icon
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
const parent = (e.target as HTMLImageElement).parentElement;
|
||||
if (parent) {
|
||||
const icon = document.createElement('i');
|
||||
icon.className = 'ri-shuffle-line';
|
||||
icon.style.fontSize = '48px';
|
||||
icon.style.color = 'var(--color-primary)';
|
||||
parent.insertBefore(icon, parent.firstChild);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="module-name">交叉评查</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 渲染原有模块 */}
|
||||
<div
|
||||
className="module-card"
|
||||
onClick={() => handleModuleClick(module)}
|
||||
onKeyDown={(e) => handleKeyDown(module, e)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={module.name}
|
||||
>
|
||||
<img
|
||||
src={getModuleIcon(module)}
|
||||
alt={module.name}
|
||||
className="w-12 h-12 mx-1"
|
||||
/>
|
||||
<span className="module-name">{module.name}</span>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
) : (
|
||||
<div className="text-center text-gray-500 py-8">
|
||||
|
||||
Reference in New Issue
Block a user