From e740ec77eca4932cf0283db457bc7296cb119d6e Mon Sep 17 00:00:00 2001 From: owenchen Date: Wed, 14 Oct 2026 18:50:17 +0800 Subject: [PATCH] ow --- uniapp/youjiala/smoke.out | 0 .../youjiala/src/common/http.interceptor.ts | 44 +- .../src/components/app-page/app-page.vue | 41 +- .../file-add-sheet/file-add-sheet.vue | 90 ++++ .../file-breadcrumb/file-breadcrumb.vue | 7 +- .../file-tab-filter/file-tab-filter.vue | 49 +- .../float-add-btn/float-add-btn.vue | 22 +- .../folder-name-dialog/folder-name-dialog.vue | 142 ++++++ .../components/page-navbar/page-navbar.vue | 51 +- .../youjiala/src/composables/useDmsFiles.ts | 14 + uniapp/youjiala/src/locale/lang/en-US.json | 24 + uniapp/youjiala/src/locale/lang/zh-CN.json | 24 + uniapp/youjiala/src/md/custom-icon.md | 93 ++++ uniapp/youjiala/src/pages.json | 4 + uniapp/youjiala/src/pages/tab/file.vue | 146 +++++- .../src/pages/transport/transport.vue | 261 ++++++++++ uniapp/youjiala/src/router/routes.ts | 3 + uniapp/youjiala/src/stores/index.ts | 1 + uniapp/youjiala/src/stores/uploadQueue.ts | 467 ++++++++++++++++++ uniapp/youjiala/src/utils/chooseFiles.ts | 64 +++ uniapp/youjiala/src/utils/folderGlyph.ts | 16 + uniapp/youjiala/src/utils/selectGlyph.ts | 17 + uniapp/youjiala/src/utils/sortGlyph.ts | 19 + uniapp/youjiala/src/utils/transferGlyph.ts | 27 + 24 files changed, 1561 insertions(+), 65 deletions(-) create mode 100644 uniapp/youjiala/smoke.out create mode 100644 uniapp/youjiala/src/components/file-add-sheet/file-add-sheet.vue create mode 100644 uniapp/youjiala/src/components/folder-name-dialog/folder-name-dialog.vue create mode 100644 uniapp/youjiala/src/md/custom-icon.md create mode 100644 uniapp/youjiala/src/pages/transport/transport.vue create mode 100644 uniapp/youjiala/src/stores/uploadQueue.ts create mode 100644 uniapp/youjiala/src/utils/chooseFiles.ts create mode 100644 uniapp/youjiala/src/utils/folderGlyph.ts create mode 100644 uniapp/youjiala/src/utils/selectGlyph.ts create mode 100644 uniapp/youjiala/src/utils/sortGlyph.ts create mode 100644 uniapp/youjiala/src/utils/transferGlyph.ts diff --git a/uniapp/youjiala/smoke.out b/uniapp/youjiala/smoke.out new file mode 100644 index 0000000..e69de29 diff --git a/uniapp/youjiala/src/common/http.interceptor.ts b/uniapp/youjiala/src/common/http.interceptor.ts index 943a61b..267f092 100644 --- a/uniapp/youjiala/src/common/http.interceptor.ts +++ b/uniapp/youjiala/src/common/http.interceptor.ts @@ -73,6 +73,21 @@ function getToken(): string { return getJwtInfo()?.AccessToken ?? ""; } +/** + * 归一化后的 Authorization 头值:ASP.NET Core JWT 认证要求 "Bearer " 前缀, + * 存量令牌可能带也可能不带前缀,统一在这里补齐—— + * 主拦截器与 uploadFile/downloadFile/上传队列等旁路通道共用这一个口径, + * 否则旁路裸发 token 会被后端 401(上传失败实测根因)。 + * @returns 无令牌时返回空串(调用方据此不挂 Authorization 头) + */ +export function bearerAuth(): string { + const token = getToken(); + if (!token) { + return ""; + } + return token.startsWith("Bearer ") ? token : `Bearer ${token}`; +} + /** * 认证失败统一收尾:必要时清登录态并跳登录页; * 已经在登录页就不再跳,避免死循环 @@ -224,6 +239,18 @@ function detectBusinessException(data: any): string { return ""; } +/** + * 静默提取业务异常消息(不弹提示):供批量传输通道使用—— + * 上传队列的失败要落在任务行上逐条展示,不能每条弹一个模态。 + * @returns 命中返回异常消息,未命中返回空串 + */ +export function extractBusinessError(data: any): string { + if (!data || typeof data !== "object" || !data.SourceCode) { + return ""; + } + return extractErrorMessage(data) || "业务处理失败"; +} + // ==================== 全局配置(httpPlugin 注册用) ==================== const httpRequestConfig: RequestConfig = { @@ -252,12 +279,9 @@ const httpInterceptor: RequestInterceptor = { config.method = String( config.method || "GET", ).toUpperCase() as RequestOptions["method"]; - const token = getToken(); - if (token) { - // ASP.NET Core JWT Bearer 认证要求 Authorization 带 "Bearer " 前缀(旧系统同) - config.header.Authorization = token.startsWith("Bearer ") - ? token - : `Bearer ${token}`; + const auth = bearerAuth(); + if (auth) { + config.header.Authorization = auth; } config.header.locale = backendLocale(); return config; @@ -360,7 +384,7 @@ export interface UploadOptions { export function uploadFile(options: UploadOptions): Promise { const { url, filePath, name = "file", formData, header = {} } = options; const fullUrl = url.indexOf("http") === 0 ? url : baseUrl + url; - const token = getToken(); + const auth = bearerAuth(); return new Promise((resolve, reject) => { uni.uploadFile({ @@ -369,7 +393,7 @@ export function uploadFile(options: UploadOptions): Promise { name, formData, timeout, - header: token ? { Authorization: token, ...header } : header, + header: auth ? { Authorization: auth, ...header } : header, success: (res) => { if (res.statusCode < 200 || res.statusCode >= 300) { const message = `上传失败[${res.statusCode}]`; @@ -448,7 +472,7 @@ function timestamp(): string { export async function downloadFile(options: DownloadOptions): Promise { const { url, method = "POST", data, filename, extension = "xlsx" } = options; const fullUrl = url.indexOf("http") === 0 ? url : baseUrl + url; - const token = getToken(); + const auth = bearerAuth(); const res = await new Promise( (resolve, reject) => { @@ -458,7 +482,7 @@ export async function downloadFile(options: DownloadOptions): Promise { data, timeout, responseType: "arraybuffer", - header: token ? { Authorization: token } : {}, + header: auth ? { Authorization: auth } : {}, success: resolve, fail: err => reject(new Error(err.errMsg || "下载失败")), }); diff --git a/uniapp/youjiala/src/components/app-page/app-page.vue b/uniapp/youjiala/src/components/app-page/app-page.vue index f89a731..ba3abe3 100644 --- a/uniapp/youjiala/src/components/app-page/app-page.vue +++ b/uniapp/youjiala/src/components/app-page/app-page.vue @@ -20,6 +20,11 @@ defineProps({ type: Boolean, default: false, }, + /** 自定义返回动作(u-navbar customBack 透传):页面做无栈兜底跳转时用 */ + customBack: { + type: Function as PropType<() => void>, + default: undefined, + }, customStyle: { type: [String, Object] as PropType>, default: "", @@ -40,11 +45,9 @@ const background = reactive({