提交 e731555f authored 作者: lihuihui's avatar lihuihui
......@@ -134,7 +134,6 @@
"useDisplayMedia": true,
"useDocumentVisibility": true,
"useDraggable": true,
"useDropZone": true,
"useElementBounding": true,
"useElementByPoint": true,
"useElementHover": true,
......
......@@ -135,7 +135,6 @@ declare global {
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useDropZone: typeof import('@vueuse/core')['useDropZone']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
......
......@@ -2,7 +2,7 @@ import httpRequest from '@/utils/axios'
// 获取用户信息
export function getUser() {
return httpRequest.get('/api/passport/account/get-user-info')
return httpRequest.get('/api/resource/v1/util/info')
}
// 退出登录
......@@ -40,7 +40,7 @@ export function getMapList() {
}
// 上传视频
export function getCreateAuth(data: { title: string, file_name: string }) {
export function getCreateAuth(data: { title: string; file_name: string }) {
return httpRequest.post('/api/resource/v1/resource/video/create-auth', data)
}
......
......@@ -135,10 +135,28 @@ defineExpose({ refetch, tableRef })
</template>
<template v-else>
<!-- input -->
<el-input v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'input'" />
<el-input
v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
style="width: 200px"
v-if="item.type === 'input'"
/>
<!-- select -->
<el-select v-model="params[item.prop]" v-bind="item" clearable @change="search" v-if="item.type === 'select'">
<el-option :label="option[item.labelKey] || option.label" :value="option[item.valueKey] || option.value" v-for="(option, index) in item.options" :key="index" />
<el-select
v-model="params[item.prop]"
v-bind="item"
clearable
@change="search"
v-if="item.type === 'select'"
>
<el-option
:label="option[item.labelKey] || option.label"
:value="option[item.valueKey] || option.value"
v-for="(option, index) in item.options"
:key="index"
/>
</el-select>
</template>
</el-form-item>
......
......@@ -51,7 +51,7 @@ function genNavClassName(data: IMenuItem) {
<img :src="userInfo.avatar || 'https://webapp-pub.ezijing.com/website/base/images/avatar.svg'" />
</div>
<div class="app-header-user-main">
<h3>{{ userStore.userName }}</h3>
<h3>{{ userInfo.name }}</h3>
<p>{{ userInfo.email || userInfo.mobile }}</p>
</div>
<div class="app-header-user-buttons">
......
......@@ -14,9 +14,13 @@ import AppList from '@/components/base/AppList.vue'
import AppUpload from '@/components/base/AppUpload.vue'
import modules from './modules'
import { permissionDirective } from '@/utils/permission'
const app = createApp(App)
// 注册公共组件
app.component('AppCard', AppCard).component('AppList', AppList).component('AppUpload', AppUpload)
app.directive('permission', permissionDirective)
// 注册模块
modules({ router })
......
......@@ -8,8 +8,8 @@ import TreeDialog from './TreeDialog.vue'
import { useMapStore } from '@/stores/map'
const categoryName = ref('')
const store = useMapStore()
const classList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const classList = store.getMapValuesByKey('system_need_pass')
const statusList = store.getMapValuesByKey('system_status')
const isTreeVisible = ref(false)
const formRef = ref()
......@@ -110,7 +110,7 @@ onMounted(() => {
})
</script>
<template>
<el-dialog :model-value="dialogVisible" draggable :before-close="handleCancel" :title="props.title" width="60%">
<el-dialog :model-value="dialogVisible" draggable :before-close="handleCancel" :title="props.title" width="30%">
<el-form :model="categoryForm" label-position="right" label-width="auto" :rules="rules" ref="formRef">
<el-form-item label="上级类别:" prop="parent_id">
<div @click="handleOpenTree" style="width: 100%">
......
......@@ -78,7 +78,7 @@ onMounted(() => {
})
</script>
<template>
<el-dialog :model-value="isTreeVisible" draggable :before-close="handleCancel" title="类别选择" width="40%">
<el-dialog :model-value="isTreeVisible" draggable :before-close="handleCancel" title="类别选择" width="20%">
<el-input v-model="filterText" placeholder="请选择类别" />
<el-tree
ref="treeRef"
......
......@@ -104,7 +104,7 @@ const listOptions = computed(() => {
return { list }
}
},
filters: [{ type: 'input', prop: 'category_name', label: '类别名称:' }],
filters: [{ type: 'input', prop: 'category_name', label: '类别名称:', placeholder: '请输入类别名称' }],
columns: [
{ label: '类别名称', prop: 'category_name', align: 'left' },
{ label: '层级', prop: 'depth', align: 'center' },
......
......@@ -4,6 +4,10 @@ import VEditor from '@/components/tinymce/Index.vue'
import AppUpload from '@/components/base/AppUpload.vue'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const levelList = store.getMapValuesByKey('teacher_level')
const router = useRouter()
const ruleFormRef = ref<FormInstance>()
......@@ -52,26 +56,28 @@ const submitForm = async (formEl: FormInstance | undefined) => {
<AppCard title="添加讲师">
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm">
<el-row>
<el-col :span="10">
<el-col :span="6">
<el-form-item label="讲师姓名:" prop="name">
<el-input v-model="ruleForm.name" />
<el-input v-model="ruleForm.name" style="width: 250px" placeholder="请输入讲师姓名" />
</el-form-item>
</el-col>
<el-col :span="10">
<el-col :span="6">
<el-form-item label="讲师职位:" prop="title">
<el-input v-model="ruleForm.title" />
<el-input v-model="ruleForm.title" style="width: 250px" placeholder="请输入讲师职位" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="10">
<el-col :span="6">
<el-form-item label="讲师学历:" prop="education">
<el-input v-model="ruleForm.education" />
<el-select v-model="ruleForm.education" clearable style="width: 250px" placeholder="请选择讲师学历">
<el-option v-for="(item, index) in levelList" :key="index" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-col :span="6">
<el-form-item label="讲师任职机构:" prop="office">
<el-input v-model="ruleForm.office" />
<el-input v-model="ruleForm.office" style="width: 250px" placeholder="请输入讲师任职机构" />
</el-form-item>
</el-col>
</el-row>
......
......@@ -82,7 +82,8 @@ onMounted(() => {
<el-row>
<el-col :span="8">
<el-form-item label="讲师图片:" prop="avatar">
<div v-if="isEdit === '1'" class="avatar_box">暂无照片</div>
<img v-if="isEdit === '1' && ruleForm.avatar !== ''" :src="ruleForm.avatar" class="avatar_box1" />
<div class="avatar_box" v-else-if="isEdit === '1' && ruleForm.avatar === ''">暂无讲师图片</div>
<AppUpload v-model="ruleForm.avatar" v-else />
</el-form-item>
</el-col>
......@@ -141,4 +142,7 @@ onMounted(() => {
color: #ccc;
border: 1px dashed #ccc;
}
.avatar_box1 {
width: 150px;
}
</style>
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import { getTeacherList, deleteTeacher } from '../api'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const router = useRouter()
const appList = ref()
const listOptions = {
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getTeacherList,
params: { type: '' }
},
filters: [
{ type: 'input', prop: 'name', label: '讲师姓名:' },
{ type: 'input', prop: 'office', label: '讲师任职机构:' },
{ type: 'input', prop: 'title', label: '讲师职位:' },
{ type: 'input', prop: 'education', label: '讲师学历:' }
{ type: 'input', prop: 'name', label: '讲师姓名:', placeholder: '请输入讲师姓名' },
{ type: 'input', prop: 'office', label: '讲师任职机构:', placeholder: '请输入讲师任职机构' },
{ type: 'input', prop: 'title', label: '讲师职位:', placeholder: '请输入讲师职位' },
{
type: 'select',
prop: 'education',
label: '讲师学历:',
placeholder: '请选择讲师学历',
options: store.getMapValuesByKey('teacher_level')
}
],
columns: [
{ label: '#', type: 'index', align: 'center' },
......@@ -24,7 +33,8 @@ const listOptions = {
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
]
}
}
})
// 删除讲师
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
......@@ -66,7 +76,16 @@ const handleDetail = (row: any) => {
<el-button type="primary" round style="margin-bottom: 20px">添加讲师</el-button>
</router-link>
<template #header-aside> </template>
<template #table-img="{ row }"> <img :src="row.avatar" alt="" style="width: 100%" /></template>
<template #table-img="{ row }">
<el-image
:src="row.avatar"
alt=""
style="width: 50px"
:preview-src-list="[row.avatar]"
:initial-index="4"
fit="contain"
:preview-teleported="true"
/></template>
<template #table-operate="{ row }">
<el-space>
<el-link type="primary" plain @click="handleDetail(row)">查看</el-link>
......
const routes = [
{
path: '/401',
component: () => import('./views/401.vue')
}
]
export { routes }
差异被折叠。
<script setup lang="ts">
import { Files } from '@element-plus/icons-vue'
const props = defineProps({
data: {
type: Object,
require: true
}
})
</script>
<template>
......@@ -12,53 +18,53 @@ import { Files } from '@element-plus/icons-vue'
</div>
<div class="info-items">
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons" />
<div class="text-box">
<div class="name">状态</div>
<div class="value active">有效</div>
<div class="value active">{{ props.data?.status_name }}</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons" />
<div class="text-box">
<div class="name">创建者</div>
<div class="value">张三丰</div>
<div class="value">{{ props.data?.created_operator_name }}</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons" />
<div class="text-box">
<div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div>
<div class="value">{{ props.data?.created_time }}</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons" />
<div class="text-box">
<div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div>
<div class="value">{{ props.data?.updated_time }}</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons" />
<div class="text-box">
<div class="name">课件名称</div>
<div class="value">基金产品(中)(初级)</div>
<div class="value">{{ props.data?.name }}</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons" />
<div class="text-box">
<div class="name">课件分类</div>
<div class="value">金融产品数字化营销-黄老师</div>
<div class="value">{{ props.data?.classification_name || '暂无' }}</div>
</div>
</div>
<div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons">
<div class="i-items" style="align-items: flex-start">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons" />
<div class="text-box">
<div class="name">知识点</div>
<div class="textarea-box">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某
{{ props.data?.knowledge_points || '暂无' }}
</div>
</div>
</div>
......@@ -66,19 +72,19 @@ import { Files } from '@element-plus/icons-vue'
</div>
</template>
<style lang="scss" scoped>
.video-info{
background: #F7F7F7;
.video-info {
background: #f7f7f7;
margin-top: 20px;
padding: 20px;
display: flex;
.video-img{
.video-img {
// width: 211px;
padding: 0 30px;
.item-info-icon{
.item-info-icon {
font-size: 100px;
color: #aa1941;
}
.name{
.name {
font-size: 16px;
line-height: 100%;
color: #666666;
......@@ -86,40 +92,40 @@ import { Files } from '@element-plus/icons-vue'
text-align: center;
}
}
.info-items{
.info-items {
display: flex;
flex-wrap: wrap;
padding-left: 12px;
.i-items{
.i-items {
display: flex;
align-items: center;
height: fit-content;
margin-right: 80px;
margin-bottom: 30px;
.textarea-box{
.textarea-box {
padding: 18px 18px 51px;
background: #FFFFFF;
background: #ffffff;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #505050;
margin-top: 14px;
}
.text-box{
.text-box {
margin-left: 16px;
.name{
.name {
font-size: 14px;
line-height: 100%;
color: #999999;
}
.value{
.value {
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
margin-top: 8px;
&.active{
color: #1AB226;
&.active {
color: #1ab226;
}
}
}
......
......@@ -43,7 +43,7 @@ getCourseDetails({ id: id }).then(res => {
<div class="btn-item">更改负责人</div>
</div> -->
<Operation :data="courseDetails" style="margin-bottom: 20px"></Operation>
<TopInfo :data="courseDetails"></TopInfo>
<TopInfo v-if="Object.keys(courseDetails).length" :data="courseDetails"></TopInfo>
<CenterInfo v-if="Object.keys(courseDetails).length" :data="courseDetails"></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard>
......
......@@ -7,9 +7,9 @@ const store = useMapStore()
const emit = defineEmits<Emits>()
const ruleFormRef = ref<FormInstance>()
// 封面类型
const typeList = store.mapList.filter((item: any) => item.key === 'system_cover_type')[0].values
const typeList = store.getMapValuesByKey('system_cover_type')
// 封面状态
const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const statusList = store.getMapValuesByKey('system_status')
const form = reactive({
title: '',
status: '1',
......@@ -77,10 +77,10 @@ onMounted(() => {
:model-value="isShowDialog"
draggable
:before-close="handleCancel"
width="30%"
width="25%"
:title="props.isEdit ? '修改预置封面信息' : ' 新增封面'"
>
<el-form :model="form" :rules="rules" ref="ruleFormRef">
<el-form :model="form" :rules="rules" ref="ruleFormRef" label-width="120px">
<el-form-item label="封面类型:" prop="type">
<el-select v-model="form.type">
<el-option v-for="(item, id) in typeList" :key="id" :label="item.label" :value="item.value"></el-option>
......@@ -97,8 +97,8 @@ onMounted(() => {
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
......
......@@ -2,17 +2,34 @@
import { getCoverList, deleteCover } from '../api'
import { ElMessage, ElMessageBox } from 'element-plus'
import AddDialog from '../components/AddDialog.vue'
import { useMapStore } from '@/stores/map'
const store = useMapStore()
const appList = ref()
const isShowDialog = ref(false)
const isEdit = ref(false)
const editData = ref({})
const listOptions = {
const listOptions = $computed(() => {
return {
remote: {
httpRequest: getCoverList,
params: { type: '' }
},
filters: [
{
type: 'select',
prop: 'type',
label: '封面类型:',
placeholder: '请选择封面类型',
options: store.getMapValuesByKey('system_cover_type')
},
{
type: 'select',
prop: 'status',
label: '封面状态:',
placeholder: '请选择封面状态',
options: store.getMapValuesByKey('system_status')
}
],
columns: [
{ label: '封面标题', prop: 'title', align: 'center' },
{ label: '封面预览', prop: 'url', slots: 'table-cover', align: 'center' },
......@@ -25,7 +42,8 @@ const listOptions = {
{ label: '创建时间', prop: 'created_time', align: 'center' },
{ label: '操作', slots: 'table-operate', width: 230, align: 'center' }
]
}
}
})
// 删除
const handleDelete = (row: any) => {
ElMessageBox.confirm('确定要删除吗?', '提示').then(() => {
......@@ -55,11 +73,12 @@ const handleEdit = (row: any) => {
<template>
<AppCard title="封面管理">
<el-button type="primary" round @click="handleAdd">新增封面</el-button>
<AppList v-bind="listOptions" ref="appList" border stripe>
<template #header-aside> </template>
<el-button type="primary" round @click="handleAdd" style="margin-bottom: 20px">新增封面</el-button>
<template #table-cover="{ row }">
<img :src="row.url" alt="" style="width: 100px" />
<img :src="row.url" alt="" style="width: 50px" />
</template>
<template #table-operate="{ row }">
<el-space>
......
......@@ -81,6 +81,7 @@ onMounted(() => {
</script>
<template>
<el-dialog
width="30%"
:model-value="isShowDialog"
draggable
:before-close="handleCancel"
......@@ -88,10 +89,10 @@ onMounted(() => {
>
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典名称:" prop="name">
<el-input v-model="form.name"></el-input>
<el-input v-model="form.name" placeholder="请输入字典名称"></el-input>
</el-form-item>
<el-form-item label="字典类型:" prop="key">
<el-input v-model="form.key"></el-input>
<el-input v-model="form.key" placeholder="请输入字典类型"></el-input>
</el-form-item>
<el-form-item label="状态:" prop="status">
......@@ -100,13 +101,13 @@ onMounted(() => {
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
<el-input v-model="form.remark" autosize type="textarea" />
<el-input v-model="form.remark" autosize type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
......
......@@ -102,16 +102,16 @@ onMounted(() => {
})
</script>
<template>
<el-dialog :model-value="isListAddDialog" draggable :before-close="handleCancel" :title="props.title">
<el-dialog width="30%" :model-value="isListAddDialog" draggable :before-close="handleCancel" :title="props.title">
<el-form :model="form" ref="ruleFormRef" :rules="rules" label-width="120px">
<el-form-item label="字典标签:" prop="label">
<el-input v-model="form.label"></el-input>
<el-input v-model="form.label" placeholder="请输入字典标签"></el-input>
</el-form-item>
<el-form-item label="字典键值:" prop="value">
<el-input v-model="form.value" :disabled="form.can_edit === '0'"></el-input>
<el-input v-model="form.value" :disabled="form.can_edit === '0'" placeholder="请输入字典键值"></el-input>
</el-form-item>
<el-form-item label="字典排序:" prop="sort">
<el-input v-model="form.sort"></el-input>
<el-input v-model="form.sort" placeholder="请输入字典排序"></el-input>
</el-form-item>
<el-form-item label="字典类型:">
<el-input disabled :placeholder="props.type"></el-input>
......@@ -122,7 +122,7 @@ onMounted(() => {
</el-radio-group>
</el-form-item>
<el-form-item label="备注:" prop="remark">
<el-input v-model="form.remark" autosize type="textarea" />
<el-input v-model="form.remark" autosize type="textarea" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="能否编辑:" prop="can_edit">
<el-radio-group v-model="form.can_edit">
......@@ -132,8 +132,8 @@ onMounted(() => {
</el-form>
<template #footer>
<span>
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm(ruleFormRef)">确定</el-button>
<el-button @click="handleCancel">关闭</el-button>
</span>
</template>
</el-dialog>
......
......@@ -25,8 +25,8 @@ const listOptions = $computed(() => {
}
},
filters: [
{ type: 'input', prop: 'name', label: '字典名称:' },
{ type: 'input', prop: 'key', label: '字典类型:' },
{ type: 'input', prop: 'name', label: '字典名称:', placeholder: '请输入字典名称' },
{ type: 'input', prop: 'key', label: '字典类型:', placeholder: '请输入字典类型' },
{
type: 'select',
prop: 'status',
......@@ -100,7 +100,7 @@ const handleUpdate = () => {
<AppCard title="数据字典">
<AppList v-bind="listOptions" ref="appList" border stripe>
<el-row>
<el-button type="primary" @click="handleAdd" style="margin-bottom: 20px">新增字典</el-button>
<el-button type="primary" @click="handleAdd" style="margin-bottom: 20px" v-permission="'test1'">新增字典</el-button>
</el-row>
<template v-slot:created_time_start="{ params }">
<el-date-picker v-model="params.created_time_start" type="date" placeholder="开始时间"> </el-date-picker>
......
......@@ -7,14 +7,15 @@ const router = createRouter({
})
router.beforeEach(async (to, from, next) => {
const whiteList = ['/401']
const user = useUserStore()
if (!user.isLogin) {
if (!user.isLogin && !whiteList.includes(to.path)) {
try {
await user.getUser()
} catch (e) {
console.error(e)
}
user.isLogin ? next() : (location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`)
user.isLogin ? next() : next('/401')
return
}
next()
......
import { defineStore } from 'pinia'
import { getMapList } from '@/api/base'
interface State {
mapList: IMapState[]
}
interface IMapState {
id: string
key: string
......@@ -17,18 +20,23 @@ interface IValuesList {
sort: string
value: string
}
export const useMapStore = defineStore({
id: 'map',
state: () => {
state: (): State => {
return {
mapList: [] as IMapState | any
mapList: []
}
},
getters: {
getMapValuesByKey: state => {
return (key: string) => state.mapList.find(map => map.key === key)?.values || []
}
},
getters: {},
actions: {
async getMapList() {
const res = await getMapList()
this.mapList = res.data
this.mapList = res.data || []
}
}
})
......
import { defineStore } from 'pinia'
import { getUser, logout } from '@/api/base'
import type { UserType, ProjectType, OrganizationType, RoleType, PermissionType } from '@/types'
interface IUserState {
id: string
avatar: string
mobile: string
realname: string
nickname: string
username: string
email: string
interface State {
user: UserType | null
project: ProjectType | null
organization: OrganizationType | null
roles: RoleType[]
permissions: PermissionType[]
}
export const useUserStore = defineStore({
id: 'user',
state: () => {
return {
user: null as IUserState | null
}
},
state: (): State => ({
user: null,
organization: null,
project: null,
roles: [],
permissions: []
}),
getters: {
isLogin: state => !!state.user,
userName: ({ user }) => {
if (!user) return ''
return user.realname || user.nickname || user.username || ''
}
isLogin: state => !!state.user
},
actions: {
async getUser() {
const res = await getUser()
this.user = res.data
console.log(res.data, 'res.data')
const { info } = res.data
const { organization, project, roles, permissions } = res.data.permissions
this.user = info
this.organization = organization
this.project = project
this.roles = roles
this.permissions = permissions
},
async logout() {
await logout()
......
......@@ -6,3 +6,48 @@ export interface IMenuItem {
icon?: Component
children?: IMenuItem[]
}
// 用户信息
export interface UserType {
id: string
mobile: string
name: string
email: string
username: string
avatar: string
}
// 项目信息
export interface ProjectType {
id: string
tab: string
name: string
}
// 机构信息
export interface OrganizationType {
id: string
name: string
contact_name: string
contact_information: string
validity_date: string
is_valid: 1 | 2
}
// 角色信息
export interface RoleType {
id: string
name: string
desc: string
}
// 权限信息
export interface PermissionType {
desc: string
effect_uris: string
id: string
name: string
parent_id: string
system_tag: number
type: number
tag: string
}
......@@ -4,7 +4,6 @@ import { ElMessage } from 'element-plus'
import router from '@/router'
const httpRequest = axios.create({
// baseURL: 'https://project-api.ezijing.com',
timeout: 60000,
withCredentials: true,
headers: {
......@@ -52,7 +51,7 @@ httpRequest.interceptors.response.use(
// 未登录
if (status === 403) {
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
} else if (status === 400) {
} else if (status === 400 || status === 402) {
// 未授权
router.push('/401')
} else {
......
import { useUserStore } from '@/stores/user'
import type { DirectiveBinding } from 'vue'
// 判断是否有权限
export function checkPermission(value: string | string[]): boolean {
const userStore = useUserStore()
const permissions = userStore.permissions
if (Array.isArray(value)) {
return permissions.some(item => value.includes(item.tag))
} else {
return !!permissions.find(item => item.tag === value)
}
}
// 权限指令
export function permissionDirective(el: HTMLElement, binding: DirectiveBinding) {
const { value } = binding
if (!value) return
if (!checkPermission(value)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论