From bf3be1cd76a983a98f490ba4dea4e19183f6c46e Mon Sep 17 00:00:00 2001 From: lion <120344285@qq.com> Date: Thu, 16 Jul 2026 17:41:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=91=A8=E6=8A=A5=E5=B0=8F=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/weekly-brief.ts | 94 +++++ src/components/ProfileMenuIcon.vue | 8 +- src/pages.json | 8 + src/pages/profile/index.vue | 5 + src/subpkg/weekly-brief/index.vue | 551 +++++++++++++++++++++++++++++ 5 files changed, 665 insertions(+), 1 deletion(-) create mode 100644 src/api/weekly-brief.ts create mode 100644 src/subpkg/weekly-brief/index.vue diff --git a/src/api/weekly-brief.ts b/src/api/weekly-brief.ts new file mode 100644 index 0000000..a53e653 --- /dev/null +++ b/src/api/weekly-brief.ts @@ -0,0 +1,94 @@ +import { API_BASE, TOKEN_STORAGE_KEY } from '@/config' +import { request } from '@/utils/request' +import type { Paginated } from '@/types/api' + +export interface WeeklyBriefStats { + papers_count?: number + papers_analyzed?: number + high_value_papers_count?: number + news_count?: number + news_analyzed?: number + teachers_count?: number + references_count?: number +} + +export interface WeeklyBriefRow { + id: number + week_start: string + week_end: string + title: string + stats?: WeeklyBriefStats | null + generated_at?: string | null + has_docx?: boolean +} + +export interface WeeklyBriefDetail extends WeeklyBriefRow { + content?: string +} + +export interface WeeklyBriefWeekOption { + offset: number + label: string + week_start: string + week_end: string +} + +function buildQuery(params?: Record) { + if (!params) return '' + const query = Object.entries(params) + .filter(([, value]) => value !== undefined && value !== null && value !== '') + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`) + .join('&') + return query ? `?${query}` : '' +} + +export const weeklyBriefApi = { + list(params?: { page?: number; page_size?: number }) { + return request>(`/weekly-briefs${buildQuery(params)}`, { auth: true }) + }, + detail(id: number) { + return request(`/weekly-briefs/${id}`, { auth: true }) + }, + weekOptions() { + return request<{ items: WeeklyBriefWeekOption[] }>('/weekly-briefs/week-options', { auth: true }) + }, + generate(payload: { week_offset?: number; week_start?: string; week_end?: string } = {}) { + return request('/weekly-briefs/generate', { + method: 'POST', + data: payload, + auth: true, + }) + }, + downloadDocx(id: number, filename: string) { + const token = uni.getStorageSync(TOKEN_STORAGE_KEY) as string + return new Promise((resolve, reject) => { + uni.downloadFile({ + url: `${API_BASE}/weekly-briefs/${id}/download`, + header: token ? { Authorization: `Bearer ${token}` } : {}, + success: (res) => { + if (res.statusCode !== 200 || !res.tempFilePath) { + reject(new Error('下载失败')) + return + } + uni.openDocument({ + filePath: res.tempFilePath, + fileType: 'docx', + showMenu: true, + success: () => resolve(), + fail: () => { + uni.saveFile({ + tempFilePath: res.tempFilePath, + success: () => { + uni.showToast({ title: '已保存文件', icon: 'none' }) + resolve() + }, + fail: (err) => reject(new Error(err.errMsg || '打开文件失败')), + }) + }, + }) + }, + fail: (err) => reject(new Error(err.errMsg || '下载失败')), + }) + }) + }, +} diff --git a/src/components/ProfileMenuIcon.vue b/src/components/ProfileMenuIcon.vue index eb20065..855a8da 100644 --- a/src/components/ProfileMenuIcon.vue +++ b/src/components/ProfileMenuIcon.vue @@ -9,7 +9,7 @@ import { computed } from 'vue' import { toSvgDataUri } from '@/utils/svg' const props = defineProps<{ - type: 'profile' | 'course' | 'activity' | 'demand' | 'checkin' | 'logout' | 'crawler' + type: 'profile' | 'course' | 'activity' | 'demand' | 'checkin' | 'logout' | 'crawler' | 'weekly-brief' }>() const iconMap = { @@ -53,6 +53,12 @@ const iconMap = { `), + 'weekly-brief': toSvgDataUri(` + + + + + `), } const iconSrc = computed(() => iconMap[props.type]) diff --git a/src/pages.json b/src/pages.json index 0646b2e..8d25bec 100644 --- a/src/pages.json +++ b/src/pages.json @@ -214,6 +214,14 @@ "navigationBarBackgroundColor": "#244e98", "navigationBarTextStyle": "white" } + }, + { + "path": "weekly-brief/index", + "style": { + "navigationBarTitleText": "论文周报", + "navigationBarBackgroundColor": "#244e98", + "navigationBarTextStyle": "white" + } } ] } diff --git a/src/pages/profile/index.vue b/src/pages/profile/index.vue index 89e122f..d1a06a1 100644 --- a/src/pages/profile/index.vue +++ b/src/pages/profile/index.vue @@ -31,6 +31,11 @@ 数据爬虫 + + + 论文周报 + + diff --git a/src/subpkg/weekly-brief/index.vue b/src/subpkg/weekly-brief/index.vue new file mode 100644 index 0000000..4f41e28 --- /dev/null +++ b/src/subpkg/weekly-brief/index.vue @@ -0,0 +1,551 @@ + + + + + + +