All checks were successful
continuous-integration/drone/push Build is passing
- 新增 platform_notification_channels 表管理通知渠道(钉钉/企微机器人)
- 新增通知渠道管理页面,支持创建、编辑、测试、删除
- 定时任务增加通知渠道选择和企微应用选择
- 脚本执行支持返回值(result变量),自动发送到配置的渠道
- 调度器执行脚本后根据配置自动发送通知
使用方式:
1. 在「通知渠道」页面为租户配置钉钉/企微机器人
2. 创建定时任务时选择通知渠道
3. 脚本中设置 result = {'content': '内容', 'title': '标题'}
4. 任务执行后自动发送到配置的渠道
110 lines
3.5 KiB
Vue
110 lines
3.5 KiB
Vue
<script setup>
|
|
import { computed } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import { ElMessageBox } from 'element-plus'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const authStore = useAuthStore()
|
|
|
|
// 菜单项
|
|
const menuItems = computed(() => {
|
|
const items = [
|
|
{ path: '/dashboard', title: '仪表盘', icon: 'Odometer' },
|
|
{ path: '/tenants', title: '租户管理', icon: 'OfficeBuilding' },
|
|
{ path: '/apps', title: '应用管理', icon: 'Grid' },
|
|
{ path: '/tenant-wechat-apps', title: '企微应用', icon: 'ChatDotRound' },
|
|
{ path: '/app-config', title: '租户订阅', icon: 'Setting' },
|
|
{ path: '/stats', title: '统计分析', icon: 'TrendCharts' },
|
|
{ path: '/logs', title: '日志查看', icon: 'Document' },
|
|
{ path: '/scheduled-tasks', title: '定时任务', icon: 'Clock' },
|
|
{ path: '/notification-channels', title: '通知渠道', icon: 'Bell' }
|
|
]
|
|
|
|
// 管理员才能看到用户管理
|
|
if (authStore.isAdmin) {
|
|
items.push({ path: '/users', title: '用户管理', icon: 'User' })
|
|
}
|
|
|
|
return items
|
|
})
|
|
|
|
const activeMenu = computed(() => route.path)
|
|
|
|
function handleMenuSelect(path) {
|
|
router.push(path)
|
|
}
|
|
|
|
function handleLogout() {
|
|
ElMessageBox.confirm('确定要退出登录吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
authStore.logout()
|
|
router.push('/login')
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="layout">
|
|
<!-- 侧边栏 -->
|
|
<aside class="sidebar">
|
|
<div class="logo">
|
|
<el-icon><Platform /></el-icon>
|
|
<span style="margin-left: 8px">平台管理</span>
|
|
</div>
|
|
|
|
<el-menu
|
|
:default-active="activeMenu"
|
|
background-color="transparent"
|
|
text-color="rgba(255,255,255,0.7)"
|
|
active-text-color="#fff"
|
|
@select="handleMenuSelect"
|
|
>
|
|
<el-menu-item v-for="item in menuItems" :key="item.path" :index="item.path">
|
|
<el-icon><component :is="item.icon" /></el-icon>
|
|
<span>{{ item.title }}</span>
|
|
</el-menu-item>
|
|
</el-menu>
|
|
</aside>
|
|
|
|
<!-- 主内容区 -->
|
|
<div class="main-container">
|
|
<!-- 顶部栏 -->
|
|
<header class="header">
|
|
<div class="breadcrumb">
|
|
<el-breadcrumb separator="/">
|
|
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
|
|
<el-breadcrumb-item v-if="route.meta.title">{{ route.meta.title }}</el-breadcrumb-item>
|
|
</el-breadcrumb>
|
|
</div>
|
|
|
|
<div class="user-info">
|
|
<span class="username">{{ authStore.user?.nickname || authStore.user?.username }}</span>
|
|
<el-dropdown trigger="click">
|
|
<el-avatar :size="32">
|
|
{{ (authStore.user?.nickname || authStore.user?.username || 'U')[0].toUpperCase() }}
|
|
</el-avatar>
|
|
<template #dropdown>
|
|
<el-dropdown-menu>
|
|
<el-dropdown-item @click="handleLogout">
|
|
<el-icon><SwitchButton /></el-icon>
|
|
退出登录
|
|
</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- 内容区 -->
|
|
<main class="main-content">
|
|
<router-view />
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</template>
|