Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	memory/index.md
Kazerin 2 giorni fa
parent
commit
3f017a29a5

+ 0 - 1
memory/index.md

@@ -54,4 +54,3 @@ npm run dev       # 默认 http://localhost:80
 - [2026-08-21:工程技能仓库配置](sessions/2026-08-21.md)
 - [2026-08-22:供水报警与工单前端适配设计](sessions/2026-08-22.md)
 - [2026-09-01:供水管网数据统计分析 T3](sessions/2026-09-01.md)
-- [2026-09-02:阈值管理 T5](sessions/2026-09-02.md)

+ 6 - 18
src/components/Breadcrumb/index.vue

@@ -19,18 +19,14 @@ function getBreadcrumb() {
   let matched = route.matched.filter(item => item.meta && item.meta.title);
   const first = matched[0]
 
-  // ===================== 【核心:子系统不显示首页】 =====================
-  const isSubSystem = route.path.startsWith(first.path);
-
-  // const currentPath = route.path
-  // const allRoutes = permissionStore.sidebarRouters
-  // const prefix = currentPath.split('/')[1]
-
-  // 只有【不是子系统】时,才添加首页
-  if (!isDashboard(first) && !isSubSystem) {
-    matched = [{path: '/index', meta: {title: '首页'}}].concat(matched)
+  if (!first) {
+    levelList.value = []
+    return
   }
 
+  // ===================== 【核心:子系统与总后台各自只显示自己的层级】 =====================
+  const isSubSystem = route.path.startsWith(first.path);
+
   // ===================== 【核心:彻底隔离子系统 / 总后台】 =====================
   if (isSubSystem) {
     // 子系统:只保留子系统路由,过滤总后台
@@ -45,14 +41,6 @@ function getBreadcrumb() {
   }
 }
 
-function isDashboard(route) {
-  const name = route && route.name
-  if (!name) {
-    return false
-  }
-  return ['Index', 'MainAdminHome'].includes(name.trim())
-}
-
 function handleLink(item) {
   const {redirect, path} = item
   if (redirect) {

+ 1 - 1
src/layout/components/Navbar.vue

@@ -100,7 +100,7 @@ function logout() {
     type: 'warning'
   }).then(() => {
     userStore.logOut().then(() => {
-      location.href = '/index';
+      location.href = '/';
     })
   }).catch(() => {
   });

+ 1 - 1
src/layout/components/TagsView/index.vue

@@ -276,7 +276,7 @@ function toLastView(visitedViews, view) {
     } else if (prefix === 'dispatch') {
       router.push('/dispatch/index')
     } else {
-      router.push('/index')
+      router.push('/')
     }
   }
 }

+ 7 - 15
src/router/index.js

@@ -32,6 +32,9 @@ import { mergeRouteRecords } from './routeUtils'
  }
  */
 
