提交 0259b09d authored 作者: matian's avatar matian

增加权限

上级 df2c6b5d
...@@ -32,15 +32,20 @@ const defaultActive = computed(() => { ...@@ -32,15 +32,20 @@ const defaultActive = computed(() => {
<nav class="nav"> <nav class="nav">
<el-menu :default-active="defaultActive" :router="true"> <el-menu :default-active="defaultActive" :router="true">
<template v-for="item in menus" :key="item.path"> <template v-for="item in menus" :key="item.path">
<el-sub-menu :index="item.path" v-if="item.children"> <el-sub-menu :index="item.path" v-permission="item.tag" v-if="item.children">
<template #title> <template #title>
<el-icon><component :is="item.icon"></component></el-icon>{{ item.name }} <el-icon><component :is="item.icon"></component></el-icon>{{ item.name }}
</template> </template>
<el-menu-item :index="subitem.path" v-for="subitem in item.children" :key="subitem.path"> <el-menu-item
:index="subitem.path"
v-for="subitem in item.children"
:key="subitem.path"
v-permission="subitem.tag"
>
{{ subitem.name }} {{ subitem.name }}
</el-menu-item> </el-menu-item>
</el-sub-menu> </el-sub-menu>
<el-menu-item :index="item.path" v-else> <el-menu-item :index="item.path" v-permission="item.tag" v-else>
<el-icon><component :is="item.icon"></component></el-icon>{{ item.name }} <el-icon><component :is="item.icon"></component></el-icon>{{ item.name }}
</el-menu-item> </el-menu-item>
</template> </template>
......
...@@ -3,15 +3,15 @@ export default { name: 'AppHeader' } ...@@ -3,15 +3,15 @@ export default { name: 'AppHeader' }
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import { useUserStore } from '@/stores/user' import { useInfoStore } from '@/stores/index'
withDefaults(defineProps<{ hasTitle?: boolean }>(), { withDefaults(defineProps<{ hasTitle?: boolean }>(), {
hasTitle: true hasTitle: true
}) })
const userStore = useUserStore() const userStore = useInfoStore()
const userInfo = userStore.user const userInfo = userStore.info
const logout = async () => { const logout = async () => {
await userStore.logout() await userStore.logout()
...@@ -39,7 +39,7 @@ const logout = async () => { ...@@ -39,7 +39,7 @@ const logout = async () => {
<img :src="userInfo.avatar || 'https://webapp-pub.ezijing.com/website/base/images/avatar.svg'" /> <img :src="userInfo.avatar || 'https://webapp-pub.ezijing.com/website/base/images/avatar.svg'" />
</div> </div>
<div class="app-header-user-main"> <div class="app-header-user-main">
<h3>{{ userStore.userName }}</h3> <h3>{{ userStore.name }}</h3>
<p>{{ userInfo.email || userInfo.mobile }}</p> <p>{{ userInfo.email || userInfo.mobile }}</p>
</div> </div>
<div class="app-header-user-buttons"> <div class="app-header-user-buttons">
......
...@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout, component: AppLayout,
children: [ children: [
{ path: '', component: () => import('./views/List.vue') }, { path: '', component: () => import('./views/List.vue') },
{ path: '/channel/bp/detail/:id', component: () => import('./views/View.vue'), props: true } { path: '/channel/bp/detail', component: () => import('./views/View.vue') }
] ]
} }
] ]
<script setup lang="ts"> <script setup lang="ts">
import shortcuts from '@/utils/shortcut'
import { getConditionList, getChannelList } from '../api' import { getConditionList, getChannelList } from '../api'
const router = useRouter()
const tagsList = ref([]) const tagsList = ref([])
getConditionList({ channel: true }).then(res => { getConditionList({ channel: true }).then(res => {
tagsList.value = res.data.channel.tags.reduce((t: any, cur: any) => { tagsList.value = res.data.channel.tags.reduce((t: any, cur: any) => {
t.push({ id: res.data.channel.tags.indexOf(cur), name: cur }) t.push({ id: res.data.channel.tags.indexOf(cur), name: cur })
...@@ -10,101 +9,7 @@ getConditionList({ channel: true }).then(res => { ...@@ -10,101 +9,7 @@ getConditionList({ channel: true }).then(res => {
}, []) }, [])
console.log(tagsList.value) console.log(tagsList.value)
}) })
const shortcuts = [
{
text: '今日',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(new Date(new Date().toLocaleDateString()).getTime())
return [start, end.setHours(23, 59, 59, 999)]
}
},
{
text: '昨日',
value: () => {
// const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
return [start.setHours(0, 0, 0, 0), start.setHours(23, 59, 59, 999)]
}
},
{
text: '本周',
value: () => {
// let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const end = new Date()
const start = new Date()
console.log(start.getDay())
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() - 1))
return [start.setHours(0, 0, 0, 0), end]
}
},
{
text: '上周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * (start.getDay() + 6))
end.setTime(end.getTime() - 3600 * 1000 * 24 * end.getDay())
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去7天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去14天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去30天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去60天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 60)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去90天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
},
{
text: '过去180天',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
return [start.setHours(0, 0, 0, 0), end.setHours(23, 59, 59, 999)]
}
}
]
// 列表配置 // 列表配置
const listOptions = $computed(() => { const listOptions = $computed(() => {
return { return {
...@@ -188,9 +93,9 @@ const listOptions = $computed(() => { ...@@ -188,9 +93,9 @@ const listOptions = $computed(() => {
</template> </template>
<template #table-x="{ row }"> <template #table-x="{ row }">
<router-link :to="`/channel/bp/detail/?id=${row.id}`" target="_blank"> <el-button type="primary" link v-permission="'channel-index-view'">
<el-link type="primary" plain>查看</el-link> <router-link :to="`/channel/bp/detail/?id=${row.id}`" target="_blank">查看</router-link>
</router-link> </el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
...@@ -44,7 +44,7 @@ const listOptions1 = $computed(() => { ...@@ -44,7 +44,7 @@ const listOptions1 = $computed(() => {
<template> <template>
<AppCard title="基本信息"> <AppCard title="基本信息">
<el-descriptions :column="4"> <el-descriptions :column="4" border>
<el-descriptions-item label="渠道编号">{{ channelInfo.channel_id || '-' }}</el-descriptions-item> <el-descriptions-item label="渠道编号">{{ channelInfo.channel_id || '-' }}</el-descriptions-item>
<el-descriptions-item label="渠道名称">{{ channelInfo.title || '-' }}</el-descriptions-item> <el-descriptions-item label="渠道名称">{{ channelInfo.title || '-' }}</el-descriptions-item>
<el-descriptions-item label="状态">{{ channelInfo.channel_status_name || '-' }}</el-descriptions-item> <el-descriptions-item label="状态">{{ channelInfo.channel_status_name || '-' }}</el-descriptions-item>
......
...@@ -30,22 +30,14 @@ const init = () => { ...@@ -30,22 +30,14 @@ const init = () => {
x: 'center', x: 'center',
left: '20%', left: '20%',
orient: 'vertical', orient: 'vertical',
data: [ data: [{ name: 'ZWS客户' }, { name: '院校客户' }, { name: '渠道客户' }] //水平排列。(vertical为垂直排列}}
{ value: 1048, name: 'ZWS客户' },
{ value: 735, name: '院校客户' },
{ value: 580, name: '渠道客户' }
] //水平排列。(vertical为垂直排列}}
}, },
{ {
x: 'center', x: 'center',
top: 'bottom', top: 'bottom',
orient: 'vertical', orient: 'vertical',
left: '60%', left: '60%',
data: [ data: [{ name: '尘峰客户' }, { name: '企微客户' }, { name: '小鹅通客户' }] //水平排列。(vertical为垂直排列}}
{ value: 484, name: '尘峰客户' },
{ value: 300, name: '企微客户' },
{ value: 300, name: '小鹅通客户' }
] //水平排列。(vertical为垂直排列}}
} }
], ],
series: [ series: [
......
...@@ -44,10 +44,16 @@ const handleRefetch = () => { ...@@ -44,10 +44,16 @@ const handleRefetch = () => {
<template> <template>
<AppCard title="联系人信息"> <AppCard title="联系人信息">
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button> <el-button
type="primary"
style="margin-bottom: 20px"
@click="handleBatchImport"
v-permission="'school-user-import'"
>批量导入</el-button
>
<template #table-x="{ row }"> <template #table-x="{ row }">
<el-button type="primary" link> <el-button type="primary" link v-permission="'school-user-view'">
<router-link :to="`/school/contact/detail/${row.id}`" target="_blank">查看</router-link> <router-link :to="`/school/contact/detail/${row.id}`" target="_blank">查看</router-link>
</el-button> </el-button>
</template> </template>
......
...@@ -44,10 +44,16 @@ const handleRefetch = () => { ...@@ -44,10 +44,16 @@ const handleRefetch = () => {
<template> <template>
<AppCard title="项目信息"> <AppCard title="项目信息">
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button> <el-button
type="primary"
style="margin-bottom: 20px"
@click="handleBatchImport"
v-permission="'school-project-import'"
>批量导入</el-button
>
<template #table-x="{ row }"> <template #table-x="{ row }">
<el-button type="primary" link> <el-button type="primary" link v-permission="'school-project-view'">
<router-link :to="`/school/project/detail/${row.id}`" target="_blank">查看</router-link> <router-link :to="`/school/project/detail/${row.id}`" target="_blank">查看</router-link>
</el-button> </el-button>
</template> </template>
......
...@@ -42,9 +42,15 @@ const handleRefetch = () => { ...@@ -42,9 +42,15 @@ const handleRefetch = () => {
<template> <template>
<AppCard title="学校信息"> <AppCard title="学校信息">
<AppList v-bind="listOptions" ref="appList"> <AppList v-bind="listOptions" ref="appList">
<el-button type="primary" style="margin-bottom: 20px" @click="handleBatchImport">批量导入</el-button> <el-button
type="primary"
style="margin-bottom: 20px"
@click="handleBatchImport"
v-permission="'school-school-import'"
>批量导入</el-button
>
<template #table-x="{ row }"> <template #table-x="{ row }">
<el-button type="primary" link> <el-button type="primary" link v-permission="'school-school-view'">
<router-link :to="`/school/school/${row.id}`" target="_blank">查看</router-link> <router-link :to="`/school/school/${row.id}`" target="_blank">查看</router-link>
</el-button> </el-button>
</template> </template>
......
...@@ -102,13 +102,13 @@ const listOptions = $computed(() => { ...@@ -102,13 +102,13 @@ const listOptions = $computed(() => {
const handleDetail = (row: any) => { const handleDetail = (row: any) => {
if (row.system_id === 'zws') { if (row.system_id === 'zws') {
router.push(`/user/zws/detail/${row.id}`) router.push(`/user/zws/detail/?id=${row.id}`)
} else if (row.system_id === 'wechat') { } else if (row.system_id === 'wechat') {
router.push(`/user/weixin/detail/${row.id}`) router.push(`/user/weixin/detail/?id=${row.id}`)
} else if (row.system_id === 'dustess') { } else if (row.system_id === 'dustess') {
router.push(`/user/chenfeng/detail/${row.id}`) router.push(`/user/chenfeng/detail/?id=${row.id}`)
} else if (row.system_id === 'xiaoe') { } else if (row.system_id === 'xiaoe') {
router.push(`/user/xiaoetong/detail/${row.id}`) router.push(`/user/xiaoetong/detail/?id=${row.id}`)
} }
} }
</script> </script>
......
...@@ -133,9 +133,9 @@ const listOptions = $computed(() => { ...@@ -133,9 +133,9 @@ const listOptions = $computed(() => {
</template> </template>
<template #table-x="{ row }"> <template #table-x="{ row }">
<router-link :to="`/user/xiaoetong/detail/?id=${row.id}`" target="_blank"> <el-button type="primary" link v-permission="'customer-xiaoe-view'">
<el-link type="primary" plain>查看</el-link> <router-link :to="`/user/xiaoetong/detail/?id=${row.id}`" target="_blank">查看</router-link>
</router-link> </el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
...@@ -112,9 +112,9 @@ const listOptions = $computed(() => { ...@@ -112,9 +112,9 @@ const listOptions = $computed(() => {
</template> </template>
<template #table-x="{ row }"> <template #table-x="{ row }">
<router-link :to="`/user/chenfeng/detail/?id=${row.id}`" target="_blank"> <el-button type="primary" link v-permission="'customer-dustess-view'">
<el-link type="primary" plain>查看</el-link> <router-link :to="`/user/chenfeng/detail/?id=${row.id}`" target="_blank">查看</router-link>
</router-link> </el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
...@@ -12,7 +12,6 @@ getPeakUserDetail(params).then(res => { ...@@ -12,7 +12,6 @@ getPeakUserDetail(params).then(res => {
res.data.custom_fields = JSON.parse(res.data.custom_fields) res.data.custom_fields = JSON.parse(res.data.custom_fields)
infoList.value = res.data infoList.value = res.data
}) })
console.log(route.query.id, '0000')
</script> </script>
<template> <template>
......
...@@ -148,9 +148,9 @@ const listOptions = $computed(() => { ...@@ -148,9 +148,9 @@ const listOptions = $computed(() => {
<div v-for="(item, index) in row.follow" :key="index">{{ item.createtime }}</div> <div v-for="(item, index) in row.follow" :key="index">{{ item.createtime }}</div>
</template> </template>
<template #table-x="{ row }"> <template #table-x="{ row }">
<router-link :to="`/user/weixin/detail/?id=${row.external_userid}`" target="_blank"> <el-button type="primary" link v-permission="'customer-wechat-view'">
<el-link type="primary" plain>查看</el-link> <router-link :to="`/user/weixin/detail/?id=${row.external_userid}`" target="_blank">查看</router-link>
</router-link> </el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
...@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [ ...@@ -7,7 +7,7 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout, component: AppLayout,
children: [ children: [
{ path: '', component: () => import('./views/List.vue') }, { path: '', component: () => import('./views/List.vue') },
{ path: '/user/zws/detail/:id', component: () => import('./views/View.vue'), props: true } { path: '/user/zws/detail', component: () => import('./views/View.vue') }
] ]
} }
] ]
...@@ -139,9 +139,9 @@ const listOptions = $computed(() => { ...@@ -139,9 +139,9 @@ const listOptions = $computed(() => {
/> />
</template> </template>
<template #table-x="{ row }"> <template #table-x="{ row }">
<router-link :to="`/user/zws/detail/?id=${row.id}`" target="_blank"> <el-button type="primary" link v-permission="'customer-zws-view'">
<el-link type="primary" plain>查看</el-link> <router-link :to="`/user/zws/detail/?id=${row.id}`" target="_blank">查看</router-link>
</router-link> </el-button>
</template> </template>
</AppList> </AppList>
</AppCard> </AppCard>
......
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/stores/user' import { useInfoStore } from '@/stores/index'
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
...@@ -8,10 +8,10 @@ const router = createRouter({ ...@@ -8,10 +8,10 @@ const router = createRouter({
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
const whiteList = ['/401'] const whiteList = ['/401']
const user = useUserStore() const user = useInfoStore()
if (!user.isLogin && !whiteList.includes(to.path)) { if (!user.isLogin && !whiteList.includes(to.path)) {
try { try {
await user.getUser() await user.getUserInfo()
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} }
......
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { getUserInfo } from '@/api/base' import { getUserInfo, logout } from '@/api/base'
import type { IInfo, IPermissions } from '@/types'
export interface IUserType { interface IUserType {
info: IInfo[] info: IInfo | null
permissions: IPermissions[] permissions: IPermissions[]
roles: [] roles: []
} }
export interface IInfo {
id: string
mobile: string
name: string
email: string
username: string
avatar: string
auth_key: null
}
export interface IPermissions {
id: string
name: string
tag: string
parent_id: string
type: number
desc: string
effect_uris: string
}
export const useInfoStore = defineStore({ export const useInfoStore = defineStore({
id: 'map', id: 'map',
state: (): IUserType => { state: (): IUserType => {
return { return {
info: [], info: null,
permissions: [], permissions: [],
roles: [] roles: []
} }
}, },
getters: {
isLogin: state => !!state.info,
userName: ({ info }) => {
if (!info) return ''
return info.name || info.username || ''
}
},
actions: { actions: {
async getUserInfo() { async getUserInfo() {
const res = await getUserInfo() const res = await getUserInfo()
this.info = res.data.info || [] this.info = res.data.info
this.permissions = res.data.permissions || [] this.permissions = res.data.permissions || []
this.roles = res.data.roles || [] this.roles = res.data.roles || []
},
async logout() {
await logout()
this.info = null
} }
} }
}) })
useInfoStore().getUserInfo()
...@@ -9,38 +9,46 @@ interface State { ...@@ -9,38 +9,46 @@ interface State {
// 学生菜单 // 学生菜单
const menus: IMenuItem[] = [ const menus: IMenuItem[] = [
{ {
tag: 'index',
name: '主页', name: '主页',
path: '/', path: '/',
icon: markRaw(House) icon: markRaw(House)
}, },
{ {
tag: 'customer',
name: '学员信息', name: '学员信息',
path: '/user', path: '/user',
icon: markRaw(User), icon: markRaw(User),
children: [ children: [
{ {
tag: 'customer-all',
name: '全部学员信息', name: '全部学员信息',
path: '/user/all' path: '/user/all'
}, },
{ {
tag: 'customer-zws',
name: 'ZWS学员信息', name: 'ZWS学员信息',
path: '/user/zws' path: '/user/zws'
}, },
{ {
tag: 'customer-wechat',
name: '企微客户', name: '企微客户',
path: '/user/weixin' path: '/user/weixin'
}, },
{ {
tag: 'customer-xiaoe',
name: '小鹅通客户', name: '小鹅通客户',
path: '/user/xiaoetong' path: '/user/xiaoetong'
}, },
{ {
tag: 'customer-dustess',
name: '尘峰客户', name: '尘峰客户',
path: '/user/chenfeng' path: '/user/chenfeng'
} }
] ]
}, },
{ {
tag: 'channel',
name: '渠道信息', name: '渠道信息',
path: '/channel', path: '/channel',
icon: markRaw(Monitor), icon: markRaw(Monitor),
...@@ -52,19 +60,23 @@ const menus: IMenuItem[] = [ ...@@ -52,19 +60,23 @@ const menus: IMenuItem[] = [
] ]
}, },
{ {
tag: 'school',
name: '学校信息', name: '学校信息',
path: '/school', path: '/school',
icon: markRaw(School), icon: markRaw(School),
children: [ children: [
{ {
tag: 'school-school',
name: '学校信息', name: '学校信息',
path: '/school/school' path: '/school/school'
}, },
{ {
tag: 'school-project',
name: '项目信息', name: '项目信息',
path: '/school/project' path: '/school/project'
}, },
{ {
tag: 'school-user',
name: '联系人信息', name: '联系人信息',
path: '/school/contact' path: '/school/contact'
} }
......
import { defineStore } from 'pinia'
import { getUser, logout } from '@/api/base'
import type { UserType, PermissionType } from '@/types'
interface State {
user: UserType | null
permissions: PermissionType[]
}
export const useUserStore = defineStore({
id: 'user',
state: (): State => ({
user: null,
permissions: []
}),
getters: {
isLogin: state => !!state.user,
userName: ({ user }) => {
if (!user) return ''
return user.realname || user.nickname || user.username || ''
}
},
actions: {
async getUser() {
const res = await getUser()
this.user = res.data
},
async logout() {
await logout()
this.user = null
}
}
})
...@@ -9,26 +9,22 @@ export interface IMenuItem { ...@@ -9,26 +9,22 @@ export interface IMenuItem {
} }
// 用户信息 // 用户信息
export interface UserType {
export interface IInfo {
id: string id: string
mobile: string mobile: string
name: string
email: string email: string
realname: string
username: string username: string
nickname: string
avatar: string avatar: string
auth_key: null
} }
export interface IPermissions {
// 权限信息
export interface PermissionType {
desc: string
effect_uris: string
id: string id: string
name: string name: string
tag: string
parent_id: string parent_id: string
system_tag: number
type: number type: number
tag: string desc: string
effect_uris: string
} }
import { useUserStore } from '@/stores/user' import { useInfoStore } from '@/stores/index'
import type { DirectiveBinding } from 'vue' import type { DirectiveBinding } from 'vue'
// 判断是否有权限 // 判断是否有权限
export function checkPermission(value: string | string[]): boolean { export function checkPermission(value: string | string[]): boolean {
const userStore = useUserStore() const userStore = useInfoStore()
const permissions = userStore.permissions const permissions = userStore.permissions
if (Array.isArray(value)) { if (Array.isArray(value)) {
return permissions.some(item => value.includes(item.tag)) return permissions.some(item => value.includes(item.tag))
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论