董国庆
2026-02-25 02cc5f5fc960f7b68fd1a4fecb422e08c8eebafc
系统价权限和按钮权限判断
2个文件已添加
8个文件已修改
309 ■■■■■ 已修改文件
.env 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/guard.ts 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/routes.static.ts 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/assetManagement/ruleConfig/index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/accountPermission/accountManagement/index.vue 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/accountPermission/permissionGroup/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/accountPermission/roleManagement/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/appVersion/appVersionManage/index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/appVersion/hotfix/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/config/index.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env
@@ -11,7 +11,7 @@
VITE_ROUTE_LOAD_MODE = static
# 设置登陆后跳转地址
VITE_HOME_PATH = /
VITE_HOME_PATH = /dashboard
# 本地存储前缀
VITE_STORAGE_PREFIX =
src/router/guard.ts
@@ -38,17 +38,24 @@
    // 如果是login路由,直接放行
    if (to.name === 'login') {
      // login页面不需要任何认证检查,直接放行
      // 继续执行后面的逻辑
      // 如果已登录,则重定向到首页
      if (isLogin) {
        next({ path: '/dashboard' })
        return
      }
      next()
      return
    }
    // 如果路由明确设置了requiresAuth为false,直接放行
    else if (to.meta.requiresAuth === false) {
      // 明确设置为false的路由直接放行
      // 继续执行后面的逻辑
      next()
      return
    }
    // 如果路由设置了requiresAuth为true,且用户未登录,重定向到登录页
    else if (to.meta.requiresAuth === true && !isLogin) {
    else if (to.meta.requiresAuth !== false && !isLogin) {
      const redirect = to.name === 'not-found' ? undefined : to.fullPath
      next({ path: '/login', query: { redirect } })
      next({ path: '/login', query: redirect ? { redirect } : undefined })
      return
    }
@@ -67,8 +74,8 @@
          })
          return
        }
        // 如果不是404页面,继续导航
        next()
        // 如果不是404页面,继续导航,并设置 replace: true 以确保路由正确替换
        next({ ...to, replace: true })
        return
      }
      catch {
@@ -80,16 +87,24 @@
    }
    // 如果用户已登录且访问login页面,重定向到首页
    if (to.name === 'login' && isLogin) {
      next({ path: '/' })
      return
    }
    // 此逻辑已移至上方处理
    next()
  })
  router.beforeResolve((to) => {
    // 设置菜单高亮
    routeStore.setActiveMenu(to.meta.activeMenu ?? to.fullPath)
    // 设置菜单高亮,优先将 activeMenu 的路径转换为对应的菜单 key(路由 name)
    let activeKey: string
    if (to.meta.activeMenu) {
      const target = routeStore.rowRoutes.find(r => r.path === to.meta.activeMenu)
      activeKey = (target?.name as string) || (to.meta.activeMenu as string)
    }
    else if (to.name) {
      activeKey = to.name as string
    }
    else {
      activeKey = to.fullPath
    }
    routeStore.setActiveMenu(activeKey)
    // 添加tabs
    tabStore.addTab(to)
    // 设置高亮标签;
src/router/routes.static.ts
@@ -114,6 +114,17 @@
    id: 2021,
    pid: 202,
  },
   {
    name: 'appVersionManage',
    path: '/system/appVersion/appVersionManage',
    title: 'APP版本管理',
    requiresAuth: true,
    icon: 'icon-park-outline:tool',
    menuType: 'page',
    componentPath: '/system/appVersion/appVersionManage/index.vue',
    id: 2021,
    pid: 202,
  },
  {
    name: 'systemConfig',
    path: '/system/config',
@@ -213,6 +224,7 @@
    id: 3022,
    pid: 302,
  },
  // 新增页面--活动
  {
    name: 'businessOperations',
    path: '/businessOperations',
@@ -342,7 +354,7 @@
    menuType: 'page',
    componentPath: '/businessOperations/cruise/parade-plan/add.vue',
    id: 4073,
    pid: 407,
    pid: 4072,
    hide: true, // 不在菜单中显示
    activeMenu: '/businessOperations/cruise/parade-plan',
  },
@@ -355,7 +367,7 @@
    menuType: 'page',
    componentPath: '/businessOperations/cruise/parade-plan/detail.vue',
    id: 4074,
    pid: 407,
    pid: 4072,
    hide: true, // 不在菜单中显示
    activeMenu: '/businessOperations/cruise/parade-plan',
  },
