diff --git a/components.d.ts b/components.d.ts index 9a51634..b30770c 100644 --- a/components.d.ts +++ b/components.d.ts @@ -79,6 +79,7 @@ declare module 'vue' { StageBreadcrumbs: typeof import('./src/components/stageBreadcrumbs/index.vue')['default'] StandardMenu: typeof import('./src/components/standardMenu/index.vue')['default'] StandMenu: typeof import('./src/components/standMenu/index.vue')['default'] + UserSelector: typeof import('./src/components/userSelector/index.vue')['default'] Xxx: typeof import('./src/components/comment/xxx.vue')['default'] Xxxx: typeof import('./src/components/xxxx/index.vue')['default'] } diff --git a/src/api/modules/Comment/index.ts b/src/api/modules/Comment/index.ts index 746d3a6..8b2663d 100644 --- a/src/api/modules/Comment/index.ts +++ b/src/api/modules/Comment/index.ts @@ -21,16 +21,16 @@ interface addCommentProps { // 获取评论 -export const getComment = (params: commentProps) => { - return request.get('/comment/getComment', { params }); +export const getComment = (data: commentProps) => { + return request.post('/communicate/v1/comment/list', data); } // 添加评论-回复评论 export const addReplyComment = (data: addCommentProps) => { - return request.post('/comment/addComment', data) + return request.post('/communicate/v1/comment/add', data) }; // 删除评论 export const deleteComment = (id: string) => { - return request.delete(`/comment/deleteComment/${id}`); + return request.delete(`/communicate/v1/comment/del/${id}`); } \ No newline at end of file diff --git a/src/components/cardItem/index.vue b/src/components/cardItem/index.vue index 9dc1aed..bcee38d 100644 --- a/src/components/cardItem/index.vue +++ b/src/components/cardItem/index.vue @@ -1,128 +1,89 @@ + + \ No newline at end of file + diff --git a/src/components/overflowTabs/index.vue b/src/components/overflowTabs/index.vue index 3d5bef3..516f015 100644 --- a/src/components/overflowTabs/index.vue +++ b/src/components/overflowTabs/index.vue @@ -11,7 +11,7 @@ v-for="(item, index) in visibleItems" :key="item[itemMap.id]" class="tab-item" - :class="{ active: modelValue === item[itemMap.id] }" + :class="{ 'active': modelValue === item[itemMap.id] }" @click="$emit('update:modelValue', item[itemMap.id])" > {{ item[itemMap.label] }} @@ -106,8 +106,6 @@ const calculateLayout = () => { for (let i = 0; i < itemWidths.value.length; i++) { const w = itemWidths.value[i]; - // 加上 20px 的 padding 补偿 (对应你 CSS 里的 padding: 0 20px) - // 最好在 measureWidths 阶段就包含 padding,或者在这里统一加 const fullWidth = w; if (currentWidth + fullWidth > containerWidth) { @@ -164,8 +162,6 @@ onMounted(async () => { updateActiveBar(); resizeObserver = new ResizeObserver(() => { - // 尽量不要在 Resize 里用太长的 debounce, - // 否则你会感觉 Tab 是“跳”出来的,而不是“滑”出来的 handleResize(); }); @@ -190,6 +186,9 @@ watch(() => props.items, async () => { \ No newline at end of file diff --git a/src/components/stageBreadcrumbs/index.vue b/src/components/stageBreadcrumbs/index.vue index bcda1ae..3076ad9 100644 --- a/src/components/stageBreadcrumbs/index.vue +++ b/src/components/stageBreadcrumbs/index.vue @@ -1,5 +1,5 @@ + + diff --git a/src/pages/stage/flow/index.vue b/src/pages/stage/flow/index.vue index aaa49fc..73440af 100644 --- a/src/pages/stage/flow/index.vue +++ b/src/pages/stage/flow/index.vue @@ -1,13 +1,86 @@ \ No newline at end of file + diff --git a/src/pages/stage/flow/subTabs.vue b/src/pages/stage/flow/subTabs.vue new file mode 100644 index 0000000..15fab88 --- /dev/null +++ b/src/pages/stage/flow/subTabs.vue @@ -0,0 +1,55 @@ + + + diff --git a/src/pages/stage/origanization/index.vue b/src/pages/stage/origanization/index.vue index 8b1b33b..8996136 100644 --- a/src/pages/stage/origanization/index.vue +++ b/src/pages/stage/origanization/index.vue @@ -2,7 +2,7 @@
- + @@ -47,7 +47,7 @@ :color="getIconColor(node)" /> - +
@@ -266,11 +266,6 @@ onMounted(()=>{ @use "sass:math"; .mj-organization { height: 100%; - .organization-tabs { - :deep(.stage-breadcrumbs) { - padding: 0; - } - } .mj-organization-card { border-radius: 16px; border: 1px solid #e2e8f099; @@ -325,9 +320,6 @@ onMounted(()=>{ } .tree-node-label{ display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; width: 100%; } } diff --git a/src/pages/stage/permission/index.vue b/src/pages/stage/permission/index.vue index c4e8d05..4575fbb 100644 --- a/src/pages/stage/permission/index.vue +++ b/src/pages/stage/permission/index.vue @@ -1,12 +1,163 @@ \ No newline at end of file diff --git a/src/request/index.ts b/src/request/index.ts index 665fa0a..6c45d06 100644 --- a/src/request/index.ts +++ b/src/request/index.ts @@ -3,16 +3,16 @@ import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; import { ElNotification } from "element-plus"; import { VITE_APP_BASE_API } from "../../config.js"; import TokenManager from "@/utils/storage"; -import { getMockData, shouldUseMock } from "@/mock"; //mock数据信息 const tokenManager = TokenManager.getInstance(); -const baseUrl = import.meta.env.MODE === "development" ? "/api" : VITE_APP_BASE_API; +const baseUrl = + import.meta.env.MODE === "development" ? "/api" : VITE_APP_BASE_API; // 1. 锁和队列定义在类外部,确保全局唯一 let isRefreshing = false; let requestsQueue: Array<(token: string) => void> = []; // 登录接口 传递参数不一样 const AUTH_OAUTH2_TOKEN_URL = "/auth/oauth2/token"; -const CLIENT_CREDENTIALS = "Basic " + window.btoa("mversion:secret"); +const CLIENT_CREDENTIALS = "Basic " + window.btoa("mversion:H7mHCOfjhV2VqlR31OHi6ruVMeOQvluz"); class HttpRequest { private instance: AxiosInstance; @@ -127,13 +127,23 @@ class HttpRequest { } // 其它业务错误 - ElNotification.error({ title: "提示", message: res.msg || "服务异常" }); + ElNotification.error({ + title: "提示", + dangerouslyUseHTMLString: true, + message: `${res.msg}
错误码:${res.subCode}` || "服务异常", + }); return Promise.reject(res); }, (error) => { // 网络层错误处理 if (error.response?.status === 401) { this.clearTokens(); + } else { + if(this.isAuthEndpoint(error.config.url)){ + ElNotification.error({ title: "提示", message: error.response.data.error || '未知错误' }); + return; + } + ElNotification.error({ title: "提示", message: "服务异常" }); } return Promise.reject(error); } diff --git a/src/router/index.ts b/src/router/index.ts index 9943d98..bf9eb95 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -9,7 +9,7 @@ import TokenManager from "@/utils/storage"; import Login from "@/pages/Login/index.vue"; import HomeView from "@/pages/Layout/index.vue"; - +import { mockBackendMenuData } from "@/mock/menu"; const tokenManager = TokenManager.getInstance(); // 基础路由(不需要权限验证) const constantRoutes: RouteRecordRaw[] = [ @@ -143,44 +143,7 @@ const addDynamicRoutes = async () => { // 从后端获取路由菜单数据 (这边需要区分 后台的菜单 和用户的菜单) let allRoutes:any[] = []; if (userStore.isBackendUser) { - // const backendResponse = await getRouteMenus(); - const backendResponse = [ - { - "name": "字典管理", - "code": "dict", - "icon": "OfficeBuilding", - "metadata": null, - "children": null - }, - { - "name": "组织管理", - "code": "origanization", - "icon": "OfficeBuilding", - "metadata": null, - "children": null - }, - { - "name": "人员管理", - "code": "personnel", - "icon": "OfficeBuilding", - "metadata": null, - "children": null - }, - { - "name": "权限管理", - "code": "permission", - "icon": "OfficeBuilding", - "metadata": null, - "children": null - }, - { - "name": "流程管理", - "code": "flow", - "icon": "OfficeBuilding", - "metadata": null, - "children": null - } - ]; + const backendResponse = await getRouteMenus(); allRoutes = [ { code: "stage", @@ -189,7 +152,7 @@ const addDynamicRoutes = async () => { meta:{ title:'管理中心' }, - children: backendResponse, + children: Object.keys(backendResponse).length ? backendResponse : mockBackendMenuData, }, ]; } else { diff --git a/src/styles/common.scss b/src/styles/common.scss index 080770e..2d63057 100644 --- a/src/styles/common.scss +++ b/src/styles/common.scss @@ -22,13 +22,14 @@ body { } +// popover 筛选框的全局样式 .filter-popper.el-popover.el-popper { --el-popover-padding: 0; border-radius: var(--mj-popper-radius); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); } -// 全局重新element相关样式 +// 全局重写element相关样式 .mj-input-form { .el-input { --el-border-radius-base: 10px; @@ -38,7 +39,7 @@ body { // 搜索框动画 -.search-dict-input { +.search-auto-expand-input { --default-width: 160px; --max-width: 224px; width: var(--default-width); @@ -71,7 +72,7 @@ body { } -// 筛选框全局样式内容 +// 筛选框内容的全局样式内容 .mj-filter-content { min-width: 380px; background: #fff; @@ -132,4 +133,42 @@ body { border-color: #407eff; } } +} + + + +// 全局单行省略样式 +.mj-ellipsis-one-line { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + + + +// 卡片的全局样式 + +.mj-card-container{ + display: grid; + gap: 16px; + width: 100%; + // 默认:一行 5 列 + grid-template-columns: repeat(5, 1fr); + // 1400px 以下:觉得 5 个太挤,切到一行 4 列 + @media (max-width: 1400px) { + grid-template-columns: repeat(4, 1fr); + } + // 1100px 以下 (iPad横屏区间):一行 3 列 + @media (max-width: 1100px) { + grid-template-columns: repeat(3, 1fr); + } + // 768px 以下 (iPad竖屏):一行 2 列 + @media (max-width: 768px) { + grid-template-columns: repeat(2, 1fr); + gap: 12px; + } + // 480px 以下 (手机端):一行 1 列 + @media (max-width: 480px) { + grid-template-columns: repeat(1, 1fr); + } } \ No newline at end of file