import { json, type MetaFunction, type LoaderFunctionArgs, type ActionFunctionArgs } from "@remix-run/node"; import { useLoaderData, useSearchParams, useSubmit, Link } from "@remix-run/react"; import { useState } from "react"; import { Button } from "~/components/ui/Button"; import { Card } from "~/components/ui/Card"; import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel"; import { Pagination } from "~/components/ui/Pagination"; import { Table } from "~/components/ui/Table"; import { Tag } from "~/components/ui/Tag"; import { getConfigLists, getConfigOptions, updateConfigStatus, type ConfigItem } from "~/api/system_setting/config-lists"; import configListsStyles from "~/styles/pages/config-lists_index.css?url"; export const links = () => [ { rel: "stylesheet", href: configListsStyles } ]; export const meta: MetaFunction = () => { return [ { title: "系统配置管理 - 中国烟草AI合同及卷宗审核系统" }, { name: "description", content: "管理系统配置,包括数据库、文件存储、AI引擎等配置项" }, { name: "keywords", content: "系统配置,配置管理,中国烟草,参数设置" } ]; }; // 配置环境枚举 export enum ConfigEnvironment { DEV = 'dev', TEST = 'test', PROD = 'prod' } // 配置模块枚举 export enum ConfigModule { SYSTEM = 'system', AUTH = 'auth', FILE = 'file', AI = 'ai', NOTIFICATION = 'notification' } // 环境标签映射 export const ENVIRONMENT_LABELS: Record = { [ConfigEnvironment.DEV]: '开发环境', [ConfigEnvironment.TEST]: '测试环境', [ConfigEnvironment.PROD]: '生产环境' }; // 模块标签映射 export const MODULE_LABELS: Record = { [ConfigModule.SYSTEM]: '系统', [ConfigModule.AUTH]: '认证', [ConfigModule.FILE]: '文件', [ConfigModule.AI]: 'AI配置', [ConfigModule.NOTIFICATION]: '通知' }; interface LoaderData { configs: ConfigItem[]; totalCount: number; currentPage: number; pageSize: number; totalPages: number; types: string[]; environments: string[]; } export async function loader({ request }: LoaderFunctionArgs) { const url = new URL(request.url); const name = url.searchParams.get("name") || ""; const type = url.searchParams.get("type") || ""; const environment = url.searchParams.get("environment") || ""; const is_active = url.searchParams.get("is_active") ? url.searchParams.get("is_active") === "true" : undefined; const currentPage = parseInt(url.searchParams.get("page") || "1", 10); const pageSize = parseInt(url.searchParams.get("pageSize") || "10", 10); try { // 获取配置列表 const configsResponse = await getConfigLists({ name, type, environment, is_active, page: currentPage, pageSize }); if (configsResponse.error || !configsResponse.data) { throw new Error(configsResponse.error || "获取配置列表失败"); } // 获取配置选项 const optionsResponse = await getConfigOptions(); if (optionsResponse.error || !optionsResponse.data) { throw new Error(optionsResponse.error || "获取配置选项失败"); } return json({ configs: configsResponse.data, totalCount: configsResponse.total, currentPage, pageSize, totalPages: Math.ceil(configsResponse.total / pageSize), types: optionsResponse.data.types, environments: optionsResponse.data.environments }, { headers: { "Cache-Control": "max-age=60, s-maxage=180" } }); } catch (error) { console.error('加载配置列表失败:', error); throw new Response('加载配置列表失败', { status: 500 }); } } export async function action({ request }: ActionFunctionArgs) { const formData = await request.formData(); const _action = formData.get('_action'); const configId = formData.get('configId'); if (!configId) { return json({ success: false, error: "缺少配置ID" }, { status: 400 }); } // 进行更新启用和禁用的状态 try { if (_action === 'toggleStatus') { const is_active = formData.get('is_active') === 'true'; const response = await updateConfigStatus(parseInt(configId as string), is_active); if (!response.success) { return json({ success: false, error: response.error }, { status: 500 }); } return json({ success: true }); } return json({ success: false, error: "未知操作" }, { status: 400 }); } catch (error) { console.error('操作配置失败:', error); return json({ success: false, error: "操作失败" }, { status: 500 }); } } export function ErrorBoundary() { return (