@@ -453,6 +465,18 @@
    hide: true, // 不在菜单中显示
    activeMenu: '/assetManagement/fleetManagement',
  },
  // 新增页面--运维规则配置
  {
    name: 'ruleConfig',
    path: '/assetManagement/ruleConfig',
    title: '运维规则配置',
    requiresAuth: true,
    icon: 'icon-park-outline:list-view',
    menuType: 'page',
    componentPath: '/assetManagement/ruleConfig/index.vue',
    id: 503,
    pid: 5,
  },
  {
    name: 'transaction',
    path: '/transaction',
@@ -529,8 +553,8 @@
    icon: 'icon-park-outline:vip-1',
    menuType: 'page',
    componentPath: '/transaction/pricingManagement/detail.vue',
    id: 603,
    pid: 6,
    id: 6021,
    pid: 602,
    hide: true, // 不在菜单中显示
    activeMenu: '/transaction/pricingManagement',
  },
@@ -542,8 +566,8 @@
    icon: 'icon-park-outline:vip-1',
    menuType: 'page',
    componentPath: '/transaction/pricingManagement/detail.vue',
    id: 604,
    pid: 6,
    id: 6024,
    pid: 602,
    hide: true, // 不在菜单中显示
    activeMenu: '/transaction/pricingManagement',
  },
@@ -555,8 +579,8 @@
    icon: 'icon-park-outline:vip-1',
    menuType: 'page',
    componentPath: '/transaction/pricingManagement/rules.vue',
    id: 605,
    pid: 6,
    id: 6022,
    pid: 602,
    hide: true, // 不在菜单中显示
    activeMenu: '/transaction/pricingManagement',
  },
@@ -568,7 +592,7 @@
    icon: 'icon-park-outline:alarm',
    menuType: 'page',
    componentPath: '/transaction/transactionStrategy/index.vue',
    id: 606,
    id: 605,
    pid: 6,
  },
  {
@@ -579,7 +603,7 @@
    icon: 'icon-park-outline:alarm',
    menuType: 'page',
    componentPath: '/transaction/navigationAndRoutePlanning/index.vue',
    id: 607,
    id: 606,
    pid: 6,
  },
  {
@@ -623,8 +647,8 @@
    icon: 'icon-park-outline:list-view',
    menuType: 'page',
    componentPath: '/operations/personnel/personnelManagement/detail.vue',
    id: 7012,
    pid: 701,
    id: 70111,
    pid: 7011,
    hide: true,
    activeMenu: '/operations/personnel/personnelManagement',
  },
@@ -668,8 +692,8 @@
    icon: 'icon-park-outline:list-view',
    menuType: 'page',
    componentPath: '/operations/attendance/statistics/detail.vue',
    id: 7023,
    pid: 702,
    id: 70222,
    pid: 7022,
    hide: true,
    activeMenu: '/operations/attendance/statistics',
  },
@@ -703,8 +727,8 @@
    icon: 'icon-park-outline:list-view',
    menuType: 'page',
    componentPath: '/operations/attendance/plan/edit.vue',
    id: 7026,
    pid: 702,
    id: 70251,
    pid: 7025,
    hide: true,
    activeMenu: '/operations/attendance/plan',
  },{
@@ -715,8 +739,8 @@
    icon: 'icon-park-outline:list-view',
    menuType: 'page',
    componentPath: '/operations/attendance/plan/copy.vue',
    id: 7027,
    pid: 702,
    id: 70252,
    pid: 7025,
    hide: true,
    activeMenu: '/operations/attendance/plan',
  },
