Files
leaudit-platform-frontend/app/routes/contract-template.list._index.tsx
T
2025-05-29 17:42:35 +08:00

239 lines
6.9 KiB
TypeScript

import type { MetaFunction, LoaderFunctionArgs } from '@remix-run/node';
import { useLoaderData, useSearchParams, useNavigate } from '@remix-run/react';
import { useState } from 'react';
import { SearchResultHeader } from '~/components/contract-template/SearchResultHeader';
import { FilterTabs } from '~/components/contract-template/FilterTabs';
import { TemplateGrid } from '~/components/contract-template/TemplateGrid';
import { Pagination } from '~/components/ui/Pagination';
import styles from '~/styles/pages/contract-template.css?url';
export const links = () => [
{ rel: 'stylesheet', href: styles }
];
export const meta: MetaFunction = () => {
return [
{ title: '合同模板列表 - 智慧法务' },
{
name: 'description',
content: '浏览和管理所有合同模板,按分类查看各种类型的合同模板。'
}
];
};
// 模拟数据 - 完整的模板库
const mockTemplates = [
{
id: '1',
title: '烟草产品销售合同(2023版)',
type: '标准版',
description: '最新版本的烟草产品销售合同模板,包含完整的法律条款、风险控制措施和行业标准要求。',
updateTime: '2023-10-25',
useCount: 2156,
rating: 4.9,
category: '销售合同'
},
{
id: '2',
title: '零售商销售协议模板',
type: '标准版',
description: '专为零售商设计的销售协议,涵盖商品配送、结算方式、退换货政策等关键条款。',
updateTime: '2023-10-20',
useCount: 1834,
rating: 4.8,
category: '销售合同'
},
{
id: '3',
title: '大客户销售合同模板',
type: '专业版',
description: '适用于大客户的专业销售合同,包含定制化条款、特殊优惠政策和长期合作框架。',
updateTime: '2023-10-18',
useCount: 1245,
rating: 4.7,
category: '销售合同'
},
{
id: '4',
title: '小额销售合同(简化版)',
type: '简化版',
description: '适用于小额交易的简化版销售合同,条款精简但保证法律效力。',
updateTime: '2023-10-15',
useCount: 956,
rating: 4.6,
category: '销售合同'
},
{
id: '5',
title: '区域代理销售合同',
type: '标准版',
description: '区域代理商专用销售合同,明确代理权限、销售目标和考核标准。',
updateTime: '2023-10-12',
useCount: 743,
rating: 4.5,
category: '销售合同'
},
{
id: '6',
title: '批发销售合同模板',
type: '标准版',
description: '适用于大宗批发业务的销售合同,包含数量折扣、物流配送等专业条款。',
updateTime: '2023-10-10',
useCount: 612,
rating: 4.4,
category: '销售合同'
},
{
id: '7',
title: '设备采购合同标准模板',
type: '标准版',
description: '设备采购专用合同模板,包含详细的技术要求、验收标准、质保条款等内容。',
updateTime: '2023-10-08',
useCount: 589,
rating: 4.6,
category: '采购合同'
},
{
id: '8',
title: '服务类采购合同',
type: '标准版',
description: '适用于各类服务采购,包含服务标准、交付要求、考核指标等条款。',
updateTime: '2023-10-05',
useCount: 432,
rating: 4.5,
category: '采购合同'
}
];
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const category = url.searchParams.get('category') || '';
const type = url.searchParams.get('type') || '';
const page = parseInt(url.searchParams.get('page') || '1');
const pageSize = 6;
// 筛选模板
let filteredTemplates = mockTemplates;
if (category) {
filteredTemplates = filteredTemplates.filter(t => t.category === category);
}
if (type) {
filteredTemplates = filteredTemplates.filter(t => t.type === type);
}
const total = filteredTemplates.length;
const startIndex = (page - 1) * pageSize;
const templates = filteredTemplates.slice(startIndex, startIndex + pageSize);
return {
templates,
total,
page,
pageSize,
category,
type
};
}
export default function ContractTemplateList() {
const { templates, total, page, pageSize, category } = useLoaderData<typeof loader>();
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const [activeFilter, setActiveFilter] = useState(category || '全部');
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [sortBy, setSortBy] = useState('newest');
const handleTemplateClick = (templateId: string) => {
navigate(`/contract-template/detail/${templateId}`);
};
const handleFilterChange = (filter: string) => {
setActiveFilter(filter);
const params = new URLSearchParams(searchParams);
if (filter === '全部') {
params.delete('category');
} else {
params.set('category', filter);
}
params.delete('page'); // 重置页码
navigate(`/contract-template/list?${params.toString()}`);
};
const handlePageChange = (newPage: number) => {
const params = new URLSearchParams(searchParams);
params.set('page', newPage.toString());
navigate(`/contract-template/list?${params.toString()}`);
};
// 动态生成筛选选项
const allCategories = [...new Set(mockTemplates.map(t => t.category))];
const filters = [
{ label: '全部', count: mockTemplates.length },
...allCategories.map(cat => ({
label: cat,
count: mockTemplates.filter(t => t.category === cat).length
}))
];
const totalPages = Math.ceil(total / pageSize);
const currentCategory = category || '全部';
return (
<div className="contract-search-results">
{/* 页面头部 */}
<div className="result-header">
<div>
<h2 className="text-2xl font-semibold mb-2">
{currentCategory === '全部' ? '合同模板库' : `${currentCategory}模板`}
</h2>
<div className="result-info">
<span className="result-count">{total}</span>
</div>
</div>
<div className="flex items-center gap-4">
<SearchResultHeader
total={0}
viewMode={viewMode}
onViewModeChange={setViewMode}
sortBy={sortBy}
onSortChange={setSortBy}
/>
</div>
</div>
{/* 筛选标签 */}
<FilterTabs
filters={filters}
activeFilter={activeFilter}
onFilterChange={handleFilterChange}
/>
{/* 模板网格 */}
<TemplateGrid
templates={templates}
viewMode={viewMode}
onTemplateClick={handleTemplateClick}
/>
{/* 分页 */}
{totalPages > 1 && (
<Pagination
currentPage={page}
total={total}
pageSize={pageSize}
onChange={handlePageChange}
showPageSizeChanger={false}
/>
)}
</div>
);
}
// 面包屑导航配置
export const handle = {
breadcrumb: "合同列表"
};