فهرست منبع

feat(@six/wisdom-legacy): 成果管理 - 论文页面接口对接

Co-authored-by: Cursor <cursoragent@cursor.com>
cmj 2 روز پیش
والد
کامیت
2159324f56

+ 16 - 3
apps/wisdom-legacy/src/api/outcome/paper.api.ts

@@ -1,6 +1,7 @@
-import type { PaperSubmitVO, PaperVO } from './paper.schema';
+import type { PaperDTO, PaperSubmitVO, PaperVO } from './paper.schema';
 
 import type { PageQueryMethodArgs } from '#/request/schema';
+import type { PageDTO } from '#/request/schema/record';
 
 import { getEnvelopeData, httpClient } from '#/request';
 import {
@@ -16,7 +17,13 @@ import {
   mockListPaperMethod,
   USE_PAPER_MOCK,
 } from './paper.mock';
-import { decodePaper, encodePaper, encodePaperQuery } from './paper.schema';
+import {
+  decodePaper,
+  decodePaperType,
+  encodePaper,
+  encodePaperQuery,
+  filterPaperPageByCategory,
+} from './paper.schema';
 
 export { USE_PAPER_MOCK } from './paper.mock';
 export type {
@@ -38,13 +45,19 @@ export function listPaperMethod(...args: PageQueryMethodArgs) {
   }
 
   const { params, data } = pageQueryArgsTransform(args, encodePaperQuery);
+  const filterCategory = data.type ? decodePaperType(data.type) : undefined;
+
   return httpClient.Post(
     `/wis-pc/outcome/paperManage/page`,
     { ...params, ...data },
     {
       params,
       hitSource: /^outcome-paper:(edit|delete)/,
-      transform: paginateTransform(decodePaper),
+      transform: (page: PageDTO<PaperDTO>) =>
+        filterPaperPageByCategory(
+          paginateTransform(decodePaper)(page),
+          filterCategory,
+        ),
     },
   );
 }

+ 31 - 29
apps/wisdom-legacy/src/api/outcome/paper.mock.ts

@@ -13,7 +13,7 @@ import { pageQueryArgsTransform } from '#/request/schema';
 import { decodePaper, encodePaper, encodePaperQuery } from './paper.schema';
 
 /** 后端接口就绪后改为 false */
-export const USE_PAPER_MOCK = true;
+export const USE_PAPER_MOCK = false;
 
 type MethodLike<T> = PromiseLike<T> & {
   send?: (force?: boolean) => PromiseLike<T>;
@@ -27,78 +27,78 @@ const SEED_RECORDS: Omit<
   'createTime' | 'id' | 'personalStudioId' | 'updateTime'
 >[] = [
   {
-    category: 'journal',
+    type: '0',
     title: '中医药治疗慢性胃炎的临床研究',
-    authors: '王教授, 张主任, 李医师',
+    author: '王教授, 张主任, 李医师',
     journalName: '中华中医药杂志',
     publishYear: '2026',
-    volumeInfo: '第41卷第3期',
-    keywords: '中医药; 慢性胃炎; 临床研究',
+    phase: '第41卷第3期',
+    keyword: '中医药; 慢性胃炎; 临床研究',
     downloadCount: 156,
     commentCount: 8,
     createBy: '王刚',
     fileUrl: MOCK_PDF_URL,
   },
   {
-    category: 'journal',
+    type: '0',
     title: '针灸联合推拿治疗腰椎间盘突出症的疗效观察',
-    authors: '李明, 赵华',
+    author: '李明, 赵华',
     journalName: '中国针灸',
     publishYear: '2025',
-    volumeInfo: '第45卷第12期',
-    keywords: '针灸; 推拿; 腰椎间盘突出',
+    phase: '第45卷第12期',
+    keyword: '针灸; 推拿; 腰椎间盘突出',
     downloadCount: 89,
     commentCount: 5,
     createBy: '张许',
     fileUrl: MOCK_PDF_URL,
   },
   {
-    category: 'degree',
+    type: '1',
     title: '基于数据挖掘的方剂配伍规律研究',
-    authors: '陈思远',
+    author: '陈思远',
     journalName: '北京中医药大学',
     publishYear: '2024',
-    volumeInfo: '博士学位论文',
-    keywords: '数据挖掘; 方剂; 配伍规律',
+    phase: '博士学位论文',
+    keyword: '数据挖掘; 方剂; 配伍规律',
     downloadCount: 42,
     commentCount: 3,
     createBy: '李虎',
     fileUrl: MOCK_PDF_URL,
   },
   {
-    category: 'conference',
+    type: '2',
     title: '人工智能辅助中医辨证论治系统的设计与实现',
-    authors: '刘洋, 周敏, 孙伟',
+    author: '刘洋, 周敏, 孙伟',
     journalName: '全国中医药信息学术年会',
     publishYear: '2025',
-    volumeInfo: '2025年11月',
-    keywords: '人工智能; 中医辨证; 辅助诊疗',
+    phase: '2025年11月',
+    keyword: '人工智能; 中医辨证; 辅助诊疗',
     downloadCount: 67,
     commentCount: 12,
     createBy: '王刚',
     fileUrl: MOCK_PDF_URL,
   },
   {
-    category: 'journal',
+    type: '0',
     title: '经典名方化裁治疗失眠的临床体会',
-    authors: '黄医师, 吴教授',
+    author: '黄医师, 吴教授',
     journalName: '中医杂志',
     publishYear: '2025',
-    volumeInfo: '第66卷第8期',
-    keywords: '经典名方; 失眠; 临床体会',
+    phase: '第66卷第8期',
+    keyword: '经典名方; 失眠; 临床体会',
     downloadCount: 203,
     commentCount: 15,
     createBy: '张许',
     fileUrl: MOCK_PDF_URL,
   },
   {
-    category: 'journal',
+    type: '0',
     title: '中药外敷治疗膝骨关节炎的Meta分析',
-    authors: '郑研究员, 钱博士',
+    author: '郑研究员, 钱博士',
     journalName: '中国中药杂志',
     publishYear: '2024',
-    volumeInfo: '第49卷第6期',
-    keywords: '中药外敷; 膝骨关节炎; Meta分析',
+    phase: '第49卷第6期',
+    keyword: '中药外敷; 膝骨关节炎; Meta分析',
     downloadCount: 118,
     commentCount: 6,
     createBy: '李虎',
@@ -140,8 +140,8 @@ function matchKeyword(record: PaperDTO, keyword?: string) {
   if (!keyword) return true;
   const text = [
     record.title,
-    record.authors,
-    record.keywords,
+    record.author,
+    record.keyword,
     record.journalName,
     record.createBy,
   ]
@@ -157,7 +157,7 @@ function matchWorkroom(record: PaperDTO, workroomId?: string) {
 
 function matchCategory(record: PaperDTO, category?: PaperCategory) {
   if (!category) return true;
-  return record.category === category;
+  return decodePaper(record).category === category;
 }
 
 function toVo(dto: PaperDTO): PaperVO {
@@ -170,7 +170,9 @@ export function mockListPaperMethod(...args: PageQueryMethodArgs) {
   const pageSize = Number(params.pageSize ?? 10);
   const keyword = data.mixture;
   const workroomId = data.personalStudioId?.toString();
-  const category = data.category;
+  const category = data.type
+    ? decodePaper({ type: data.type }).category
+    : void 0;
 
   const filtered = store.filter(
     (record) =>

+ 61 - 18
apps/wisdom-legacy/src/api/outcome/paper.schema.ts

@@ -13,6 +13,21 @@ import { decodeAuditRecord } from '#/request/schema/audit-record';
 
 export type PaperCategory = 'conference' | 'degree' | 'journal';
 
+/** 后端 `type` 字段:0-期刊论文 1-学位论文 2-会议论文 */
+export type PaperTypeDTO = '0' | '1' | '2';
+
+const PAPER_TYPE_TO_DTO: Record<PaperCategory, PaperTypeDTO> = {
+  journal: '0',
+  degree: '1',
+  conference: '2',
+};
+
+const PAPER_TYPE_FROM_DTO: Record<PaperTypeDTO, PaperCategory> = {
+  '0': 'journal',
+  '1': 'degree',
+  '2': 'conference',
+};
+
 export const PAPER_CATEGORY_OPTIONS = [
   { label: '期刊论文', value: 'journal' },
   { label: '学位论文', value: 'degree' },
@@ -28,29 +43,57 @@ export function getPaperCategoryLabel(category?: PaperCategory) {
   );
 }
 
+export function decodePaperType(type?: number | string): PaperCategory {
+  const normalized = type?.toString();
+  if (normalized === '0' || normalized === '1' || normalized === '2') {
+    return PAPER_TYPE_FROM_DTO[normalized];
+  }
+  return 'journal';
+}
+
+/** 按 Tab 分类过滤分页结果(后端未按 type 过滤时的兜底) */
+export function filterPaperPageByCategory<
+  T extends { items: PaperVO[]; total: number },
+>(page: T, category?: PaperCategory): T {
+  if (!category) return page;
+  const items = page.items.filter((item) => item.category === category);
+  return { ...page, items };
+}
+
+function encodePaperType(category: PaperCategory): PaperTypeDTO {
+  return PAPER_TYPE_TO_DTO[category];
+}
+
 // ---------------------------------------------------------------------------
 // DTO
 // ---------------------------------------------------------------------------
 
+/** 论文 DTO,对应 `OutcomePaperDetail` */
 export interface PaperDTO extends AuditRecordDTO {
   id?: number | string;
+  status?: string;
+  remark?: string;
   personalStudioId?: number | string;
-  category?: PaperCategory;
-  title?: string;
-  authors?: string;
-  journalName?: string;
-  publishYear?: string;
-  volumeInfo?: string;
-  keywords?: string;
   fileUrl?: string;
   downloadCount?: number;
+  browseCount?: number;
   commentCount?: number;
+  praiseCount?: number;
+  /** 分类 0-期刊论文 1-学位论文 2-会议论文 */
+  type?: PaperTypeDTO | string;
+  title?: string;
+  author?: string;
+  journalName?: string;
+  publishYear?: string;
+  phase?: string;
+  keyword?: string;
 }
 
 export interface PaperQueryDTO {
   mixture?: string;
   personalStudioId?: number | string;
-  category?: PaperCategory;
+  type?: PaperTypeDTO | string;
+  status?: string;
   pageNum?: number;
   pageSize?: number;
 }
@@ -109,13 +152,13 @@ export function decodePaper(dto: PaperDTO): PaperVO {
     ...decodeAuditRecord(dto),
     id: dto.id?.toString(),
     workroomId: dto.personalStudioId?.toString() ?? '',
-    category: dto.category ?? 'journal',
+    category: decodePaperType(dto.type),
     title: dto.title ?? '',
-    authors: dto.authors ?? '',
+    authors: dto.author ?? '',
     journalName: dto.journalName ?? '',
     publishYear: dto.publishYear ?? '',
-    volumeInfo: dto.volumeInfo,
-    keywords: dto.keywords,
+    volumeInfo: dto.phase,
+    keywords: dto.keyword,
     pdfUrl: dto.fileUrl,
     downloadCount: dto.downloadCount ?? 0,
     commentCount: dto.commentCount ?? 0,
@@ -126,7 +169,7 @@ export function encodePaperQuery(query: Partial<PaperQueryVO>): PaperQueryDTO {
   return {
     mixture: query.keyword,
     personalStudioId: query.workroomId,
-    category: query.category,
+    type: query.category ? encodePaperType(query.category) : undefined,
   };
 }
 
@@ -134,14 +177,14 @@ export function encodePaper(vo: PaperSubmitVO): PaperDTO {
   return {
     id: vo.id,
     personalStudioId: vo.workroomId,
-    category: vo.category,
+    fileUrl: vo.pdfUrl,
+    type: encodePaperType(vo.category),
     title: vo.title,
-    authors: vo.authors,
+    author: vo.authors,
     journalName: vo.journalName,
     publishYear: vo.publishYear,
-    volumeInfo: vo.volumeInfo,
-    keywords: vo.keywords,
-    fileUrl: vo.pdfUrl,
+    phase: vo.volumeInfo,
+    keyword: vo.keywords,
   };
 }
 

+ 11 - 2
apps/wisdom-legacy/src/views/outcome/PaperList.vue

@@ -6,6 +6,7 @@ import { computed, ref, shallowRef, triggerRef, watch } from 'vue';
 import { Page } from '@vben/common-ui';
 import { Plus } from '@vben/icons';
 
+import { watchDebounced } from '@vueuse/core';
 import {
   Button,
   Empty,
@@ -144,11 +145,19 @@ async function handleDelete(row: PaperVO) {
   }
 }
 
-function onSearch() {
-  searchKeyword.value = keyword.value.trim();
+function applySearch(value: string) {
+  const next = value.trim();
+  if (next === searchKeyword.value) return;
+  searchKeyword.value = next;
   pageNum.value = 1;
 }
 
+watchDebounced(keyword, applySearch, { debounce: 300 });
+
+function onSearch() {
+  applySearch(keyword.value);
+}
+
 function onTabChange(key: number | string) {
   category.value = key as PaperCategory;
   pageNum.value = 1;