@@ -731,6 +755,7 @@
    id: 704,
    pid: 7,
  },
  // 新增页面--任务工单
  {
    name: 'service',
    path: '/service',
src/views/assetManagement/ruleConfig/index.vue
New file
@@ -0,0 +1,86 @@
<script setup lang="ts">
import { ref } from 'vue'
import type { FormInst, FormRules } from 'naive-ui'
interface FormModel {
  maintenanceStatus: boolean
  startTime: number | null
  endTime: number | null
}
const formRef = ref<FormInst | null>(null)
const formModel = ref<FormModel>({
  maintenanceStatus: true,
  startTime: null,
  endTime: null
})
const rules: FormRules = {
  startTime: [
    { required: true, type: 'number', message: '请选择开始维护时间', trigger: 'change' }
  ],
  endTime: [
    { required: true, type: 'number', message: '请选择预计结束时间', trigger: 'change' }
  ]
}
const handleSave = async () => {
  try {
    await formRef.value?.validate()
    console.log('保存配置', formModel.value)
    window.$message?.success('保存成功')
  } catch (error) {
    console.log('验证失败', error)
  }
}
</script>
<template>
  <div class="h-full flex flex-col">
    <n-card content-style="padding: 12px">
      <n-form
        ref="formRef"
        :model="formModel"
        :rules="rules"
        label-placement="left"
        inline
        :show-feedback="false"
        require-mark-placement="left"
      >
        <n-space vertical :size="16">
          <n-form-item label="维护状态" required>
            <n-switch v-model:value="formModel.maintenanceStatus" />
          </n-form-item>
          <n-form-item label="开始维护时间" path="startTime" required>
            <n-date-picker
              v-model:value="formModel.startTime"
              type="datetime"
              placeholder="年/月/日 --:--"
              style="width: 400px;"
              clearable
            />
          </n-form-item>
          <n-form-item label="预计结束时间" path="endTime" required>
            <n-date-picker
              v-model:value="formModel.endTime"
              type="datetime"
              placeholder="年/月/日 --:--"
              style="width: 400px;"
              clearable
            />
          </n-form-item>
        </n-space>
      </n-form>
    </n-card>
    <div class="absolute bottom-0 left-0 right-0 flex justify-end gap-3 bg-white px-6 py-4" style="box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); z-index: 100">
      <n-button type="primary" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
    </div>
  </div>
</template>
<style scoped>
</style>
src/views/system/accountPermission/accountManagement/index.vue
@@ -140,16 +140,17 @@
    render: (row) => {
      return (
        <NSpace justify="center">
          <NButton
          {/* <NButton
            text
            type="primary"
            onClick={() => handleView(row)}
          >
            查看
          </NButton>
          </NButton> */}
          <NButton
            text
            type="primary"
            v-permission="20112"
            onClick={() => handleEdit(row)}
          >
            编辑
@@ -159,6 +160,7 @@
                <NButton
                  text
                  type="warning"
                  v-permission="20113"
                  onClick={() => toggleAccountStatus(row.id!, '1')}
                >
                  禁用
@@ -168,6 +170,7 @@
                <NButton
                  text
                  type="success"
                  v-permission="20113"
                  onClick={() => toggleAccountStatus(row.id!, '0')}
                >
                  启用
@@ -176,11 +179,19 @@
          <NButton
            text
            type="primary"
            v-permission="20114"
            onClick={() => handleResetPassword(row)}
          >
            重置密码
          </NButton>
          <NButton text type="error" onClick={() => deleteAccount(row.id!)}>删除</NButton>
          <NButton
            text
            type="error"
            v-permission="20115"
            onClick={() => deleteAccount(row.id!)}
          >
            删除
          </NButton>
        </NSpace>
      )
    },
@@ -326,7 +337,7 @@
      <n-card class="flex-1">
        <template #header>
          <NButton type="primary" @click="handleAdd">
          <NButton type="primary" v-permission="20111" @click="handleAdd">
            新增
          </NButton>
        </template>
src/views/system/accountPermission/permissionGroup/index.vue
@@ -72,6 +72,7 @@
          <NButton
            text
            type="primary"
            v-permission="20132"
            onClick={() => handleView(row)}
          >
            详情
@@ -79,6 +80,7 @@
          <NButton
            text
            type="primary"
            v-permission="20133"
            onClick={() => handleEdit(row)}
          >
            编辑
@@ -93,6 +95,7 @@
                <NButton
                  text
                  type="error"
                  v-permission="20134"
                  disabled={hasAccounts}
                >
                  删除
@@ -205,7 +208,7 @@
      <n-card class="flex-1">
        <template #header>
          <NButton type="primary" @click="handleAdd">
          <NButton type="primary" v-permission="20131" @click="handleAdd">
            新增
          </NButton>
        </template>
src/views/system/accountPermission/roleManagement/index.vue
@@ -71,6 +71,7 @@
          <NButton
            text
            type="primary"
            v-permission="20152"
            onClick={() => handleView(row)}
          >
            详情
@@ -78,6 +79,7 @@
          <NButton
            text
            type="primary"
            v-permission="20153"
            onClick={() => handleEdit(row)}
          >
            编辑
@@ -85,6 +87,7 @@
          <NButton
            text
            type="error"
            v-permission="20154"
            disabled={hasAccounts}
            onClick={() => handleDelete(row.id!)}
          >
@@ -212,7 +215,7 @@
      <n-card class="flex-1">
        <template #header>
          <NButton type="primary" @click="handleAdd">
          <NButton type="primary" v-permission="20151" @click="handleAdd">
            新增
          </NButton>
        </template>
src/views/system/appVersion/appVersionManage/index.vue
New file
@@ -0,0 +1,86 @@
<script setup lang="ts">
import { ref } from 'vue'
import type { FormInst, FormRules } from 'naive-ui'
interface FormModel {
  maintenanceStatus: boolean
  startTime: number | null
  endTime: number | null
}
const formRef = ref<FormInst | null>(null)
const formModel = ref<FormModel>({
  maintenanceStatus: true,
  startTime: null,
  endTime: null
})
const rules: FormRules = {
  startTime: [
    { required: true, type: 'number', message: '请选择开始维护时间', trigger: 'change' }
  ],
  endTime: [
    { required: true, type: 'number', message: '请选择预计结束时间', trigger: 'change' }
  ]
}
const handleSave = async () => {
  try {
    await formRef.value?.validate()
    console.log('保存配置', formModel.value)
    window.$message?.success('保存成功')
  } catch (error) {
    console.log('验证失败', error)
  }
}
</script>
<template>
  <div class="h-full flex flex-col">
    <n-card content-style="padding: 12px">
      <n-form
        ref="formRef"
        :model="formModel"
        :rules="rules"
        label-placement="left"
        inline
        :show-feedback="false"
        require-mark-placement="left"
      >
        <n-space vertical :size="16">
          <n-form-item label="维护状态" required>
            <n-switch v-model:value="formModel.maintenanceStatus" />
          </n-form-item>
          <n-form-item label="开始维护时间" path="startTime" required>
            <n-date-picker
              v-model:value="formModel.startTime"
              type="datetime"
              placeholder="年/月/日 --:--"
              style="width: 400px;"
              clearable
            />
          </n-form-item>
          <n-form-item label="预计结束时间" path="endTime" required>
            <n-date-picker
              v-model:value="formModel.endTime"
              type="datetime"
              placeholder="年/月/日 --:--"
              style="width: 400px;"
              clearable
            />
          </n-form-item>
        </n-space>
      </n-form>
    </n-card>
    <div class="absolute bottom-0 left-0 right-0 flex justify-end gap-3 bg-white px-6 py-4" style="box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); z-index: 100">
      <n-button type="primary" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
    </div>
  </div>
</template>
<style scoped>
</style>
src/views/system/appVersion/hotfix/index.vue
@@ -77,7 +77,7 @@
    </n-card>
    <div class="absolute bottom-0 left-0 right-0 flex justify-end gap-3 bg-white px-6 py-4" style="box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); z-index: 100">
      <n-button type="primary" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
      <n-button type="primary" v-permission="201211" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
    </div>
  </div>
</template>
src/views/system/config/index.vue
@@ -158,7 +158,7 @@
    </n-card>
    <div class="absolute bottom-0 left-0 right-0 flex justify-end gap-3 bg-white px-6 py-4" style="box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1); z-index: 100">
            <n-button type="primary" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
            <n-button type="primary" v-permission="2031" style="width: 84px; height: 32px" @click="handleSave">保存</n-button>
        </div>
  </div>
</template>