创建评查点分组的API文件
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { json, type MetaFunction } from "@remix-run/node";
|
||||
import { useLoaderData, Link, useNavigate, useSearchParams } from "@remix-run/react";
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import indexStyles from "~/styles/pages/rule-groups_index.css?url";
|
||||
import { Card } from "~/components/ui/Card";
|
||||
import { Button } from "~/components/ui/Button";
|
||||
@@ -8,23 +8,12 @@ import { StatusDot } from "~/components/ui/StatusDot";
|
||||
import { Table } from "~/components/ui/Table";
|
||||
import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel";
|
||||
import { Pagination } from "~/components/ui/Pagination";
|
||||
import { getRuleGroups, getChildGroups, type RuleGroup } from "~/api/evaluation_points/rule-groups";
|
||||
|
||||
export function links() {
|
||||
return [{ rel: "stylesheet", href: indexStyles }];
|
||||
}
|
||||
|
||||
// 定义数据类型
|
||||
interface RuleGroup {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
ruleCount: number;
|
||||
subGroupCount: number;
|
||||
status: 'active' | 'inactive';
|
||||
createdAt: string;
|
||||
children?: RuleGroup[];
|
||||
}
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
{ title: "评查点分组 - 中国烟草AI合同及卷宗审核系统" },
|
||||
@@ -32,98 +21,85 @@ export const meta: MetaFunction = () => {
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
// 模拟数据
|
||||
const MOCK_GROUPS: RuleGroup[] = [
|
||||
{
|
||||
id: "1",
|
||||
name: "合同基本要素检查",
|
||||
code: "contract-base",
|
||||
ruleCount: 18,
|
||||
subGroupCount: 12,
|
||||
status: "active",
|
||||
createdAt: "2023-10-01 14:30",
|
||||
children: [
|
||||
{
|
||||
id: "2",
|
||||
name: "必备要素检查",
|
||||
code: "essential-elements",
|
||||
ruleCount: 7,
|
||||
subGroupCount: 0,
|
||||
status: "active",
|
||||
createdAt: "2023-10-02 10:15",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "合同主体检查",
|
||||
code: "contract-parties",
|
||||
ruleCount: 5,
|
||||
subGroupCount: 0,
|
||||
status: "active",
|
||||
createdAt: "2023-10-03 16:20",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "销售合同专项检查",
|
||||
code: "contract-sales",
|
||||
ruleCount: 12,
|
||||
subGroupCount: 5,
|
||||
status: "active",
|
||||
createdAt: "2023-10-05 09:30",
|
||||
children: [
|
||||
{
|
||||
id: "6",
|
||||
name: "付款条件检查",
|
||||
code: "payment-terms",
|
||||
ruleCount: 5,
|
||||
subGroupCount: 0,
|
||||
status: "active",
|
||||
createdAt: "2023-10-05 14:45",
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "行政处罚规范性检查",
|
||||
code: "punishment",
|
||||
ruleCount: 8,
|
||||
subGroupCount: 0,
|
||||
status: "inactive",
|
||||
createdAt: "2023-10-08 11:45",
|
||||
}
|
||||
];
|
||||
|
||||
export async function loader() {
|
||||
return json({ groups: MOCK_GROUPS });
|
||||
try {
|
||||
const response = await getRuleGroups();
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
return json({ groups: response.data });
|
||||
} catch (error) {
|
||||
console.error('加载评查点分组失败:', error);
|
||||
return json({ groups: [] });
|
||||
}
|
||||
}
|
||||
|
||||
export default function RuleGroupsIndex() {
|
||||
const { groups } = useLoaderData<typeof loader>();
|
||||
const { groups: initialGroups } = useLoaderData<typeof loader>();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [expandedGroups, setExpandedGroups] = useState<string[]>([]);
|
||||
const [groups, setGroups] = useState<RuleGroup[]>(initialGroups);
|
||||
const [loading, setLoading] = useState<Record<string, boolean>>({});
|
||||
|
||||
// 处理展开/收起
|
||||
const toggleGroup = (groupId: string) => {
|
||||
setExpandedGroups(prev =>
|
||||
prev.includes(groupId)
|
||||
? prev.filter(id => id !== groupId)
|
||||
: [...prev, groupId]
|
||||
);
|
||||
const toggleGroup = async (groupId: string) => {
|
||||
if (expandedGroups.includes(groupId)) {
|
||||
// 收起分组
|
||||
setExpandedGroups(prev => prev.filter(id => id !== groupId));
|
||||
return;
|
||||
}
|
||||
|
||||
// 展开分组
|
||||
setLoading(prev => ({ ...prev, [groupId]: true }));
|
||||
try {
|
||||
const response = await getChildGroups(groupId);
|
||||
if (response.error) {
|
||||
throw new Error(response.error);
|
||||
}
|
||||
|
||||
// 更新分组数据
|
||||
setGroups(prev => prev.map(group => {
|
||||
if (group.id === groupId) {
|
||||
return {
|
||||
...group,
|
||||
children: response.data
|
||||
};
|
||||
}
|
||||
return group;
|
||||
}));
|
||||
|
||||
setExpandedGroups(prev => [...prev, groupId]);
|
||||
} catch (error) {
|
||||
console.error('加载子分组失败:', error);
|
||||
} finally {
|
||||
setLoading(prev => ({ ...prev, [groupId]: false }));
|
||||
}
|
||||
};
|
||||
|
||||
// 展开/收起全部
|
||||
const toggleAll = (expand: boolean) => {
|
||||
setExpandedGroups(expand ? groups.map(g => g.id) : []);
|
||||
const toggleAll = async (expand: boolean) => {
|
||||
if (expand) {
|
||||
// 展开所有分组
|
||||
const expandedIds = groups.map(g => g.id);
|
||||
setExpandedGroups(expandedIds);
|
||||
|
||||
// 加载所有子分组
|
||||
for (const group of groups) {
|
||||
if (!group.children || group.children.length === 0) {
|
||||
await toggleGroup(group.id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setExpandedGroups([]);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理删除分组
|
||||
const handleDeleteGroup = (groupId: string) => {
|
||||
if (confirm("确定要删除该分组吗?此操作将同时删除该分组下的所有评查点,且不可恢复。")) {
|
||||
console.log('删除分组ID:', groupId);
|
||||
// 实际应用中,这里会调用API删除数据
|
||||
// TODO: 实现删除分组的API调用
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,7 +168,7 @@ export default function RuleGroupsIndex() {
|
||||
title: "分组名称",
|
||||
key: "name",
|
||||
width: "400px",
|
||||
render: (_: unknown, record: (RuleGroup & { isParent?: boolean, parentId?: string })) => (
|
||||
render: (_: unknown, record: RuleGroup & { isParent?: boolean, parentId?: string }) => (
|
||||
<div className={`flex items-center ${!record.isParent ? 'ml-8' : ''}`}>
|
||||
{record.isParent && (
|
||||
<span
|
||||
@@ -207,7 +183,11 @@ export default function RuleGroupsIndex() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<i className={`ri-arrow-${expandedGroups.includes(record.id) ? 'down' : 'right'}-s-line`}></i>
|
||||
{loading[record.id] ? (
|
||||
<i className="ri-loader-4-line animate-spin"></i>
|
||||
) : (
|
||||
<i className={`ri-arrow-${expandedGroups.includes(record.id) ? 'down' : 'right'}-s-line`}></i>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
<Link
|
||||
@@ -231,23 +211,20 @@ export default function RuleGroupsIndex() {
|
||||
title: "评查点数量",
|
||||
key: "ruleCount",
|
||||
render: (_: unknown, record: RuleGroup) => (
|
||||
<>
|
||||
<Link to={`/rule-groups/${record.id}/rules`} className="badge bg-primary text-white">
|
||||
{record.ruleCount}
|
||||
</Link>
|
||||
{record.subGroupCount > 0 && (
|
||||
<span className="text-secondary text-sm ml-1">
|
||||
| 子分组: {record.subGroupCount}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
<Link to={`/rule-groups/${record.id}/rules`} className="badge bg-primary text-white">
|
||||
{record.ruleCount || 0}
|
||||
</Link>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
key: "status",
|
||||
render: (_: unknown, record: RuleGroup) => (
|
||||
<StatusDot status={record.status === 'active' ? 'success' : 'error'} text={record.status === 'active' ? '启用' : '禁用'} />
|
||||
<StatusDot
|
||||
status={record.status ? 'success' : 'error'}
|
||||
text={record.status ? '启用' : '禁用'}
|
||||
align="left"
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
@@ -349,8 +326,8 @@ export default function RuleGroupsIndex() {
|
||||
name="status"
|
||||
value={searchParams.get('status') || ''}
|
||||
options={[
|
||||
{ value: "active", label: "启用" },
|
||||
{ value: "inactive", label: "禁用" }
|
||||
{ value: "true", label: "启用" },
|
||||
{ value: "false", label: "禁用" }
|
||||
]}
|
||||
onChange={handleStatusChange}
|
||||
className="flex-1 min-w-[200px]"
|
||||
|
||||
@@ -430,7 +430,6 @@ export default function RulesIndex() {
|
||||
key: "isActive",
|
||||
align: "left" as const,
|
||||
width: "8%",
|
||||
className: "status-column",
|
||||
render: (_: unknown, record: Rule) => (
|
||||
<StatusDot status={record.isActive} text={record.isActive ? "启用" : "禁用"} />
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user