refactor(search): 将搜索结果中的资料改为文章展示
- 替换 MaterialCard 为 ArticleCard 组件 - 更新 Tab 名称:资料 → 文章 - 更新数据字段:data.files → data.article - 映射 API 字段:post_title, post_excerpt, post_date, is_favorite - 同步更新 mock 数据使用 generateArticleItem Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Showing
3 changed files
with
131 additions
and
115 deletions
| ... | @@ -3,6 +3,71 @@ | ... | @@ -3,6 +3,71 @@ |
| 3 | 记录项目开发过程中的重要变更和完成任务。 | 3 | 记录项目开发过程中的重要变更和完成任务。 |
| 4 | 4 | ||
| 5 | ## 2026-02-28 | 5 | ## 2026-02-28 |
| 6 | +### 19:54:54 - docs | ||
| 7 | + | ||
| 8 | +- 更新搜索 API 响应字段:files → article | ||
| 9 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 10 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 11 | +- 计划书 API 完善参数文档说明 | ||
| 12 | + | ||
| 13 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>(api | ||
| 14 | + | ||
| 15 | +- 更新搜索 API 响应字段:files → article | ||
| 16 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 17 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 18 | +- 计划书 API 完善参数文档说明 | ||
| 19 | + | ||
| 20 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>): 同步搜索 API 文档,将 file 类型改为 article | ||
| 21 | + | ||
| 22 | +- 更新搜索 API 响应字段:files → article | ||
| 23 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 24 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 25 | +- 计划书 API 完善参数文档说明 | ||
| 26 | + | ||
| 27 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> | ||
| 28 | + | ||
| 29 | +**影响文件**: | ||
| 30 | +- `docs/api-specs/search/search.md` | ||
| 31 | +- `src/api/article.js` | ||
| 32 | +- `src/api/plan.js` | ||
| 33 | + | ||
| 34 | +**变更摘要**: | ||
| 35 | +- 同步搜索 API 文档,将 file 类型改为 article | ||
| 36 | + | ||
| 37 | +- 更新搜索 API 响应字段:files → article | ||
| 38 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 39 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 40 | +- 计划书 API 完善参数文档说明 | ||
| 41 | + | ||
| 42 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> | ||
| 43 | + | ||
| 44 | +**相关提交**: | ||
| 45 | +- `a4ef54a` - docs | ||
| 46 | + | ||
| 47 | +- 更新搜索 API 响应字段:files → article | ||
| 48 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 49 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 50 | +- 计划书 API 完善参数文档说明 | ||
| 51 | + | ||
| 52 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>(api | ||
| 53 | + | ||
| 54 | +- 更新搜索 API 响应字段:files → article | ||
| 55 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 56 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 57 | +- 计划书 API 完善参数文档说明 | ||
| 58 | + | ||
| 59 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>): 同步搜索 API 文档,将 file 类型改为 article | ||
| 60 | + | ||
| 61 | +- 更新搜索 API 响应字段:files → article | ||
| 62 | +- 字段名规范化:name/value/extension → post_title/post_excerpt/post_link | ||
| 63 | +- 文章详情 API 添加 file_list 字段类型定义 | ||
| 64 | +- 计划书 API 完善参数文档说明 | ||
| 65 | + | ||
| 66 | +Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> | ||
| 67 | + | ||
| 68 | +--- | ||
| 69 | + | ||
| 70 | + | ||
| 6 | ### 17:11:05 - fix | 71 | ### 17:11:05 - fix |
| 7 | 72 | ||
| 8 | - 删除 if/else 块外部的重复 mv 命令 | 73 | - 删除 if/else 块外部的重复 mv 命令 | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2026-02-08 | 2 | * @Date: 2026-02-08 |
| 3 | * @Description: 搜索页面 - 使用 LoadMoreList 组件重构版本 | 3 | * @Description: 搜索页面 - 使用 LoadMoreList 组件重构版本 |
| 4 | - * @description 支持产品和资料搜索,实时查询API,自动切换分类 | 4 | + * @description 支持产品和文章搜索,实时查询API,自动切换分类 |
| 5 | --> | 5 | --> |
| 6 | <template> | 6 | <template> |
| 7 | <view class="bg-[#FFF] search-page-container"> | 7 | <view class="bg-[#FFF] search-page-container"> |
| ... | @@ -27,7 +27,7 @@ | ... | @@ -27,7 +27,7 @@ |
| 27 | <view class="px-[40rpx] mt-[32rpx]"> | 27 | <view class="px-[40rpx] mt-[32rpx]"> |
| 28 | <SearchBar | 28 | <SearchBar |
| 29 | v-model="searchKeyword" | 29 | v-model="searchKeyword" |
| 30 | - placeholder="搜索培训资料、案例、产品..." | 30 | + placeholder="搜索文章、产品..." |
| 31 | variant="rounded" | 31 | variant="rounded" |
| 32 | :show-border="true" | 32 | :show-border="true" |
| 33 | :show-clear="true" | 33 | :show-clear="true" |
| ... | @@ -80,18 +80,18 @@ | ... | @@ -80,18 +80,18 @@ |
| 80 | )" | 80 | )" |
| 81 | /> | 81 | /> |
| 82 | 82 | ||
| 83 | - <!-- File Results --> | 83 | + <!-- Article Results --> |
| 84 | - <MaterialCard | 84 | + <ArticleCard |
| 85 | - v-else-if="activeTab === 'file'" | 85 | + v-else-if="activeTab === 'article'" |
| 86 | :id="item.id" | 86 | :id="item.id" |
| 87 | :title="item.title" | 87 | :title="item.title" |
| 88 | - :file-name="item.fileName" | 88 | + :excerpt="item.excerpt" |
| 89 | - :file-size="item.fileSize" | 89 | + :cover-url="item.coverUrl" |
| 90 | + :date="item.date" | ||
| 90 | :learners="item.learners" | 91 | :learners="item.learners" |
| 91 | :read-people-percent="item.readPeoplePercent" | 92 | :read-people-percent="item.readPeoplePercent" |
| 92 | :collected="item.collected" | 93 | :collected="item.collected" |
| 93 | - :extension="item.extension" | 94 | + :show-cover="!!item.coverUrl" |
| 94 | - :download-url="item.downloadUrl" | ||
| 95 | class="search-result-item" | 95 | class="search-result-item" |
| 96 | @collect-changed="handleCollectChanged(item, $event)" | 96 | @collect-changed="handleCollectChanged(item, $event)" |
| 97 | /> | 97 | /> |
| ... | @@ -102,7 +102,7 @@ | ... | @@ -102,7 +102,7 @@ |
| 102 | <!-- Initial State (从未搜索过) --> | 102 | <!-- Initial State (从未搜索过) --> |
| 103 | <view v-if="!hasSearched" class="flex flex-col items-center justify-center py-[120rpx]"> | 103 | <view v-if="!hasSearched" class="flex flex-col items-center justify-center py-[120rpx]"> |
| 104 | <IconFont name="search" class="text-gray-300 mb-[24rpx]" size="64" /> | 104 | <IconFont name="search" class="text-gray-300 mb-[24rpx]" size="64" /> |
| 105 | - <view class="text-[#6B7280] text-[28rpx]">搜索产品或资料</view> | 105 | + <view class="text-[#6B7280] text-[28rpx]">搜索产品或文章</view> |
| 106 | <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">输入关键词开始搜索,自动切换分类</view> | 106 | <view class="text-[#9CA3AF] text-[24rpx] mt-[12rpx]">输入关键词开始搜索,自动切换分类</view> |
| 107 | </view> | 107 | </view> |
| 108 | 108 | ||
| ... | @@ -136,7 +136,7 @@ import NavHeader from '@/components/navigation/NavHeader.vue' | ... | @@ -136,7 +136,7 @@ import NavHeader from '@/components/navigation/NavHeader.vue' |
| 136 | import IconFont from '@/components/icons/IconFont.vue' | 136 | import IconFont from '@/components/icons/IconFont.vue' |
| 137 | import SearchBar from '@/components/forms/SearchBar.vue' | 137 | import SearchBar from '@/components/forms/SearchBar.vue' |
| 138 | import ProductCard from '@/components/cards/ProductCard.vue' | 138 | import ProductCard from '@/components/cards/ProductCard.vue' |
| 139 | -import MaterialCard from '@/components/cards/MaterialCard.vue' | 139 | +import ArticleCard from '@/components/cards/ArticleCard.vue' |
| 140 | import PlanFormContainer from '@/components/plan/PlanFormContainer.vue' | 140 | import PlanFormContainer from '@/components/plan/PlanFormContainer.vue' |
| 141 | import { searchAPI } from '@/api/search' | 141 | import { searchAPI } from '@/api/search' |
| 142 | import { mockSearchAPI } from '@/utils/mockData' | 142 | import { mockSearchAPI } from '@/utils/mockData' |
| ... | @@ -169,7 +169,7 @@ onMounted(() => { | ... | @@ -169,7 +169,7 @@ onMounted(() => { |
| 169 | 169 | ||
| 170 | /** | 170 | /** |
| 171 | * 搜索页面状态管理 | 171 | * 搜索页面状态管理 |
| 172 | - * @description 支持双类型(产品/资料)搜索,自动切换分类 | 172 | + * @description 支持双类型(产品/文章)搜索,自动切换分类 |
| 173 | */ | 173 | */ |
| 174 | 174 | ||
| 175 | // Plan Popup State | 175 | // Plan Popup State |
| ... | @@ -183,9 +183,9 @@ const hasSearched = ref(false) // 是否已经搜索过 | ... | @@ -183,9 +183,9 @@ const hasSearched = ref(false) // 是否已经搜索过 |
| 183 | 183 | ||
| 184 | // 数据状态 - 双列表系统 | 184 | // 数据状态 - 双列表系统 |
| 185 | const products = ref([]) // 产品列表 | 185 | const products = ref([]) // 产品列表 |
| 186 | -const files = ref([]) // 资料列表 | 186 | +const articles = ref([]) // 文章列表 |
| 187 | const productsTotal = ref(0) // 产品总数 | 187 | const productsTotal = ref(0) // 产品总数 |
| 188 | -const filesTotal = ref(0) // 资料总数 | 188 | +const articlesTotal = ref(0) // 文章总数 |
| 189 | 189 | ||
| 190 | // 分页状态 | 190 | // 分页状态 |
| 191 | const loading = ref(false) // 首次加载状态 | 191 | const loading = ref(false) // 首次加载状态 |
| ... | @@ -195,11 +195,11 @@ const currentPage = ref(0) // 当前页码(从0开始) | ... | @@ -195,11 +195,11 @@ const currentPage = ref(0) // 当前页码(从0开始) |
| 195 | const pageSize = 20 // 每页数量 | 195 | const pageSize = 20 // 每页数量 |
| 196 | 196 | ||
| 197 | /** | 197 | /** |
| 198 | - * Tab 数据源(只保留产品和资料) | 198 | + * Tab 数据源(只保留产品和文章) |
| 199 | */ | 199 | */ |
| 200 | const tabsData = ref([ | 200 | const tabsData = ref([ |
| 201 | { id: 'product', name: '产品' }, | 201 | { id: 'product', name: '产品' }, |
| 202 | - { id: 'file', name: '资料' }, | 202 | + { id: 'article', name: '文章' }, |
| 203 | ]) | 203 | ]) |
| 204 | 204 | ||
| 205 | /** | 205 | /** |
| ... | @@ -213,7 +213,7 @@ const currentList = computed(() => { | ... | @@ -213,7 +213,7 @@ const currentList = computed(() => { |
| 213 | if (activeTab.value === 'product') { | 213 | if (activeTab.value === 'product') { |
| 214 | return products.value | 214 | return products.value |
| 215 | } else { | 215 | } else { |
| 216 | - return files.value | 216 | + return articles.value |
| 217 | } | 217 | } |
| 218 | }) | 218 | }) |
| 219 | 219 | ||
| ... | @@ -227,7 +227,7 @@ const currentTotal = computed(() => { | ... | @@ -227,7 +227,7 @@ const currentTotal = computed(() => { |
| 227 | if (activeTab.value === 'product') { | 227 | if (activeTab.value === 'product') { |
| 228 | return productsTotal.value | 228 | return productsTotal.value |
| 229 | } else { | 229 | } else { |
| 230 | - return filesTotal.value | 230 | + return articlesTotal.value |
| 231 | } | 231 | } |
| 232 | }) | 232 | }) |
| 233 | 233 | ||
| ... | @@ -244,7 +244,7 @@ const shouldEnableScrollLoad = computed(() => { | ... | @@ -244,7 +244,7 @@ const shouldEnableScrollLoad = computed(() => { |
| 244 | * 执行搜索 | 244 | * 执行搜索 |
| 245 | * | 245 | * |
| 246 | * @param {string} keyword - 搜索关键字 | 246 | * @param {string} keyword - 搜索关键字 |
| 247 | - * @param {string} type - 可选,'product' | 'file' | undefined | 247 | + * @param {string} type - 可选,'product' | 'article' | undefined |
| 248 | * @param {number} page - 页码(从0开始) | 248 | * @param {number} page - 页码(从0开始) |
| 249 | * @param {number} limit - 每页数量 | 249 | * @param {number} limit - 每页数量 |
| 250 | * @param {boolean} isLoadMore - 是否为加载更多 | 250 | * @param {boolean} isLoadMore - 是否为加载更多 |
| ... | @@ -273,43 +273,39 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo | ... | @@ -273,43 +273,39 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo |
| 273 | // 映射产品列表 | 273 | // 映射产品列表 |
| 274 | const newProducts = res.data.products.list || [] | 274 | const newProducts = res.data.products.list || [] |
| 275 | 275 | ||
| 276 | - // 映射资料列表(进行字段映射,与首页保持一致) | 276 | + // 映射文章列表(参考本周热门文章的映射方式) |
| 277 | - const newFiles = (res.data.files.list || []).map(item => { | 277 | + const newArticles = (res.data.article.list || []).map(item => ({ |
| 278 | - return { | 278 | + id: item.id, |
| 279 | - id: item.meta_id || item.id, | 279 | + title: item.post_title || '未命名文章', |
| 280 | - title: item.name, | 280 | + excerpt: item.post_excerpt || '', |
| 281 | - fileName: item.name || '未命名文件', | 281 | + coverUrl: '', // API 未返回封面图,留空 |
| 282 | - fileSize: item.size || item.file_size, | 282 | + date: item.post_date || '', |
| 283 | - downloadUrl: item.src || item.value, | 283 | + collected: item.is_favorite === 1 || item.is_favorite === '1' || item.is_favorite === true, |
| 284 | - // 不手动提取 extension,让 MaterialCard 内部使用 extractExtensionFromFile 自动从 URL 解析 | 284 | + learners: '', // API 未返回学习人数,留空 |
| 285 | - learners: item.read_people_count ? `${item.read_people_count }人学习` : '', | 285 | + readPeoplePercent: null // API 未返回热度百分比,留空 |
| 286 | - readPeoplePercent: item.read_people_percent, | 286 | + })) |
| 287 | - is_favorite: item.is_favorite, // 保留原始字段 | ||
| 288 | - collected: Boolean(item.is_favorite) // 转换为 Boolean 供 MaterialCard 使用 | ||
| 289 | - } | ||
| 290 | - }) | ||
| 291 | 287 | ||
| 292 | // 根据是否为加载更多来处理数据 | 288 | // 根据是否为加载更多来处理数据 |
| 293 | if (isLoadMore) { | 289 | if (isLoadMore) { |
| 294 | // 加载更多:追加数据 | 290 | // 加载更多:追加数据 |
| 295 | products.value = [...products.value, ...newProducts] | 291 | products.value = [...products.value, ...newProducts] |
| 296 | - files.value = [...files.value, ...newFiles] | 292 | + articles.value = [...articles.value, ...newArticles] |
| 297 | } else { | 293 | } else { |
| 298 | // 首次加载或刷新:替换数据 | 294 | // 首次加载或刷新:替换数据 |
| 299 | products.value = newProducts | 295 | products.value = newProducts |
| 300 | - files.value = newFiles | 296 | + articles.value = newArticles |
| 301 | } | 297 | } |
| 302 | 298 | ||
| 303 | productsTotal.value = res.data.products.total || 0 | 299 | productsTotal.value = res.data.products.total || 0 |
| 304 | - filesTotal.value = res.data.files.total || 0 | 300 | + articlesTotal.value = res.data.article.total || 0 |
| 305 | 301 | ||
| 306 | // ⚠️ 重要:必须先自动选择 tab,然后再计算 hasMore | 302 | // ⚠️ 重要:必须先自动选择 tab,然后再计算 hasMore |
| 307 | // 如果不传 type,自动选择有数据的 tab(仅首次搜索时) | 303 | // 如果不传 type,自动选择有数据的 tab(仅首次搜索时) |
| 308 | if (!type && !isLoadMore) { | 304 | if (!type && !isLoadMore) { |
| 309 | if (productsTotal.value > 0) { | 305 | if (productsTotal.value > 0) { |
| 310 | activeTab.value = 'product' | 306 | activeTab.value = 'product' |
| 311 | - } else if (filesTotal.value > 0) { | 307 | + } else if (articlesTotal.value > 0) { |
| 312 | - activeTab.value = 'file' | 308 | + activeTab.value = 'article' |
| 313 | } | 309 | } |
| 314 | // 如果都为 0,默认 product | 310 | // 如果都为 0,默认 product |
| 315 | } | 311 | } |
| ... | @@ -320,8 +316,8 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo | ... | @@ -320,8 +316,8 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo |
| 320 | const actualTab = type || activeTab.value | 316 | const actualTab = type || activeTab.value |
| 321 | if (actualTab === 'product') { | 317 | if (actualTab === 'product') { |
| 322 | hasMore.value = products.value.length < productsTotal.value | 318 | hasMore.value = products.value.length < productsTotal.value |
| 323 | - } else if (actualTab === 'file') { | 319 | + } else if (actualTab === 'article') { |
| 324 | - hasMore.value = files.value.length < filesTotal.value | 320 | + hasMore.value = articles.value.length < articlesTotal.value |
| 325 | } else { | 321 | } else { |
| 326 | // 如果都没有选中,保守设置为false | 322 | // 如果都没有选中,保守设置为false |
| 327 | hasMore.value = false | 323 | hasMore.value = false |
| ... | @@ -331,7 +327,7 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo | ... | @@ -331,7 +327,7 @@ const performSearch = async (keyword, type, page = 0, limit = pageSize, isLoadMo |
| 331 | 327 | ||
| 332 | console.log('[Search] 搜索成功', { | 328 | console.log('[Search] 搜索成功', { |
| 333 | productsTotal: productsTotal.value, | 329 | productsTotal: productsTotal.value, |
| 334 | - filesTotal: filesTotal.value, | 330 | + articlesTotal: articlesTotal.value, |
| 335 | activeTab: activeTab.value, | 331 | activeTab: activeTab.value, |
| 336 | isLoadMore, | 332 | isLoadMore, |
| 337 | hasMore: hasMore.value | 333 | hasMore: hasMore.value |
| ... | @@ -437,9 +433,9 @@ const clearSearch = () => { | ... | @@ -437,9 +433,9 @@ const clearSearch = () => { |
| 437 | searchKeyword.value = '' | 433 | searchKeyword.value = '' |
| 438 | hasSearched.value = false | 434 | hasSearched.value = false |
| 439 | products.value = [] | 435 | products.value = [] |
| 440 | - files.value = [] | 436 | + articles.value = [] |
| 441 | productsTotal.value = 0 | 437 | productsTotal.value = 0 |
| 442 | - filesTotal.value = 0 | 438 | + articlesTotal.value = 0 |
| 443 | activeTab.value = '' // 重置为空,不选中任何tab | 439 | activeTab.value = '' // 重置为空,不选中任何tab |
| 444 | currentPage.value = 0 | 440 | currentPage.value = 0 |
| 445 | hasMore.value = true | 441 | hasMore.value = true |
| ... | @@ -500,15 +496,15 @@ const { handlePlanSubmit } = usePlanSubmit({ | ... | @@ -500,15 +496,15 @@ const { handlePlanSubmit } = usePlanSubmit({ |
| 500 | /** | 496 | /** |
| 501 | * 处理收藏状态改变 | 497 | * 处理收藏状态改变 |
| 502 | * | 498 | * |
| 503 | - * @param {Object} item - 资料对象 | 499 | + * @param {Object} item - 文章对象 |
| 504 | * @param {Object} newStatus - 新的状态 { collected: boolean } | 500 | * @param {Object} newStatus - 新的状态 { collected: boolean } |
| 505 | */ | 501 | */ |
| 506 | const handleCollectChanged = (item, newStatus) => { | 502 | const handleCollectChanged = (item, newStatus) => { |
| 507 | console.log('[Search] 收藏状态改变:', item.title, newStatus.collected) | 503 | console.log('[Search] 收藏状态改变:', item.title, newStatus.collected) |
| 508 | // 找到对应的项并更新状态 | 504 | // 找到对应的项并更新状态 |
| 509 | - const file = files.value.find(f => f.id === item.id) | 505 | + const article = articles.value.find(a => a.id === item.id) |
| 510 | - if (file) { | 506 | + if (article) { |
| 511 | - file.collected = newStatus.collected | 507 | + article.collected = newStatus.collected |
| 512 | } | 508 | } |
| 513 | } | 509 | } |
| 514 | </script> | 510 | </script> | ... | ... |
| ... | @@ -516,9 +516,9 @@ export async function mockSearchAPI(params) { | ... | @@ -516,9 +516,9 @@ export async function mockSearchAPI(params) { |
| 516 | 516 | ||
| 517 | if (!keyword) { | 517 | if (!keyword) { |
| 518 | // 🔧 优化:如果没有关键词,返回更多推荐数据用于测试 | 518 | // 🔧 优化:如果没有关键词,返回更多推荐数据用于测试 |
| 519 | - // 生成20个产品和20个资料作为默认搜索结果 | 519 | + // 生成20个产品和20个文章作为默认搜索结果 |
| 520 | const defaultProducts = [] | 520 | const defaultProducts = [] |
| 521 | - const defaultFiles = [] | 521 | + const defaultArticles = [] |
| 522 | 522 | ||
| 523 | for (let i = 0; i < 20; i++) { | 523 | for (let i = 0; i < 20; i++) { |
| 524 | const productItem = generateProductItem(i + 1) | 524 | const productItem = generateProductItem(i + 1) |
| ... | @@ -528,32 +528,17 @@ export async function mockSearchAPI(params) { | ... | @@ -528,32 +528,17 @@ export async function mockSearchAPI(params) { |
| 528 | cover_image: productItem.cover_image | 528 | cover_image: productItem.cover_image |
| 529 | }) | 529 | }) |
| 530 | 530 | ||
| 531 | - const materialItem = generateMaterialItem(i + 1) | 531 | + const articleItem = generateArticleItem(i + 1) |
| 532 | - // 确保使用真实的测试文件地址 | 532 | + defaultArticles.push(articleItem) |
| 533 | - const testFileUrl = getTestFileUrl(materialItem.extension, i) | ||
| 534 | - | ||
| 535 | - defaultFiles.push({ | ||
| 536 | - ...materialItem, | ||
| 537 | - id: i + 1, | ||
| 538 | - fileName: materialItem.fileName, | ||
| 539 | - fileSize: materialItem.size, | ||
| 540 | - learners: `${materialItem.read_people_count}人学习`, | ||
| 541 | - readPeoplePercent: materialItem.read_people_percent, | ||
| 542 | - collected: materialItem.collected, | ||
| 543 | - extension: materialItem.extension, | ||
| 544 | - downloadUrl: testFileUrl, // 覆盖为真实的测试文件地址 | ||
| 545 | - title: materialItem.title, | ||
| 546 | - src: materialItem.src | ||
| 547 | - }) | ||
| 548 | } | 533 | } |
| 549 | 534 | ||
| 550 | - console.log(`[Mock] searchAPI - 无关键词,返回默认数据:产品${defaultProducts.length}条,资料${defaultFiles.length}条`) | 535 | + console.log(`[Mock] searchAPI - 无关键词,返回默认数据:产品${defaultProducts.length}条,文章${defaultArticles.length}条`) |
| 551 | return { | 536 | return { |
| 552 | code: 1, | 537 | code: 1, |
| 553 | msg: 'success', | 538 | msg: 'success', |
| 554 | data: { | 539 | data: { |
| 555 | products: { list: defaultProducts, total: defaultProducts.length * 5 }, | 540 | products: { list: defaultProducts, total: defaultProducts.length * 5 }, |
| 556 | - files: { list: defaultFiles, total: defaultFiles.length * 5 } | 541 | + article: { list: defaultArticles, total: defaultArticles.length * 5 } |
| 557 | } | 542 | } |
| 558 | } | 543 | } |
| 559 | } | 544 | } |
| ... | @@ -566,13 +551,13 @@ export async function mockSearchAPI(params) { | ... | @@ -566,13 +551,13 @@ export async function mockSearchAPI(params) { |
| 566 | msg: 'success', | 551 | msg: 'success', |
| 567 | data: { | 552 | data: { |
| 568 | products: { list: [], total: 0 }, | 553 | products: { list: [], total: 0 }, |
| 569 | - files: { list: [], total: 0 } | 554 | + article: { list: [], total: 0 } |
| 570 | } | 555 | } |
| 571 | } | 556 | } |
| 572 | } | 557 | } |
| 573 | 558 | ||
| 574 | const products = [] | 559 | const products = [] |
| 575 | - const files = [] | 560 | + const articles = [] |
| 576 | const startIndex = page * limit | 561 | const startIndex = page * limit |
| 577 | 562 | ||
| 578 | // 🔧 优化:每次循环都生成数据和尝试匹配,增加命中率 | 563 | // 🔧 优化:每次循环都生成数据和尝试匹配,增加命中率 |
| ... | @@ -598,35 +583,20 @@ export async function mockSearchAPI(params) { | ... | @@ -598,35 +583,20 @@ export async function mockSearchAPI(params) { |
| 598 | }) | 583 | }) |
| 599 | } | 584 | } |
| 600 | 585 | ||
| 601 | - // 资料 | 586 | + // 文章 |
| 602 | - const materialItem = generateMaterialItem(startIndex + i + 100) | 587 | + const articleItem = generateArticleItem(startIndex + i + 100) |
| 603 | - const materialName = materialItem.name.toLowerCase() | 588 | + const articleTitle = articleItem.post_title.toLowerCase() |
| 604 | - | 589 | + |
| 605 | - const hasAnyCharMaterial = keywords.length > 0 && keywords.some(k => materialName.includes(k)) | 590 | + const hasAnyCharArticle = keywords.length > 0 && keywords.some(k => articleTitle.includes(k)) |
| 606 | - const hasBigramMaterial = searchKeyword.length >= 2 && keywords.slice(0, -1).some((k, idx) => materialName.includes(k + keywords[idx + 1])) | 591 | + const hasBigramArticle = searchKeyword.length >= 2 && keywords.slice(0, -1).some((k, idx) => articleTitle.includes(k + keywords[idx + 1])) |
| 607 | - | 592 | + |
| 608 | - if (materialName.includes(searchKeyword) || hasAnyCharMaterial || hasBigramMaterial) { | 593 | + if (articleTitle.includes(searchKeyword) || hasAnyCharArticle || hasBigramArticle) { |
| 609 | - // 确保使用真实的测试文件地址 | 594 | + articles.push(articleItem) |
| 610 | - const testFileUrl = getTestFileUrl(materialItem.extension, startIndex + i + 100) | ||
| 611 | - | ||
| 612 | - files.push({ | ||
| 613 | - ...materialItem, | ||
| 614 | - id: startIndex + i + 100, | ||
| 615 | - fileName: materialItem.fileName, | ||
| 616 | - fileSize: materialItem.size, | ||
| 617 | - learners: `${materialItem.read_people_count}人学习`, | ||
| 618 | - readPeoplePercent: materialItem.read_people_percent, | ||
| 619 | - collected: materialItem.collected, | ||
| 620 | - extension: materialItem.extension, | ||
| 621 | - downloadUrl: testFileUrl, // 覆盖为真实的测试文件地址 | ||
| 622 | - title: materialItem.title, | ||
| 623 | - src: materialItem.src | ||
| 624 | - }) | ||
| 625 | } | 595 | } |
| 626 | } | 596 | } |
| 627 | 597 | ||
| 628 | // 🔧 优化:如果没有匹配到任何数据,返回一些推荐数据 | 598 | // 🔧 优化:如果没有匹配到任何数据,返回一些推荐数据 |
| 629 | - if (products.length === 0 && files.length === 0) { | 599 | + if (products.length === 0 && articles.length === 0) { |
| 630 | console.log(`[Mock] searchAPI - 无匹配结果,返回推荐数据`) | 600 | console.log(`[Mock] searchAPI - 无匹配结果,返回推荐数据`) |
| 631 | // 生成 5 个推荐产品 | 601 | // 生成 5 个推荐产品 |
| 632 | for (let i = 0; i < 5; i++) { | 602 | for (let i = 0; i < 5; i++) { |
| ... | @@ -637,34 +607,19 @@ export async function mockSearchAPI(params) { | ... | @@ -637,34 +607,19 @@ export async function mockSearchAPI(params) { |
| 637 | cover_image: productItem.cover_image | 607 | cover_image: productItem.cover_image |
| 638 | }) | 608 | }) |
| 639 | 609 | ||
| 640 | - const materialItem = generateMaterialItem(startIndex + i + 100) | 610 | + const articleItem = generateArticleItem(startIndex + i + 100) |
| 641 | - // 确保使用真实的测试文件地址 | 611 | + articles.push(articleItem) |
| 642 | - const testFileUrl = getTestFileUrl(materialItem.extension, startIndex + i + 100) | ||
| 643 | - | ||
| 644 | - files.push({ | ||
| 645 | - ...materialItem, | ||
| 646 | - id: startIndex + i + 100, | ||
| 647 | - fileName: materialItem.fileName, | ||
| 648 | - fileSize: materialItem.size, | ||
| 649 | - learners: `${materialItem.read_people_count}人学习`, | ||
| 650 | - readPeoplePercent: materialItem.read_people_percent, | ||
| 651 | - collected: materialItem.collected, | ||
| 652 | - extension: materialItem.extension, | ||
| 653 | - downloadUrl: testFileUrl, // 覆盖为真实的测试文件地址 | ||
| 654 | - title: materialItem.title, | ||
| 655 | - src: materialItem.src | ||
| 656 | - }) | ||
| 657 | } | 612 | } |
| 658 | } | 613 | } |
| 659 | 614 | ||
| 660 | - console.log(`[Mock] searchAPI - 第${page}页,关键词"${keyword}",产品${products.length}条,资料${files.length}条`) | 615 | + console.log(`[Mock] searchAPI - 第${page}页,关键词"${keyword}",产品${products.length}条,文章${articles.length}条`) |
| 661 | 616 | ||
| 662 | return { | 617 | return { |
| 663 | code: 1, | 618 | code: 1, |
| 664 | msg: 'success', | 619 | msg: 'success', |
| 665 | data: { | 620 | data: { |
| 666 | products: { list: products, total: products.length * totalPages }, | 621 | products: { list: products, total: products.length * totalPages }, |
| 667 | - files: { list: files, total: files.length * totalPages } | 622 | + article: { list: articles, total: articles.length * totalPages } |
| 668 | } | 623 | } |
| 669 | } | 624 | } |
| 670 | } | 625 | } | ... | ... |
-
Please register or login to post a comment