fix: 1. 接入入口模块的管理接口,优化样式。

2. 将查看文档评查结果详情对接接口,采用接口的方式进行查询。
This commit is contained in:
2025-11-26 23:37:14 +08:00
parent ae24b82384
commit d5827a2146
13 changed files with 563 additions and 673 deletions
+41 -29
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef } from "react";
import { useNavigate, useSearchParams, useLoaderData } from "@remix-run/react";
import { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
import { ClientLoaderFunctionArgs, MetaFunction } from "@remix-run/react";
import { Card } from "~/components/ui/Card";
import { Button } from "~/components/ui/Button";
import { toastService } from "~/components/ui/Toast";
@@ -9,9 +9,18 @@ import {
getEntryModuleById,
createEntryModule,
updateEntryModule,
type EntryModule
type EntryModule,
type AreaConfig
} from "~/api/entry-modules/entry-modules";
import { API_BASE_URL, DOCUMENT_URL } from "~/config/api-config";
import entryModulesStyles from "~/styles/pages/entry-modules.css?url";
// 引入CSS样式
export function links() {
return [
{ rel: "stylesheet", href: entryModulesStyles }
];
}
// 页面元数据
export const meta: MetaFunction = () => {
@@ -33,38 +42,31 @@ export const handle = {
interface LoaderData {
module?: EntryModule;
error?: string;
frontendJWT?: string | null;
}
// 加载函数 - 获取入口模块数据(编辑模式)
export async function loader({ request }: LoaderFunctionArgs) {
// 🔑 客户端加载函数 - 在浏览器端执行,axios-client 会自动添加 JWT
export async function clientLoader({ request }: ClientLoaderFunctionArgs) {
try {
const { getUserSession } = await import("~/api/login/auth.server");
const { frontendJWT } = await getUserSession(request);
const url = new URL(request.url);
const id = url.searchParams.get('id');
if (id) {
const moduleResponse = await getEntryModuleById(parseInt(id), frontendJWT);
// ✅ 不需要传递 JWTaxios-client 会自动处理
const moduleResponse = await getEntryModuleById(parseInt(id));
if (moduleResponse.error) {
throw new Error(moduleResponse.error);
}
return Response.json({
module: moduleResponse.data,
frontendJWT
});
return {
module: moduleResponse.data
};
}
return Response.json({ frontendJWT });
return {};
} catch (error) {
console.error("加载入口模块失败:", error);
return Response.json(
{
error: error || "加载入口模块失败",
status: 500
}
);
return {
error: error instanceof Error ? error.message : "加载入口模块失败"
};
}
}
@@ -81,7 +83,7 @@ const AREA_OPTIONS = [
export default function EntryModuleNew() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { module, error, frontendJWT } = useLoaderData<LoaderData>();
const { module, error } = useLoaderData<LoaderData>();
const id = searchParams.get('id');
const isEditMode = !!id;
@@ -89,7 +91,10 @@ export default function EntryModuleNew() {
// 表单状态
const [name, setName] = useState(module?.name || '');
const [description, setDescription] = useState(module?.description || '');
const [selectedAreas, setSelectedAreas] = useState<string[]>(module?.areas || []);
// 🔑 从 AreaConfig[] 提取地区名称数组
const [selectedAreas, setSelectedAreas] = useState<string[]>(
module?.areas ? module.areas.map(a => a.area) : []
);
const [logoFile, setLogoFile] = useState<File | null>(null);
const [logoPreview, setLogoPreview] = useState<string | null>(
module?.path ? `${DOCUMENT_URL}${module.path}` : null
@@ -168,10 +173,14 @@ export default function EntryModuleNew() {
formData.append('file', logoFile);
formData.append('folder', 'entryModule');
// ✅ 不需要手动添加 Authorization 头
// fetch 可以自动使用浏览器的认证信息,或者我们也可以使用 axios
const token = localStorage.getItem('access_token');
const response = await fetch(`${API_BASE_URL}/admin/upload`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${frontendJWT}`
'Authorization': `Bearer ${token}`
},
body: formData
});
@@ -210,18 +219,21 @@ export default function EntryModuleNew() {
logoPath = await uploadLogo();
}
// 🔑 准备提交数据
// areas 字段会在 API 层自动转换为 AreaConfig[] 格式
const moduleData = {
name: name.trim(),
description: description.trim() || undefined,
path: logoPath,
areas: selectedAreas
areas: selectedAreas // 字符串数组,API会自动转换
};
// ✅ 不需要传递 JWTaxios-client 会自动处理
let result;
if (isEditMode) {
result = await updateEntryModule(parseInt(id!), moduleData, frontendJWT);
result = await updateEntryModule(parseInt(id!), moduleData);
} else {
result = await createEntryModule(moduleData, frontendJWT);
result = await createEntryModule(moduleData);
}
if (result.error) {
@@ -280,7 +292,7 @@ export default function EntryModuleNew() {
onChange={(e) => setName(e.target.value)}
placeholder="请输入模块名称,如:合同管理"
maxLength={255}
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
className="w-full px-3 py-2 border border-gray-300 rounded-md"
/>
</div>
@@ -291,7 +303,7 @@ export default function EntryModuleNew() {
value={description}
onChange={(e) => setDescription(e.target.value)}
placeholder="请输入模块描述"
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
className="w-full px-3 py-2 border border-gray-300 rounded-md"
rows={4}
/>
</div>
@@ -349,7 +361,7 @@ export default function EntryModuleNew() {
type="checkbox"
checked={selectedAreas.includes(option.value)}
onChange={() => handleAreaToggle(option.value)}
className="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
className="w-4 h-4 border-gray-300 rounded cursor-pointer"
/>
<span className="text-sm text-gray-700">{option.label}</span>
</label>