import { useState, useEffect } from "react"; import { useSearchParams, useNavigate, useLoaderData, useRouteLoaderData } from "@remix-run/react"; import { ActionFunctionArgs, LoaderFunctionArgs, MetaFunction } from "@remix-run/node"; import { Table } from "~/components/ui/Table"; import { Card } from "~/components/ui/Card"; import { Button } from "~/components/ui/Button"; import { Pagination } from "~/components/ui/Pagination"; import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel"; import { toastService } from "~/components/ui/Toast"; import { getEntryModules, deleteEntryModule, type EntryModule, type EntryModuleSearchParams } from "~/api/entry-modules/entry-modules"; import entryModulesStyles from "~/styles/pages/entry-modules.css?url"; import { DOCUMENT_URL } from "~/config/api-config"; // 引入CSS样式 export function links() { return [ { rel: "stylesheet", href: entryModulesStyles } ]; } // 页面元数据 export const meta: MetaFunction = () => { return [ { title: "入口模块管理 - 中国烟草AI合同及卷宗审核系统" }, { name: "description", content: "管理入口模块,包括查看、编辑和删除入口模块" }, ]; }; // 面包屑配置 export const handle = { breadcrumb: "入口模块管理" }; // 定义加载器返回的数据类型 interface LoaderData { modules: EntryModule[]; total: number; pageSize: number; currentPage: number; error?: string; frontendJWT?: string | null; } // 加载函数 - 获取入口模块列表 export async function loader({ request }: LoaderFunctionArgs) { try { // 获取用户会话信息 const { getUserSession } = await import("~/api/login/auth.server"); const { frontendJWT } = await getUserSession(request); const url = new URL(request.url); const name = url.searchParams.get('name') || undefined; const area = url.searchParams.get('area') || undefined; const page = parseInt(url.searchParams.get('page') || '1', 10); const pageSize = parseInt(url.searchParams.get('pageSize') || '10', 10); // 构建搜索参数 const searchParams: EntryModuleSearchParams = { name, area, page, pageSize }; const modulesResponse = await getEntryModules(searchParams, frontendJWT); if (modulesResponse.error) { console.error("获取入口模块失败:", modulesResponse.error); throw new Error(modulesResponse.error); } const modulesResult = modulesResponse.data?.modules || []; return Response.json({ modules: modulesResult, total: modulesResponse.data?.total || modulesResult.length, pageSize, currentPage: page, frontendJWT }); } catch (error) { console.error("加载入口模块列表失败:", error); return Response.json( { modules: [], total: 0, pageSize: 10, currentPage: 1, error: error instanceof Error ? error.message : "加载入口模块列表失败" }, { status: 500 } ); } } // 动作函数 - 处理删除请求 export async function action({ request }: ActionFunctionArgs) { // 获取表单数据 const formData = await request.formData(); const id = formData.get("id") as string; const intent = formData.get("intent") as string; const { getUserSession } = await import("~/api/login/auth.server"); const { frontendJWT } = await getUserSession(request); if (intent === "delete" && id) { try { const result = await deleteEntryModule(parseInt(id), frontendJWT || undefined); if (result.error) { return Response.json({ success: false, error: result.error }, { status: 500 }); } return Response.json({ success: true }); } catch (error) { return Response.json( { success: false, error: error instanceof Error ? error.message : "删除入口模块失败" }, { status: 500 } ); } } return Response.json({ success: false, error: "无效的操作" }, { status: 400 }); } // 地区选项 const AREA_OPTIONS = [ { value: "", label: "全部地区" }, { value: "梅州", label: "梅州" }, { value: "云浮", label: "云浮" }, { value: "揭阳", label: "揭阳" }, { value: "潮州", label: "潮州" }, { value: "省局", label: "省局" } ]; // 入口模块列表组件 export default function EntryModulesList() { const navigate = useNavigate(); const [searchParams, setSearchParams] = useSearchParams(); const [isDeleting, setIsDeleting] = useState(false); // 获取加载器数据 const { modules, total, error, frontendJWT } = useLoaderData(); // 获取用户角色并判断权限 const rootData = useRouteLoaderData("root") as { userRole: string }; const userRole = rootData?.userRole || 'common'; const hasEditPermission = userRole.toLowerCase().includes('admin') || userRole.toLowerCase().includes('developer'); // 调试信息 useEffect(() => { console.log('📋 [EntryModules] 用户角色:', userRole); console.log('📋 [EntryModules] 是否有编辑权限:', hasEditPermission); }, [userRole, hasEditPermission]); // 获取搜索参数 const name = searchParams.get('name') || ''; const area = searchParams.get('area') || ''; const currentPage = parseInt(searchParams.get('page') || String(1), 10); const pageSize = parseInt(searchParams.get('pageSize') || String(10), 10); // 处理loader加载数据的时候的错误 useEffect(() => { if (error) { toastService.error(error); } }, [error]); // 处理名称搜索 const handleNameSearch = (value: string) => { const newParams = new URLSearchParams(searchParams); if (value) { newParams.set('name', value); } else { newParams.delete('name'); } newParams.set('page', '1'); setSearchParams(newParams); }; // 处理筛选变更 const handleFilterChange = (e: React.ChangeEvent) => { const { name, value } = e.target; const newParams = new URLSearchParams(searchParams); if (value) { newParams.set(name, value); } else { newParams.delete(name); } // 切换筛选条件时,重置到第一页 newParams.set('page', '1'); setSearchParams(newParams); }; // 处理重置筛选 const handleReset = () => { const nameInput = document.querySelector('input[placeholder="请输入入口模块名称"]'); if (nameInput) { (nameInput as HTMLInputElement).value = ''; } // 重置所有筛选条件 setSearchParams(new URLSearchParams()); }; // 处理删除入口模块 const handleDelete = async (id: number) => { if (confirm('确定要删除该入口模块吗?此操作不可撤销。')) { setIsDeleting(true); try { const formData = new FormData(); formData.append('id', id.toString()); formData.append('intent', 'delete'); const response = await fetch('/entry-modules', { method: 'POST', body: formData }); const result = await response.json(); if (result.success) { toastService.success('删除成功!'); // 刷新页面 window.location.reload(); } else { toastService.error(`删除失败: ${result.error || '未知错误'}`); } } catch (error) { toastService.error(`删除失败: ${error instanceof Error ? error.message : '未知错误'}`); } finally { setIsDeleting(false); } } }; // 处理编辑入口模块 const handleEdit = (id: number) => { navigate(`/entry-modules/new?id=${id}`); }; // 处理分页变更 const handlePageChange = (page: number) => { const newParams = new URLSearchParams(searchParams); newParams.set('page', page.toString()); setSearchParams(newParams); }; // 处理每页条数变更 const handlePageSizeChange = (size: number) => { const newParams = new URLSearchParams(searchParams); newParams.set('pageSize', size.toString()); newParams.set('page', '1'); setSearchParams(newParams); }; // 表格列定义 const columns = [ { key: 'id', title: 'ID', width: '80px', render: (row: EntryModule) => row.id }, { key: 'name', title: '模块名称', width: '200px', render: (row: EntryModule) => ( {row.name} ) }, { key: 'description', title: '描述', width: '250px', render: (row: EntryModule) => ( {row.description || '-'} ) }, { key: 'logo', title: 'Logo图片', width: '150px', render: (row: EntryModule) => { if (!row.path) { return 未上传; } const logoUrl = `${DOCUMENT_URL}${row.path}`; return (
{row.name} { (e.target as HTMLImageElement).style.display = 'none'; (e.target as HTMLImageElement).parentElement!.innerHTML = '加载失败'; }} /> 查看
); } }, { key: 'areas', title: '适用地区', width: '200px', render: (row: EntryModule) => (
{row.areas && row.areas.length > 0 ? ( row.areas.map((area, index) => ( {area} )) ) : ( 未设置 )}
) }, { key: 'created_at', title: '创建时间', width: '180px', render: (row: EntryModule) => row.created_at ? new Date(row.created_at).toLocaleString('zh-CN') : '-' }, { key: 'actions', title: '操作', width: '150px', render: (row: EntryModule) => (
) } ]; return (
{/* 页面头部 */}

入口模块管理

管理系统入口模块,包括Logo图片和适用地区设置

{hasEditPermission && ( )}
{/* 筛选面板 */} {/* 表格 */} {/* 分页 */} {total > 0 && ( )} ); }