出错了

加载配置列表时发生错误。请稍后再试,或联系管理员。

); } export default function ConfigListsIndex() { const { configs, totalCount, currentPage, pageSize, types, environments } = useLoaderData(); const [searchParams, setSearchParams] = useSearchParams(); const submit = useSubmit(); const [showDetailModal, setShowDetailModal] = useState(false); const [selectedConfig, setSelectedConfig] = useState(null); 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 handleConfigNameSearch = (value: string) => { const newParams = new URLSearchParams(searchParams); if (value) { newParams.set('name', value); } else { newParams.delete('name'); } // 搜索时,重置到第一页 newParams.set('page', '1'); setSearchParams(newParams); }; const handleToggleStatus = (config: ConfigItem) => { if (window.confirm(`确定要${config.is_active ? '禁用' : '启用'}该配置吗?`)) { const formData = new FormData(); formData.append('_action', 'toggleStatus'); formData.append('configId', config.id.toString()); formData.append('is_active', String(!config.is_active)); submit(formData, { method: 'post' }); } }; const handleViewDetail = (config: ConfigItem) => { setSelectedConfig(config); setShowDetailModal(true); }; 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 handleReset = () => { const nameInput = document.querySelector('input[placeholder="请输入配置名称"]') as HTMLInputElement; const typeSelect = document.querySelector('select[name="type"]') as HTMLInputElement; const environmentSelect = document.querySelector('select[name="environment"]') as HTMLInputElement; const statusSelect = document.querySelector('select[name="is_active"]') as HTMLInputElement; setSearchParams(new URLSearchParams()); if(nameInput) nameInput.value = '' if(typeSelect) typeSelect.value = '' if(environmentSelect) environmentSelect.value = '' if(statusSelect) statusSelect.value = '' }; // 关闭详情模态框 const closeDetailModal = () => { setShowDetailModal(false); setSelectedConfig(null); }; // 定义表格列配置 const columns = [ { title: "配置名称", dataIndex: "name" as keyof ConfigItem, key: "name", width: "20%" }, { title: "所属模块", key: "type", width: "10%", render: (_: unknown, record: ConfigItem) => record.type }, { title: "环境", key: "environment", width: "15%", render: (_: unknown, record: ConfigItem) => { return ( {record.environment} ); } }, { title: "状态", key: "is_active", width: "15%", render: (_: unknown, record: ConfigItem) => ( {record.is_active ? '已启用' : '已禁用'} ) }, { title: "最后更新时间", dataIndex: "updated_at" as keyof ConfigItem, key: "updated_at", width: "15%" }, { title: "操作", key: "operation", width: "25%", render: (_: unknown, record: ConfigItem) => (
编辑
) } ]; return (
{/* 页面头部 */}

系统配置管理

{/* 搜索区域 */} {/* */} } noActionDivider={true} > ({ value: type, label: type }))]} onChange={handleFilterChange} className="flex-1 min-w-[200px]" /> ({ value: env, label: env }))]} onChange={handleFilterChange} className="flex-1 min-w-[200px]" /> {/* 表格区域 */} {/* 分页区域 */} {totalCount > 0 && ( )} {/* 配置详情模态框 */} {showDetailModal && selectedConfig && (

查看配置详情

配置名称
{selectedConfig.name}
所属模块
{selectedConfig.type}
环境
{selectedConfig.environment}
状态
{selectedConfig.is_active ? '已启用' : '已禁用'}
配置数据
                  {JSON.stringify(selectedConfig.config, null, 2)}
                
创建时间
{selectedConfig.created_at}
更新时间
{selectedConfig.updated_at}
)} ); }