数据列表查询对接完成

This commit is contained in:
2025-05-30 18:20:19 +08:00
parent d292dcfccf
commit c169d718c5
6 changed files with 215 additions and 58 deletions
+63 -17
View File
@@ -25,7 +25,7 @@ export const meta: MetaFunction = () => {
// 将数据库模板转换为前端显示格式
function transformTemplate(template: ContractTemplate) {
// 模拟使用次数和评分(实际项目中可以从其他表获取)
const mockUsageCount = Math.floor(Math.random() * 2000) + 100;
/* const mockUsageCount = Math.floor(Math.random() * 2000) + 100;
const mockRating = (Math.random() * 1.5 + 3.5).toFixed(1);
// 根据模板属性确定类型
@@ -36,17 +36,24 @@ function transformTemplate(template: ContractTemplate) {
templateType = '简化版';
} else if (template.description && (template.description.includes('专业') || template.description.includes('大客户'))) {
templateType = '专业版';
}
} */
// 添加调试信息
console.log('原始模板数据:', template);
console.log('file_path:', template.file_path);
console.log('file_format:', template.file_format);
return {
id: template.id.toString(),
title: template.title,
type: templateType,
// type: templateType,
description: template.description || '',
updateTime: new Date(template.updated_at).toLocaleDateString('zh-CN'),
useCount: mockUsageCount,
rating: parseFloat(mockRating),
category: template.category?.name || '其他'
// useCount: mockUsageCount,
// rating: parseFloat(mockRating),
category: template.category?.name || '其他',
file_path: template.file_path,
file_format: template.file_format
};
}
@@ -55,16 +62,45 @@ export async function loader({ request }: LoaderFunctionArgs) {
const category = url.searchParams.get('category') || '';
const category_id = url.searchParams.get('category_id') || '';
const type = url.searchParams.get('type') || '';
const sortBy = url.searchParams.get('sortBy') || 'relevance';
const page = parseInt(url.searchParams.get('page') || '1');
const pageSize = 6;
try {
// 根据sortBy值设置数据库排序参数
let dbSortBy = 'id';
let dbSortOrder: 'asc' | 'desc' = 'asc';
switch (sortBy) {
case 'relevance':
dbSortBy = 'id';
dbSortOrder = 'asc';
break;
case 'newest':
dbSortBy = 'updated_at';
dbSortOrder = 'desc';
break;
/* case 'popular':
// 暂时按创建时间排序,后续可以加入使用频率字段
dbSortBy = 'created_at';
dbSortOrder = 'desc';
break;
case 'rating':
// 暂时按特色推荐排序,后续可以加入评分字段
dbSortBy = 'is_featured';
dbSortOrder = 'desc';
break; */
default:
dbSortBy = 'id';
dbSortOrder = 'asc';
}
// 构建搜索参数
const searchParams: TemplateSearchParams = {
page,
pageSize,
sortBy: 'updated_at',
sortOrder: 'desc'
sortBy: dbSortBy,
sortOrder: dbSortOrder
};
// 优先使用category_id,其次使用category名称
@@ -91,6 +127,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
category,
category_id,
type,
sortBy,
categories: []
};
}
@@ -99,12 +136,12 @@ export async function loader({ request }: LoaderFunctionArgs) {
const categories: ContractCategoryWithCount[] = categoriesResponse.error ? [] : categoriesResponse.data || [];
// 转换模板数据格式
let transformedTemplates = templatesResponse.data?.templates.map(transformTemplate) || [];
const transformedTemplates = templatesResponse.data?.templates.map(transformTemplate) || [];
// 如果有类型筛选,在前端进行筛选(因为数据库中没有type字段
if (type) {
// 注释掉类型筛选,因为数据库中没有type字段且已隐藏该功能
/* if (type) {
transformedTemplates = transformedTemplates.filter(t => t.type === type);
}
} */
// 获取当前分类信息(用于显示)
let currentCategory = '全部';
@@ -123,6 +160,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
category: currentCategory,
category_id,
type,
sortBy,
categories
};
} catch (error) {
@@ -135,18 +173,18 @@ export async function loader({ request }: LoaderFunctionArgs) {
category,
category_id,
type,
sortBy,
categories: []
};
}
}
export default function ContractTemplateList() {
const { templates, total, page, pageSize, category, category_id, categories } = useLoaderData<typeof loader>();
const { templates, total, page, pageSize, category, category_id, categories, sortBy } = 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');
// 监听category变化,同步更新activeFilter状态
useEffect(() => {
@@ -186,6 +224,13 @@ export default function ContractTemplateList() {
navigate(`/contract-template/list?${params.toString()}`);
};
const handleSortChange = (newSort: string) => {
const params = new URLSearchParams(searchParams);
params.set('sortBy', newSort);
params.delete('page'); // 重置页码
navigate(`/contract-template/list?${params.toString()}`);
};
// 动态生成筛选选项
// 计算所有分类的总模板数量
const totalAllTemplates = categories.reduce((sum, cat) => sum + (cat.template_count || 0), 0);
@@ -235,11 +280,12 @@ export default function ContractTemplateList() {
<select
className="px-3 py-3 border border-gray-200 rounded-lg text-sm"
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
onChange={(e) => handleSortChange(e.target.value)}
>
<option value="relevance"></option>
<option value="newest"></option>
<option value="popular">使</option>
<option value="rating"></option>
{/* <option value="popular">使用频率</option>
<option value="rating">评分最高</option> */}
</select>
</div>
</div>
+55 -14
View File
@@ -38,29 +38,33 @@ interface CategoryWithSearchCount extends ContractCategory {
interface DisplayTemplate {
id: string;
title: string;
type: string;
// type: string;
description: string;
updateTime: string;
useCount: number;
rating: number;
// useCount: number;
// rating: number;
category: string;
file_path?: string;
file_format?: string;
}
// 将数据库模板转换为前端显示格式
function transformTemplate(template: ContractTemplate) {
// 模拟使用次数和评分(实际项目中可以从其他表获取)
const mockUsageCount = Math.floor(Math.random() * 2000) + 100;
const mockRating = (Math.random() * 1.5 + 3.5).toFixed(1);
/* const mockUsageCount = Math.floor(Math.random() * 2000) + 100;
const mockRating = (Math.random() * 1.5 + 3.5).toFixed(1); */
return {
id: template.id.toString(),
title: template.title,
type: template.is_featured ? '推荐版' : '标准版',
// type: template.is_featured ? '推荐版' : '标准版',
description: template.description || '',
updateTime: new Date(template.updated_at).toLocaleDateString('zh-CN'),
useCount: mockUsageCount,
rating: parseFloat(mockRating),
category: template.category?.name || '其他'
// useCount: mockUsageCount,
// rating: parseFloat(mockRating),
category: template.category?.name || '其他',
file_path: template.file_path,
file_format: template.file_format
};
}
@@ -68,11 +72,38 @@ export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const query = url.searchParams.get('q') || '';
const category = url.searchParams.get('category') || '';
const sortBy = url.searchParams.get('sortBy') || 'relevance';
const page = parseInt(url.searchParams.get('page') || '1');
const pageSize = 6;
// 记录搜索开始时间
const startTime = Date.now();
// 根据sortBy值设置数据库排序参数
let dbSortBy = 'id';
let dbSortOrder: 'asc' | 'desc' = 'asc';
switch (sortBy) {
case 'relevance':
dbSortBy = 'id';
dbSortOrder = 'asc';
break;
case 'newest':
dbSortBy = 'updated_at';
dbSortOrder = 'desc';
break;
/* case 'popular':
dbSortBy = 'created_at';
dbSortOrder = 'desc';
break;
case 'rating':
dbSortBy = 'is_featured';
dbSortOrder = 'desc';
break; */
default:
dbSortBy = 'id';
dbSortOrder = 'asc';
}
try {
// 并行获取搜索结果和分类数据
@@ -81,8 +112,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
category,
page,
pageSize,
sortBy: 'updated_at',
sortOrder: 'desc'
sortBy: dbSortBy,
sortOrder: dbSortOrder
}),
getContractCategories()
]);
@@ -97,6 +128,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
total: 0,
page,
pageSize,
sortBy,
searchTime: '搜索失败',
categories: []
};
@@ -155,6 +187,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
total: searchResponse.data?.total || 0,
page,
pageSize,
sortBy,
searchTime: searchTimeText,
categories: categoriesWithSearchCount
};
@@ -167,6 +200,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
total: 0,
page,
pageSize,
sortBy,
searchTime: '搜索失败',
categories: []
};
@@ -174,12 +208,13 @@ export async function loader({ request }: LoaderFunctionArgs) {
}
export default function ContractTemplateSearchResults() {
const { results, query, total, page, pageSize, searchTime, categories }: {
const { results, query, total, page, pageSize, sortBy, searchTime, categories }: {
results: DisplayTemplate[];
query: string;
total: number;
page: number;
pageSize: number;
sortBy: string;
searchTime: string;
categories: CategoryWithSearchCount[];
} = useLoaderData<typeof loader>();
@@ -188,7 +223,6 @@ export default function ContractTemplateSearchResults() {
const navigate = useNavigate();
const [activeFilter, setActiveFilter] = useState('全部');
const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
const [sortBy, setSortBy] = useState('relevance');
const handleSearch = (newQuery: string) => {
if (newQuery.trim()) {
@@ -220,6 +254,13 @@ export default function ContractTemplateSearchResults() {
navigate(`/contract-template/search/results?${params.toString()}`);
};
const handleSortChange = (newSort: string) => {
const params = new URLSearchParams(searchParams);
params.set('sortBy', newSort);
params.delete('page'); // 重置页码
navigate(`/contract-template/search/results?${params.toString()}`);
};
// 动态生成筛选选项
const filters = [
{ label: '全部', count: total },
@@ -246,7 +287,7 @@ export default function ContractTemplateSearchResults() {
viewMode={viewMode}
onViewModeChange={setViewMode}
sortBy={sortBy}
onSortChange={setSortBy}
onSortChange={handleSortChange}
/>
{/* 筛选标签 */}