+// 进入总后台后的默认落地页(原写死的 /index 首页菜单已移除)
+export const DEFAULT_BACKEND_HOME = '/system/user'
+
 // 公共路由
 export const constantRoutes = mergeRouteRecords(
   [
@@ -73,22 +76,11 @@ export const constantRoutes = mergeRouteRecords(
     hidden: true
   },
 
-  // 原若依首页(总后台标记)
+  // 根路径直接落到默认后台页面,不再保留写死的首页菜单
   {
-    path: '',
-    component: Layout,
-    redirect: '/index',
-    meta: { isMainAdmin: true }, // 总后台标记
-    children: [
-      {
-        path: '/index',
-        component: () => import('@/views/index'),
-        // Keep this name unique: backend menu paths such as "index" are also
-        // normalized to the route name "Index" by the dynamic router builder.
-        name: 'MainAdminHome',
-        meta: { title: '首页', icon: 'dashboard', affix: true }
-      }
-    ]
+    path: '/',
+    redirect: DEFAULT_BACKEND_HOME,
+    hidden: true
   },
 
   {

+ 1 - 1
src/utils/request.js

@@ -92,7 +92,7 @@ service.interceptors.response.use(res => {
         ElMessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => {
           isRelogin.show = false;
           useUserStore().logOut().then(() => {
-            location.href = '/index';
+            location.href = '/';
           })
       }).catch(() => {
         isRelogin.show = false;

+ 1 - 1
src/views/error/404.vue

@@ -17,7 +17,7 @@
         <div class="bullshit__info">
           对不起,您正在寻找的页面不存在。尝试检查URL的错误,然后按浏览器上的刷新按钮或尝试在我们的应用程序中找到其他内容。
         </div>
-        <router-link to="/index" class="bullshit__return-home">
+        <router-link to="/" class="bullshit__return-home">
           返回首页
         </router-link>
       </div>

+ 10 - 7
src/views/portal/index.vue

@@ -44,9 +44,10 @@
 <script setup lang="ts">
 import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue'
 import { useRouter } from 'vue-router'
+import { DEFAULT_BACKEND_HOME } from '@/router'
 import useUserStore from '@/store/modules/user'
 import usePermissionStore from '@/store/modules/permission'
-import { ElMessageBox, ElMessage } from 'element-plus'
+import { ElMessageBox } from 'element-plus'
 
 const router = useRouter()
 const userStore = useUserStore()
@@ -235,21 +236,23 @@ const loadDynamicModules = () => {
 // 进入后台
 // ==============================================
 const enterBackend = () => {
-  router.push('/index')
+  router.push(DEFAULT_BACKEND_HOME)
 }
 
 // ==============================================
-// 退出系统(文件1逻辑
+// 退出系统(与 Navbar 保持一致
 // ==============================================
 const logout = () => {
   ElMessageBox.confirm('确定要退出登录吗?', '提示', {
     confirmButtonText: '确定',
     cancelButtonText: '取消',
     type: 'warning'
-  }).then(async () => {
-    await userStore.logout()
-    ElMessage.success('退出成功')
-    router.push('/login')
+  }).then(() => {
+    // Store 中的方法名是 logOut,logout() 不存在,调用会静默失败导致没有真正退出
+    userStore.logOut().then(() => {
+      // 整页跳转回登录页,刷新路由实例以清除已动态注册的路由
+      location.href = '/login'
+    })
   }).catch(() => {})
 }
 

+ 1 - 1
src/views/subSystem/drainage/jcsj/jsqc.vue

@@ -357,7 +357,7 @@ function goBack() {
   router.push('/')
 }
 function goAdmin() {
-  router.push('/index')
+  router.push('/')
 }
 
 // ==================== 地图初始化 ====================

+ 77 - 13
src/views/subSystem/pipeNetwork/pdeviceInform/PequipmentLed.vue

@@ -104,7 +104,7 @@
                 {{ typeNameMap[scope.row.equipmentTypeId] || scope.row.equipmentTypeId || "-" }}
               </template>
             </el-table-column>
-            <el-table-column label="当前状态" align="center" width="110">
+            <el-table-column label="资产状态" align="center" width="110">
               <template #default="scope">
                 <el-tag :type="getStatusTagType(getRowStatus(scope.row.equipmentId))">
                   {{ getStatusText(getRowStatus(scope.row.equipmentId)) }}
@@ -116,7 +116,7 @@
               <template #default="scope">
                 <el-button link type="primary" icon="View" @click.stop="handleView(scope.row)">详情</el-button>
                 <el-button link type="primary" icon="Edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
-                <el-button link type="warning" icon="Tools" @click.stop="openStatusDialog(scope.row)">状态维护</el-button>
+                <el-button link type="warning" icon="Tools" @click.stop="openStatusDialog(scope.row)">资产状态维护</el-button>
                 <el-button link type="success" icon="Aim" @click.stop="openTestDialog(scope.row)">测试验证</el-button>
                 <el-button link type="danger" icon="Delete" @click.stop="handleDelete(scope.row)">删除</el-button>
               </template>
@@ -172,8 +172,8 @@
             <div class="section-block">
               <div class="section-title">关联点位</div>
               <el-table :data="selectedDetail.pointRelList || []" size="small" max-height="180">
-                <el-table-column label="监测点ID" prop="pointId" min-width="160" show-overflow-tooltip />
-                <el-table-column label="设备ID" prop="equipmentId" min-width="160" show-overflow-tooltip />
+                <el-table-column label="监测点编码" prop="pointCode" min-width="160" show-overflow-tooltip />
+                <el-table-column label="监测点名称" prop="pointName" min-width="160" show-overflow-tooltip />
               </el-table>
             </div>
 
@@ -210,14 +210,16 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="设备类型" prop="equipmentTypeId">
-              <el-select v-model="form.equipmentTypeId" placeholder="请选择设备类型" style="width: 100%">
-                <el-option
-                  v-for="item in equipmentTypeOptions"
-                  :key="item.typeId"
-                  :label="item.typeName"
-                  :value="item.typeId"
-                />
-              </el-select>
+              <el-tree-select
+                v-model="form.equipmentTypeId"
+                :data="equipmentTypeTree"
+                node-key="typeId"
+                :props="{ label: 'typeName', children: 'children', disabled: 'disabled' }"
+                default-expand-all
+                :render-after-expand="false"
+                placeholder="请选择设备类型"
+                style="width: 100%"
+              />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -307,7 +309,7 @@
         <el-form-item label="设备名称">
           <span>{{ currentRow.equipmentName || "-" }}</span>
         </el-form-item>
-        <el-form-item label="当前状态">
+        <el-form-item label="资产状态">
           <el-select v-model="statusForm.currentStatus" style="width: 100%">
             <el-option
               v-for="item in equipmentStatusOptions"
@@ -406,6 +408,68 @@ const typeNameMap = computed(() => {
   }, {});
 });
 
+// parentTypeId 为 0(或空)表示父类
+function isTopLevelType(item) {
+  const parentTypeId = item?.parentTypeId;
+  return parentTypeId === 0 || parentTypeId === "0" || parentTypeId === null || parentTypeId === undefined || parentTypeId === "";
+}
+
+const equipmentTypeTree = computed(() => {
+  const list = equipmentTypeOptions.value || [];
+  const entries = [];
+  // 同时按 typeId / id 建索引,兼容 parentTypeId 指向不同主键字段的情况
+  const nodeIndex = {};
+
+  list.forEach((item) => {
+    const node = {
+      typeId: item.typeId,
+      typeName: item.typeName,
+      disabled: isTopLevelType(item),
+      children: []
+    };
+    entries.push({ item, node });
+    [item.typeId, item.id].forEach((key) => {
+      if (key !== undefined && key !== null) {
+        nodeIndex[String(key)] = node;
+      }
+    });
+  });
+
+  const roots = [];
+  // 父节点不在返回列表中时兜底归类,避免子类型在下拉中丢失
+  const fallbackNode = { typeId: "__other__", typeName: "未分类", disabled: true, children: [] };
+
+  entries.forEach(({ item, node }) => {
+    if (isTopLevelType(item)) {
+      roots.push(node);
+      return;
+    }
+    const parent = nodeIndex[String(item.parentTypeId)];
+    if (parent && parent !== node) {
+      parent.children.push(node);
+    } else {
+      fallbackNode.children.push(node);
+    }
+  });
+
+  // 带子级的节点(即父类)统一禁选,叶子节点可选;空 children 去掉渲染为叶子
+  const prune = (node) => {
+    if (node.children && node.children.length) {
+      node.disabled = true;
+      node.children.forEach(prune);
+    } else {
+      delete node.children;
+    }
+    return node;
+  };
+
+  const result = roots.map(prune);
+  if (fallbackNode.children.length) {
+    result.push(prune(fallbackNode));
+  }
+  return result;
+});
+
 const statusMap = computed(() => {
   return equipmentStatusList.value.reduce((acc, item) => {
     acc[item.equipmentId] = item;

+ 1 - 3
src/views/subSystem/pipeNetwork/pdeviceInform/PkeyPoints.vue

@@ -104,6 +104,7 @@
             @row-click="handleRowClick"
           >
             <el-table-column type="selection" width="55" align="center" />
+            <el-table-column label="监测点编码" prop="pointCode" min-width="120" show-overflow-tooltip />
             <el-table-column label="监测点名称" prop="pointName" min-width="170" show-overflow-tooltip />
             <el-table-column label="监测类型" prop="pointType" min-width="110" />
             <el-table-column label="状态" width="90">
@@ -120,9 +121,6 @@
             </el-table-column>
             <el-table-column label="操作" align="center" width="150">
               <template #default="scope">
-                <el-button link type="primary" icon="Connection" @click.stop="openBindDialog(scope.row)">
-                  关联设备
-                </el-button>
                 <el-button link type="primary" icon="Edit" @click.stop="handleUpdate(scope.row)">修改</el-button>
               </template>
             </el-table-column>