Merge branch 'PingChuan' into shiy-login

This commit is contained in:
2025-12-08 17:31:41 +08:00
9 changed files with 367 additions and 75 deletions
+4
View File
@@ -1,6 +1,10 @@
/**
* GET /api/v3/dify/area-datasets - 获取所有知识库绑定列表(管理员)
* POST /api/v3/dify/area-datasets - 创建知识库绑定
*
* 权限说明:
* GET: @require_permission_v2("dify:dataset:manage")
* POST: @require_permission_v2("dify:dataset:manage")
*/
import { type LoaderFunctionArgs, json } from '@remix-run/node';
+12 -14
View File
@@ -3,22 +3,19 @@
* 路由: /contract-draft/:draftId
*/
import type { LoaderFunctionArgs, MetaFunction, ActionFunctionArgs } from '@remix-run/node';
import { redirect } from '@remix-run/node';
import { useLoaderData, useNavigate, useFetcher } from '@remix-run/react';
import { useState, useRef, useEffect } from 'react';
import { FilePreview, type FilePreviewHandle } from '~/components/reviews/FilePreview';
import { PlaceholderForm } from '~/components/contracts/PlaceholderForm';
import { getDraftById, deleteDraft } from '~/api/contracts/draft-service.server';
import type { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction } from '@remix-run/node';
import { useFetcher, useLoaderData, useNavigate } from '@remix-run/react';
import { useEffect, useRef, useState } from 'react';
import { downloadFile } from '~/api/axios-client';
import type { ContractTemplate } from '~/api/contract-template/templates';
import { extractPlaceholdersFromDocx, generateDefaultSchema } from '~/api/contracts/docx-parser.server';
import { getUserSession } from '~/api/login/auth.server';
import { deleteFile } from '~/api/storage/minio-client';
import { toastService } from '~/components/ui/Toast';
import { PlaceholderForm } from '~/components/contracts/PlaceholderForm';
import { FilePreview, type FilePreviewHandle } from '~/components/reviews/FilePreview';
import { messageService } from '~/components/ui/MessageModal';
import { downloadFile } from '~/api/axios-client';
import { extractPlaceholdersFromDocx, generateDefaultSchema } from '~/api/contracts/docx-parser.server';
import path from 'path';
import { toastService } from '~/components/ui/Toast';
import type { DraftedContract, PlaceholderSchema } from '~/types/contract-draft';
import type { ContractTemplate } from '~/api/contract-template/templates';
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return [
@@ -301,10 +298,11 @@ export default function ContractDraftPage() {
// 设置高亮值,触发 FilePreview 中的高亮
setHighlightValue(placeholder);
// 短暂延迟清除高亮,以便下次点击可以重新触发
// 延迟清除高亮,给焦点夺回机制充足的时间
// PlaceholderForm 会在 150ms 后夺回焦点,所以这里延迟 250ms 清除
setTimeout(() => {
setHighlightValue(undefined);
}, 100);
}, 250);
};
// 导出文档(下载当前编辑的文件)- 不再需要手动保存
+40 -9
View File
@@ -945,10 +945,18 @@ export default function RolePermissions() {
}
};
// ==================== 权限状态管理 ====================
// 存储原始的、未映射的权限(用于保存时)
const [originalRoutePermissionsMap, setOriginalRoutePermissionsMap] = useState<Map<number, ApiPermission[]>>(new Map());
const [originalAllPermissions, setOriginalAllPermissions] = useState<ApiPermission[]>([]);
// 选择角色
const handleSelectRole = async (role: RoleInfo) => {
setSelectedRole(role);
// 动态导入权限映射工具
const { mapPermissions } = await import('~/utils/permission-mapper');
// v3.0: 并行加载数据
const [routesResult, rolePermissions, users] = await Promise.all([
getRoleRoutesWithPermissions(role.id),
@@ -958,26 +966,49 @@ export default function RolePermissions() {
const { routes: routesWithPerms, selectedRouteIds: routeIds } = routesResult;
// 构建 routePermissionsMap:从返回的路由中提取每个路由的可用 permissions
const permMap = new Map<number, ApiPermission[]>();
const extractPermissions = (routes: RouteInfo[]) => {
// 构建原始权限映射(未映射的,用于保存)
const originalPermMap = new Map<number, ApiPermission[]>();
// 存储所有原始权限的列表
const allOriginalPerms: ApiPermission[] = [];
const extractOriginalPermissions = (routes: RouteInfo[]) => {
routes.forEach(route => {
if (route.permissions && route.permissions.length > 0) {
permMap.set(route.id, route.permissions);
originalPermMap.set(route.id, route.permissions);
allOriginalPerms.push(...route.permissions);
}
if (route.children) {
extractPermissions(route.children);
extractOriginalPermissions(route.children);
}
});
};
extractPermissions(routesWithPerms);
extractOriginalPermissions(routesWithPerms);
// 从 getRolePermissions 结果中提取已分配的权限ID
// 存储原始权限
setOriginalRoutePermissionsMap(originalPermMap);
setOriginalAllPermissions(allOriginalPerms);
// 构建映射后的权限映射(用于显示)
const displayPermMap = new Map<number, ApiPermission[]>();
const extractDisplayPermissions = (routes: RouteInfo[]) => {
routes.forEach(route => {
if (route.permissions && route.permissions.length > 0) {
const mappedPermissions = mapPermissions(route.permissions);
displayPermMap.set(route.id, mappedPermissions);
}
if (route.children) {
extractDisplayPermissions(route.children);
}
});
};
extractDisplayPermissions(routesWithPerms);
// 从 getRolePermissions 结果中提取已分配的权限ID(原始ID)
const assignedPermissionIds = rolePermissions.map(p => p.permission_id);
setRoutePermissionsMap(permMap);
// 存储状态
setRoutePermissionsMap(displayPermMap); // 用于显示
setSelectedRouteIds(routeIds);
setSelectedPermissionIds(assignedPermissionIds); // 使用实际已分配的权限ID
setSelectedPermissionIds(assignedPermissionIds); // 使用原始权限ID
setExpandedRouteIds([]); // 重置展开状态
setRoleUsers(users);
};