diff --git a/src/api/request.ts b/src/api/request.ts index 0a8ac57..c05ceac 100644 --- a/src/api/request.ts +++ b/src/api/request.ts @@ -171,6 +171,13 @@ export function patch(url: string, data?: unknown, config?: AxiosRe return request.patch(url, data, config) as unknown as Promise } +/** 原始响应请求:返回 AxiosResponse(绕过 {code,data} 解包), + * 供需要访问原始响应体(非标准结构/流式响应)的场景使用, + * 替代 responseType:'text' + 双重类型断言的 hack */ +export function requestRaw(config: AxiosRequestConfig): Promise> { + return request.request(config) as Promise> +} + /** 上传文件 */ export function upload(url: string, formData: FormData, config?: AxiosRequestConfig): Promise { return request.post(url, formData, { diff --git a/src/router/index.ts b/src/router/index.ts index a4d1fa1..43e528d 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -360,13 +360,8 @@ export const staticRoutes: RouteRecordRaw[] = [ component: () => import('@/views/LegacyPage.vue'), meta: { title: '储值查看', requiresAuth: true, menuGuarded: true, legacySrc: '/pages/private/CreateE/StoreValue.html' }, }, - // === 阶段 8:SKU(移动端 C 端,待决策是否拆分独立工程) === - { - path: 'sku', - name: 'Sku', - component: () => import('@/views/SKU/Sku.vue'), - meta: { title: '商品详情', requiresAuth: false }, - }, + // === SKU(移动端 C 端):全 Mock 页面已从生产路由移除 === + // Sku.vue 仍保留源码(1870 行 Mock 数据 + TODO),待决策是否拆分为独立移动端工程后再接入 // === 兜底:未匹配路由在 DefaultLayout 内显示 404(保留 menu/nav/tab) === // 作为 DefaultLayout 子路由,享有完整框架;requiresAuth: true 使其自动开 tab { diff --git a/src/stores/app.ts b/src/stores/app.ts index 7e16cf0..960f830 100644 --- a/src/stores/app.ts +++ b/src/stores/app.ts @@ -131,7 +131,7 @@ function applyPrimaryColor(color: string): void { } } -/** 应用状态:侧边栏折叠、主题、配色、语言等全局 UI 状态 */ +/** 应用状态:侧边栏折叠、主题、配色等全局 UI 状态 */ export const useAppStore = defineStore('app', () => { /** 侧边栏是否折叠 */ const sidebarCollapsed = ref(false) @@ -139,8 +139,6 @@ export const useAppStore = defineStore('app', () => { const theme = ref('default') /** 自定义主色(hex);设置后覆盖预设配色,null 表示用预设 */ const customPrimary = ref(null) - /** 当前语言 */ - const locale = ref<'zh-CN' | 'en-US'>('zh-CN') /** 切换侧边栏 */ function toggleSidebar(): void { @@ -193,7 +191,6 @@ export const useAppStore = defineStore('app', () => { sidebarCollapsed, theme, customPrimary, - locale, toggleSidebar, setTheme, setCustomColor, diff --git a/src/stores/user.ts b/src/stores/user.ts index a86a15d..15b2c0e 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -32,8 +32,6 @@ export const useUserStore = defineStore('user', () => { const userInfo = ref(null) const roles = ref([]) const menus = ref([]) - const token = ref('') - const loading = ref(false) // CheckAdmin 结果(后端按当前角色权限码判定管理员,不依赖 GetELTUserInfo 的 IsAdmin 字段) const adminCheck = ref(null) // CheckAdmin 是否已加载完成(成功或失败都置 true,供页面区分"加载中"与"确实无权限") @@ -114,16 +112,11 @@ export const useUserStore = defineStore('user', () => { // === 动作 === /** 登录 */ async function login(params: LoginParams): Promise { - loading.value = true - try { - await apiLogin(params) - await fetchUserInfo() - await fetchMenus() - await fetchRoles() - await fetchAdminCheck() - } finally { - loading.value = false - } + await apiLogin(params) + await fetchUserInfo() + await fetchMenus() + await fetchRoles() + await fetchAdminCheck() } /** 注销 */ @@ -243,7 +236,6 @@ export const useUserStore = defineStore('user', () => { userInfo.value = null roles.value = [] menus.value = [] - token.value = '' adminCheck.value = null adminChecked.value = false localStorage.removeItem(CACHE_KEY) @@ -254,8 +246,6 @@ export const useUserStore = defineStore('user', () => { userInfo, roles, menus, - token, - loading, adminCheck, adminChecked, // 计算属性 diff --git a/src/types/api.ts b/src/types/api.ts index 13a30f8..ad4398c 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -324,10 +324,25 @@ export interface RoleScope { WorkgroupUUID?: string } -/** CheckAdmin 接口返回结果 */ +/** CheckAdmin 接口返回结果(对齐后端 /API/FormAPI/CheckAdmin) */ export interface AdminCheckResult { /** 是否管理员 */ is_admin?: boolean - /** 用户作用域 */ - role_scope?: RoleScope | null + is_superuser?: boolean + is_super_admin?: boolean + is_tenant_admin?: boolean + current_role_name?: string + current_role_uuid?: string + current_company_uuid?: string + current_tenant_uuid?: string + has_current_company?: boolean + /** 当前角色的数据作用域 */ + role_scope?: { + Type?: string + TypeLabel?: string + IsAdmin?: boolean + IsDeptManager?: boolean + IsWorkgroupLead?: boolean + IsMember?: boolean + } | null } diff --git a/src/views/assets/Manager.vue b/src/views/assets/Manager.vue index 6dbfd54..15189fa 100644 --- a/src/views/assets/Manager.vue +++ b/src/views/assets/Manager.vue @@ -525,7 +525,7 @@ async function UploadFiles(files: File[]): Promise { /** * 简单上传:单 FormData - * 直接用 XHR 拿 onprogress 进度回调 + * 走统一 axios 实例(拦截器注入时区/作用域参数/401 处理),onUploadProgress 拿进度 */ async function SimpleUpload( file: File, @@ -533,26 +533,10 @@ async function SimpleUpload( ): Promise { const fd = new FormData() fd.append('file', file) - // TODO: @/api/request 的 upload() 封装暂未暴露 onProgress 回调 - // 若后续扩展 upload() 支持 onUploadProgress,可改回 upload('/API/Asset/Upload', fd, { onUploadProgress }) - await new Promise((resolve, reject) => { - const xhr = new XMLHttpRequest() - xhr.open('POST', '/API/Asset/Upload') - xhr.withCredentials = true - xhr.upload.onprogress = (e) => { - if (e.lengthComputable) onProgress(Math.round((e.loaded / e.total) * 100)) - } - xhr.onload = () => { - try { - const data = JSON.parse(xhr.responseText) - if (data.code === 0) resolve() - else reject(new Error(data.msg || '上传失败')) - } catch { - reject(new Error('解析响应失败')) - } - } - xhr.onerror = () => reject(new Error('网络错误')) - xhr.send(fd) + await upload('/API/Asset/Upload', fd, { + onUploadProgress: (e) => { + if (e.total) onProgress(Math.round((e.loaded / e.total) * 100)) + }, }) }