update admin

This commit is contained in:
全栈小学生 2023-09-16 18:43:30 +08:00
parent 6b524aefb5
commit 0023c79586
14 changed files with 426 additions and 271 deletions

View File

@ -39,3 +39,9 @@ export function getLoginConfig() {
export function setStarAddon(params: Record<string, any>) {
return request.post('auth/appstar', params)
}
/**
*
*/
export function getAuthaddon() {
return request.get(`auth/authaddon`)
}

View File

@ -11,7 +11,7 @@ export function getAuthinfo() {
*
*/
export function setAuthinfo(params: Record<string, any>) {
return request.post('niucloud/authinfo', params, {showSuccessMessage: true})
return request.post('niucloud/authinfo', params, { showSuccessMessage: true })
}
/**
@ -43,6 +43,6 @@ export function getModuleVersion() {
* @param addon
* @returns
*/
export function downloadVersion(addon) {
return request.post(`addon/download/${addon}`, {}, {showSuccessMessage: true})
export function downloadVersion(params: Record<string, any>) {
return request.post(`addon/download/${params.addon}`, params, { showSuccessMessage: true })
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -39,5 +39,6 @@
"cloudInstall": "一键云安装",
"cloudInstallTips": "云安装可实现一键安装,安装后无需手动更新依赖和编译前端源码",
"installingTips": "有插件正在安装中请等待安装完成之后再进行其他操作,点击查看",
"installPercent": "安装进度"
"installPercent": "安装进度",
"downloading": "下载中"
}

View File

@ -0,0 +1,5 @@
{
"app":"应用",
"noPlug":"暂无应用",
"installApp":"安装应用"
}

View File

@ -35,9 +35,9 @@
<span class="text-[14px] truncate w-[160px]">{{ item.title }}</span>
<span class="text-xs text-gray-400 truncate w-[160px] mt-[4px]">{{ item.desc }}</span>
</div>
<span
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none "
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') }}</span>
<el-button size="small" round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button>
</div>
</div>
@ -56,11 +56,10 @@
<p class="app-text text-[12px] text-[#999] pl-2">{{ item.desc }}</p>
</div>
<div class="flex items-center pr-2">
<span
class="w-max flex items-center plug-item-operate border rounded-2xl px-2 py-1 leading-none mt-[10px]"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') }}</span>
<el-button size="small" round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button>
</div>
</div>
</div>
</div>
@ -85,12 +84,14 @@
<span class="text-[14px] truncate w-[160px]">{{ item.title }}</span>
<span class="text-xs text-gray-400 truncate w-[160px] mt-[4px]">{{ item.desc }}</span>
</div>
<span v-if="item.is_download"
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none"
@click.stop="installAddonFn(item.key)">{{ t('install') }}</span>
<span v-else
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none"
@click.stop="downEvent(item.key)">{{ t('down') }}</span>
<el-button v-if="item.is_download" size="small" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="installAddonFn(item.key)">{{ t('install')
}}</el-button>
<el-button v-else size="small" :loading="downloading == item.key" :disabled="downloading"
round class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') : t('down')
}}</el-button>
</div>
</div>
@ -112,12 +113,16 @@
<p class="app-text text-[12px] text-[#999] pl-2">{{ item.desc }}</p>
</div>
<div class="flex items-center pr-2">
<span v-if="item.is_download"
class="w-max flex items-center plug-item-operate border rounded-2xl px-2 py-1 leading-none mt-[10px]"
@click.stop="installAddonFn(item.key)">{{ t('install') }}</span>
<span v-else
class="w-max flex items-center plug-item-operate border rounded-2xl px-2 py-1 leading-none mt-[10px]"
@click.stop="downEvent(item.key)">{{ t('down') }}</span>
<el-button v-if="item.is_download" size="small" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="installAddonFn(item.key)">{{ t('install')
}}</el-button>
<el-button v-else size="small" :loading="downloading == item.key"
:disabled="downloading" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') :
t('down')
}}</el-button>
</div>
</div>
</div>
@ -143,15 +148,18 @@
<span class="text-[14px] truncate w-[160px]">{{ item.title }}</span>
<span class="text-xs text-gray-400 truncate w-[160px] mt-[4px]">{{ item.desc }}</span>
</div>
<span v-if="item.install_info && Object.keys(item.install_info)?.length"
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none "
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') }}</span>
<span v-else-if="item.is_download && item.install_info <= 0"
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none"
@click.stop="installAddonFn(item.key)">{{ t('install') }}</span>
<span v-else
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none"
@click.stop="downEvent(item.key)">{{ t('down') }}</span>
<el-button v-if="item.install_info && Object.keys(item.install_info)?.length" size="small"
round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button>
<el-button v-else-if="item.is_download && item.install_info <= 0" size="small" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="installAddonFn(item.key)">{{ t('install')
}}</el-button>
<el-button v-else size="small" :loading="downloading == item.key" :disabled="downloading"
round class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') : t('down')
}}</el-button>
</div>
</div>
@ -172,15 +180,19 @@
<p class="app-text text-[12px] text-[#999] pl-2">{{ item.desc }}</p>
</div>
<div class="flex items-center pr-2">
<span v-if="item.install_info && Object.keys(item.install_info)?.length"
class="w-max flex items-center plug-item-operate border rounded-2xl px-3.5 py-1.5 leading-none "
@click.stop="uninstallAddonFn(item.key)">{{ t('unload') }}</span>
<span v-else-if="item.is_download && item.install_info <= 0"
class="w-max flex items-center plug-item-operate border rounded-2xl px-2 py-1 leading-none mt-[10px]"
@click.stop="installAddonFn(item.key)">{{ t('install') }}</span>
<span v-else
class="w-max flex items-center plug-item-operate border rounded-2xl px-2 py-1 leading-none mt-[10px]"
@click.stop="downEvent(item.key)">{{ t('down') }}</span>
<el-button v-if="item.install_info && Object.keys(item.install_info)?.length"
size="small" round class="!text-primary !border-primary !bg-transparent"
@click.stop="uninstallAddonFn(item.key)">{{ t('unload')
}}</el-button>
<el-button v-else-if="item.is_download && item.install_info <= 0" size="small" round
class="!text-primary !border-primary !bg-transparent"
@click.stop="installAddonFn(item.key)">{{ t('install')
}}</el-button>
<el-button v-else size="small" round :loading="downloading == item.key"
:disabled="downloading" class="!text-primary !border-primary !bg-transparent"
@click.stop="downEvent(item)">{{ downloading == item.key ? t('downloading') :
t('down')
}}</el-button>
</div>
</div>
</div>
@ -326,10 +338,18 @@ const activeName = ref('installed')
const loading = ref<Boolean>(false)
const showType = ref('large')
const mode = ref(import.meta.env.MODE)
const downloading = ref('')
const downEvent = (key: string) => {
downloadVersion(key).then(() => {
const downEvent = (param: Record<string, any>) => {
if (downloading.value) return
downloading.value = param.key
downloadVersion({ addon: param.key, version: param.version }).then(() => {
installAddonFn(param.key)
localListFn()
downloading.value = ''
}).catch(() => {
downloading.value = ''
})
}
@ -454,7 +474,7 @@ const getInstallTask = (first: boolean = true) => {
}, 2000)
} else {
if (!first) {
installStep.value += 2
installStep.value = 3
localListFn()
notificationEl.close()
}
@ -477,7 +497,7 @@ const handleInstall = () => {
localInstalling.value = true
installAddon({ addon: currAddon.value }).then(res => {
installStep.value += 2
installStep.value = 3
localListFn()
localInstalling.value = false
}).catch((res) => {
@ -494,7 +514,7 @@ const handleCloudInstall = () => {
cloudInstalling.value = true
cloudInstallAddon({ addon: currAddon.value }).then(res => {
installStep.value += 1
installStep.value = 1
terminalApi.execute('my-terminal', 'clear')
terminalApi.pushMessage('my-terminal', { content: '开始安装插件', class: 'info' })
getInstallTask()

View File

@ -0,0 +1,84 @@
<template>
<div class="main-container" v-loading="loading">
<div :class="['h-[480px] box-border px-[60px] pt-[40px]',detail.appList.length?'overview-top':'']">
<div class="flex justify-between items-center">
<div class="font-600 text-[20px] text-[#222]">{{ t('app') }}</div>
<el-button @click="installApp">
<span class="iconfont iconanzhuang mr-[9px]"></span><span>{{ t('installApp') }}</span>
</el-button>
</div>
<div class="flex flex-wrap mt-[28px]">
<template v-for="(item, index) in detail.appList" :key="index">
<div class="app-item w-[284px] box-border p-[18px] pb-[24px] bg-[#fff] rounded-[8px] cursor-pointer mr-[24px]"
@click="itemPath(item.key)">
<div class="flex items-center">
<el-image class="w-[40px] h-[40px] rounded-[8px]" :src="img(item.icon)" fit="contain">
<template #error>
<div class="image-slot">
<img class="w-[40px] h-[40px] rounded-[8px]"
src="@/app/assets/images/app_store/app_store_default.png" />
</div>
</template>
</el-image>
<div class="flex-1 font-600 text-[14px] text-[#222] ml-[12px]">{{ item.title }}</div>
</div>
<div class="font-500 text-[13px] text-[#6D7278] mt-[14px]">{{ item.desc }}</div>
</div>
</template>
<el-empty :description="t('noPlug')" v-if="!detail.appList.length && !loading" class="mx-auto" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import { t } from '@/lang'
import { getAuthaddon } from '@/app/api/auth'
import { img } from '@/utils/common'
import { useRouter } from 'vue-router'
const router = useRouter()
import useUserStore from '@/stores/modules/user'
const userStore = useUserStore()
const loading = ref(false)
const detail = reactive({
appList: []
})
const getAuthaddonFn = () => {
loading.value = true
getAuthaddon().then(res => {
detail.appList = res.data
loading.value = false
}).catch(()=>{
loading.value = false
})
}
getAuthaddonFn()
const installApp = () => {
router.push('app/app_store')
}
const itemPath = (key: any) => {
let name = userStore.addonIndexRoute[key]
if (name) {
router.push({ name })
} else {
installApp()
}
}
</script>
<style lang="scss" scoped>
.overview-top {
background-image: url('@/app/assets/images/index/overview.png');
background-repeat: no-repeat;
background-size: cover;
}
.app-item {
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.18);
}
</style>

View File

@ -72,9 +72,6 @@ const setFormData = async (id: number = 0) => {
webSite.value = await (await getWebConfig()).data
storage.set({ key: 'siteInfo', data: webSite.value })
}
const routerList = ref({
tourism: "/tourism/index", vipcard: "/vipcard/index", cms: "/cms/article/list", shop: "/shop/hello_world"
})
setFormData()
setWindowTitle(t('adminLogin'))
@ -125,11 +122,8 @@ const handleLogin = async (formEl: FormInstance | undefined) => {
const loginFn = (data = {}) => {
loading.value = true
userStore.login({ username: form.username, password: form.password, ...data }).then(res => {
// const { query: { redirect } } = route
// const path = typeof redirect === 'string' ? redirect : '/'
let key = storage.get('menuAppStorage')
if(!key) storage.set({key:'menuAppStorage',data:'tourism'})
let path = key&&key!=''?routerList.value[key]:'/tourism/index'
const { query: { redirect } } = route
const path = typeof redirect === 'string' ? redirect : '/'
router.push(path)
}).catch(() => {
loading.value = false
@ -172,4 +166,5 @@ const loginFn = (data = {}) => {
.login-main-left {
display: none;
}
}</style>
}
</style>

View File

@ -1,11 +1,11 @@
<template>
<div :class="['flex', { 'two-type': sidebar == 'twoType' }, { 'three-type': sidebar == 'threeType' }]" v-if="aaa">
<div :class="['flex', { 'two-type': sidebar == 'twoType' }, { 'three-type': sidebar == 'threeType' }]">
<div class="w-[65px] overflow-hidden" v-if="!floatMenuStyle">
<el-aside
:class="['h-screen layout-aside w-[65px] pb-[30px] bg-[#F7F8FA] ease-in duration-200', { 'bright': !dark }]">
<!-- 一级菜单 -->
<div class="h-full flex flex-col pt-2 relative">
<div class="h-full flex flex-col relative">
<!-- <el-header class="logo-wrap h-auto mb-[10px]">
<div class="logo flex items-center m-auto max-w-[210px] h-[60px] justify-center"#19233C>
<span class="iconfont iconyun text-[#999] !text-[36px]"></span>
@ -18,9 +18,14 @@
<img :src="img(item.icon)" class="w-[35px] h-[35px] rounded-full" alt="" :title="item.title">
</div>
</template> -->
<div class=" flex items-center justify-center h-[45px] mb-[5px] cursor-pointer cut-style" @click="floatActive=!floatActive">
<div class=" flex items-center justify-center h-[64px] cursor-pointer cut-style"
@click="floatActive = !floatActive">
<span class="iconfont icontuodong !text-[30px] "></span>
</div>
<div @click="homeClick"
class="flex items-center justify-center h-[56px] cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] menu-item hover:text-color whitespace-nowrap">
<span class="iconfont iconshouye !text-[24px] "></span>
</div>
<div class="mb-[20px]">
<template v-for="(item, index) in menus" :key="index">
<div v-if="item.meta.app == '' && item.meta.attr == 'common'" @click="toLink(item)"
@ -37,8 +42,9 @@
</el-aside>
</div>
<!-- 浮动样式的应用菜单 -->
<div v-if="!floatMenuStyle&&floatActive"
<div v-if="!floatMenuStyle && floatActive && applyList.filter(el => { return el.type === 'app' }).length"
class="flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-10 box-border shadow-lg">
<template v-for="(item, index) in applyList" :key="index">
<div v-if="item.type == 'app'" @click="appToLink(item.key)"
class="flex items-center cursor-pointer text-[#6d7278] hover:bg-[#f1f2f6] whitespace-nowrap py-[10px] px-[15px]">
@ -63,7 +69,7 @@
<span>{{ item.meta.app ? appInfo.title : item.meta.title }}</span>
</div>
<!-- 浮动样式的应用菜单 -->
<div v-if="floatMenuStyle"
<div v-if="floatMenuStyle && applyList.filter(el => { return el.type === 'app' }).length"
class="hidden group-hover:flex absolute bg-[#fff] w-[640px] px-[28px] py-[20px] flex-wrap left-0 top-[65px] z-10 box-border shadow-lg">
<template v-for="(item, index) in applyList" :key="index">
<div v-if="item.type == 'app'" @click="appToLink(item.key)"
@ -79,12 +85,14 @@
<el-scrollbar class="overflow-y-auto menus-wrap">
<el-menu class="apply-menu !border-0" :router="true" unique-opened="true"
:default-active="String(route.name)">
<template v-if="!floatMenuStyle || floatMenuStyle && applyTypeList.length">
<template v-for="(twoMenu, twoIndex) in item.children">
<el-sub-menu :index="String(twoMenu.meta.title)" v-if="twoMenu.children && twoMenu.meta.show">
<el-sub-menu :index="String(twoMenu.meta.title)"
v-if="twoMenu.children && twoMenu.meta.show">
<template #title>
<div class="w-[16px] h-[16px] relative flex items-center">
<icon v-if="twoMenu.meta.icon" :name="twoMenu.meta.icon" class="absolute !w-auto"
size="18px" />
<icon v-if="twoMenu.meta.icon" :name="twoMenu.meta.icon"
class="absolute !w-auto" size="18px" />
</div>
<span class="ml-[11px] text-[15px]">{{ twoMenu.meta.title }}</span>
</template>
@ -96,7 +104,8 @@
<div class="w-[16px] h-[16px] relative flex items-center">
<icon v-if="threeMenu.meta.icon && floatMenuStyle"
:name="threeMenu.meta.icon" class="absolute !w-auto" size="18px" />
<span v-if="!floatMenuStyle" class="iconfont icondian !text-[25px]"></span>
<span v-if="!floatMenuStyle"
class="iconfont icondian !text-[25px]"></span>
</div>
<span class="ml-[11px] text-[15px]">{{ threeMenu.meta.title }}</span>
</template>
@ -144,8 +153,8 @@
class="!pl-[25px] text-[#333]" :index="String(twoMenu.name)" @click="toLink(twoMenu)">
<template #title>
<div v-if="twoMenu.meta.icon" class="w-[16px] h-[16px] relative flex items-center">
<icon v-if="twoMenu.meta.icon" :name="twoMenu.meta.icon" class="absolute !w-auto"
size="18px" />
<icon v-if="twoMenu.meta.icon" :name="twoMenu.meta.icon"
class="absolute !w-auto" size="18px" />
</div>
<span class="ml-[11px] text-[15px]">{{ twoMenu.meta.title }}</span>
</template>
@ -185,7 +194,8 @@
</div>
<span class="ml-[11px] text-[15px]">{{ threeMenu.meta.title }}</span>
</template>
<template v-for="(fourMenu, fourIndex) in threeMenu.children" :key="fourIndex">
<template v-for="(fourMenu, fourIndex) in threeMenu.children"
:key="fourIndex">
<!-- 三级菜单 -->
<el-sub-menu :index="String(fourMenu.meta.title)"
v-if="fourMenu.children && fourMenu.meta.show">
@ -194,21 +204,24 @@
class="w-[16px] h-[16px] relative flex items-center justify-center">
<span class="iconfont icondian !text-[25px]"></span>
</div>
<span class="ml-[11px] text-[15px]">{{ fourMenu.meta.title }}</span>
<span class="ml-[11px] text-[15px]">{{ fourMenu.meta.title
}}</span>
</template>
<template v-for="(fiveMenu, fiveIndex) in fourMenu.children"
:key="fiveIndex">
<el-menu-item v-if="fiveMenu.meta.show" class="!h-[52px] !pl-[55px]"
:index="String(fiveMenu.name)" @click="toLink(fiveMenu)">
<el-menu-item v-if="fiveMenu.meta.show"
class="!h-[52px] !pl-[55px]" :index="String(fiveMenu.name)"
@click="toLink(fiveMenu)">
<template #title>
<span class="text-[14px]">{{ fiveMenu.meta.title }}</span>
<span class="text-[14px]">{{ fiveMenu.meta.title
}}</span>
</template>
</el-menu-item>
</template>
</el-sub-menu>
<el-menu-item v-else-if="fourMenu.meta.show"
class="!ml-[30px] !h-[52px] !pl-[35px]" :index="String(fourMenu.name)"
@click="toLink(fourMenu)">
class="!ml-[30px] !h-[52px] !pl-[35px]"
:index="String(fourMenu.name)" @click="toLink(fourMenu)">
<template #title>
<span class="text-[14px]">{{ fourMenu.meta.title }}</span>
</template>
@ -250,7 +263,8 @@
<template v-for="(fourMenu, fourIndex) in threeMenu.children"
:key="fourIndex">
<el-menu-item v-if="fourMenu.meta.show"
class="!h-[52px] !pl-[55px]" :index="String(fourMenu.name)"
class="!h-[52px] !pl-[55px]"
:index="String(fourMenu.name)"
@click="toLink(fourMenu)">
<template #title>
<span class="text-[14px]">{{ fourMenu.meta.title
@ -268,7 +282,8 @@
</el-menu-item>
</template>
</el-sub-menu>
<el-menu-item v-else-if="twoMenu.meta.app && twoMenu.meta.app == plugMenuType"
<el-menu-item
v-else-if="twoMenu.meta.app && twoMenu.meta.app == plugMenuType"
class="!pl-[25px] text-[#333]" :index="String(twoMenu.name)"
@click="toLink(twoMenu)">
<template #title>
@ -284,9 +299,11 @@
</template>
</el-sub-menu>
<el-menu-item v-else-if="twoMenu.meta.attr == 'system' && !twoMenu.meta.app"
class="!pl-[25px] text-[#333]" :index="String(twoMenu.name)" @click="toLink(twoMenu)">
class="!pl-[25px] text-[#333]" :index="String(twoMenu.name)"
@click="toLink(twoMenu)">
<template #title>
<div v-if="twoMenu.meta.icon" class="w-[16px] h-[16px] relative flex items-center">
<div v-if="twoMenu.meta.icon"
class="w-[16px] h-[16px] relative flex items-center">
<icon v-if="twoMenu.meta.icon" :name="twoMenu.meta.icon"
class="absolute !w-auto" size="18px" />
</div>
@ -295,10 +312,12 @@
</el-menu-item>
</template>
</template>
</template>
<!-- 浮动样式 -->
<template v-if="floatMenuStyle">
<div class="!border-0 !border-t-[1px] border-solid mx-[25px] bg-[#f7f7f7] my-[5px]"></div>
<div
:class="['!border-0 border-solid mx-[25px] bg-[#f7f7f7] my-[5px]', floatMenuStyle && !applyTypeList.length ? '' : '!border-t-[1px]']">
</div>
<template v-for="(twoMenu, twoIndex) in menus">
<el-sub-menu :index="String(twoMenu.meta.title)"
v-if="twoMenu.meta.attr == 'common' && !twoMenu.meta.app && twoMenu.children">
@ -399,27 +418,25 @@ const userStore = useUserStore()
const systemStore = useSystemStore()
const route = useRoute()
const router = useRouter()
let globalAppKey = ref('') //
let localMenuKey = ref('') //
const globalAppKey = ref('') //
const localMenuKey = ref('') //
globalAppKey.value = storage.get('menuAppStorage')
localMenuKey.value = storage.get('menuAppStorage')
// start
let applyList = ref([]);
let applyTypeList = ref([]);
let otherTypeList = ref([]); // \\
let aaa = ref(false)
const applyList = ref([])
const applyTypeList = ref([])
const otherTypeList = ref([]) // \\
// let aaa = ref(true)
const getApplelist = async () => {
const res = await getApply()
applyList.value = applyList.value.concat(res.data)
applyList.value.forEach((item, index) => {
if (item.type == 'app')
applyTypeList.value.push(item.key)
if (item.type == 'addon')
otherTypeList.value.push(item.key)
if (item.type == 'app') { applyTypeList.value.push(item.key) }
if (item.type == 'addon') { otherTypeList.value.push(item.key) }
})
otherTypeList.value = otherTypeList.value.concat(['member', 'overview'])
aaa.value = true;
// aaa.value = true;
}
getApplelist()
const floatActive = ref(false)
@ -437,13 +454,13 @@ const getAppLink = () => {
}
getAppLink()
const appToLink = (addon: string) => {
globalAppKey.value = addon;
localMenuKey.value = addon;
globalAppKey.value = addon
localMenuKey.value = addon
storage.set({ key: 'menuAppStorage', data: addon })
storage.set({ key: 'plugMenuTypeStorage', data: '' })
let data = userStore.appMenuList
const data = userStore.appMenuList
if (!data.length) {
data.push(addon)
} else if (!data.includes(addon)) {
@ -453,11 +470,13 @@ const appToLink = (addon: string) => {
userStore.setAppMenuList(data)
floatActive.value = false
router.push({ name: appLink.value[addon] })
}
const homeClick = () => {
const key = storage.get('menuAppStorage')
key ? router.push({ name: appLink.value[key] }) : router.push({ path: '/' })
}
// end
const menus = computed(() => {
const menus = []
userStore.routers.forEach((item, index) => {
@ -483,35 +502,34 @@ const getAppInfo = (type) => {
})
}
let currMetaAppType = "";
let plugMenuType = ref(''); //
let currentRoute = ref(''); //
let currMetaAppType = ''
const plugMenuType = ref('') //
const currentRoute = ref('') //
watch(route, () => {
plugMenuType.value = storage.get('plugMenuTypeStorage')
let data = route.matched[1]
currentRoute.value = route.matched[1];
localMenuKey.value = data.meta.key;
const data = route.matched[1]
currentRoute.value = route.matched[1]
localMenuKey.value = data.meta.key
data.meta.app = !data.meta.app && !data.meta.attr ? 'member' : data.meta.app;
data.meta.app = !data.meta.app && !data.meta.attr ? 'member' : data.meta.app
// applist
setTimeout(() => {
//
if (data.meta.app && (!currMetaAppType || currMetaAppType != data.meta.app)) {
appInfo.value = {};
currMetaAppType = data.meta.app;
let appInfoKey = otherTypeList.value.includes(data.meta.app) ? globalAppKey.value : data.meta.app;
appInfo.value = {}
currMetaAppType = data.meta.app
const appInfoKey = otherTypeList.value.includes(data.meta.app) ? globalAppKey.value : data.meta.app
getAppInfo(appInfoKey)
}
}, 800);
}, 800)
systemStore.$patch(state => {
state.menuDrawer = false
})
}, { immediate: true })
//
const toLink = (data) => {
if (data.meta.key != 'official_market') {
@ -527,20 +545,20 @@ const sidebar = computed(() => {
})
//
let floatMenuStyle = ref(false);
floatMenuStyle.value = storage.get('floatMenuStyle') || false;
const floatMenuStyle = ref(false)
floatMenuStyle.value = storage.get('floatMenuStyle') || false
const cutMenuStyleFn = () => {
floatMenuStyle.value = true;
storage.set({ key: 'floatMenuStyle', data: true });
location.reload();
floatMenuStyle.value = true
storage.set({ key: 'floatMenuStyle', data: true })
location.reload()
}
//
const isTwoMenuFn = (item) => {
let bool = (otherTypeList.value.includes(localMenuKey.value) && globalAppKey.value == item.meta.app)
|| (floatMenuStyle.value && !applyTypeList.value.includes(localMenuKey.value) && !otherTypeList.value.includes(localMenuKey.value) && globalAppKey.value == item.meta.app)
|| (floatMenuStyle.value && applyTypeList.value.includes(localMenuKey.value) && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
|| (floatMenuStyle.value && !applyTypeList.value.length && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
|| (!floatMenuStyle.value && !otherTypeList.value.includes(localMenuKey.value) && (item.meta.key == localMenuKey.value || item.meta.app == localMenuKey.value))
return bool;
}
@ -608,9 +626,11 @@ const isTwoMenuFn = (item) => {
color: #6d7278;
}
.cut-style.qx {
transform: translateX(-50%);
}
//
.two-type {
.logo-wrap {
@ -669,7 +689,6 @@ const isTwoMenuFn = (item) => {
}
}
//
.three-type {
.logo-wrap {
@ -738,5 +757,4 @@ const isTwoMenuFn = (item) => {
.menus-wrap {
height: calc(100vh - 64px);
}
</style>
}</style>

View File

@ -10,7 +10,7 @@
<el-main :class="['main-wrap h-full p-0',{'bg-page': dark}]">
<el-scrollbar>
<div class="p-[10px]">
<div>
<router-view v-slot="{ Component, route }" v-if="appStore.routeRefreshTag">
<component :is="Component" :key="route.fullPath" />
</router-view>

View File

@ -39,7 +39,7 @@ router.beforeEach(async (to, from, next) => {
// 如果已加载路由
if (userStore.routers.length) {
if (to.path === loginPath) {
next(`/${getAppType()}`)
next('/')
} else {
next()
}
@ -48,14 +48,16 @@ router.beforeEach(async (to, from, next) => {
await userStore.getAuthMenus()
// 设置首页路由
const currApp = storage.get('menuAppStorage')
const firstRoute = findFirstValidRoute(userStore.routers)
if (currApp) {
ROOT_ROUTER.redirect = { name: userStore.addonIndexRoute[currApp] ?? firstRoute }
} else {
ROOT_ROUTER.redirect = { name: firstRoute }
}
console.log(currApp, ROOT_ROUTER.redirect)
router.addRoute(ROOT_ROUTER)
// 设置应用首页路由
ADMIN_ROUTE.children[0].redirect = { name: firstRoute }
router.addRoute(ADMIN_ROUTE)
// 添加动态路由
userStore.routers.forEach(route => {
// 页面装修

View File

@ -3,12 +3,13 @@ import { getToken, setToken, removeToken, getAppType } from '@/utils/common'
import { login, getAuthMenus } from '@/app/api/auth'
import storage from '@/utils/storage'
import router from '@/router'
import { formatRouters } from '@/router/routers'
import { formatRouters, findFirstValidRoute } from '@/router/routers'
interface User {
token: string,
userInfo: object,
routers: any[],
addonIndexRoute: Record<string, symbol>,
rules: any[],
appMenuList: any[]
}
@ -19,6 +20,7 @@ const useSystemStore = defineStore('user', {
token: getToken() || '',
userInfo: storage.get('userinfo') || {},
routers: [],
addonIndexRoute: {},
rules: [],
appMenuList: storage.get('appMenuList' + (storage.get('userinfo') ? storage.get('userinfo').username : '')) || []
}
@ -52,6 +54,16 @@ const useSystemStore = defineStore('user', {
getAuthMenus()
.then((res) => {
this.routers = formatRouters(res.data)
// 获取插件的首个菜单
this.routers.forEach((item, index) => {
if (item.meta.app !== '') {
if (item.children && item.children.length) {
this.addonIndexRoute[item.meta.app] = findFirstValidRoute(item.children)
} else {
this.addonIndexRoute[item.meta.app] = item.name
}
}
})
resolve(res)
})
.catch((error) => {

View File

@ -221,7 +221,7 @@ html.dark {
.el-input__wrapper, .el-input-group__append, .el-textarea__inner{
border-radius: 0 !important;
}
.el-button{
.el-button:not(.is-round){
border-radius: 2px !important;
}

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 3883393 */
src: url('//at.alicdn.com/t/c/font_3883393_236yfsl6lh5.woff2?t=1694750730982') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_236yfsl6lh5.woff?t=1694750730982') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_236yfsl6lh5.ttf?t=1694750730982') format('truetype');
src: url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.woff2?t=1694854845443') format('woff2'),
url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.woff?t=1694854845443') format('woff'),
url('//at.alicdn.com/t/c/font_3883393_0ym8w80fw9vi.ttf?t=1694854845443') format('truetype');
}
.iconfont {
@ -13,6 +13,18 @@
-moz-osx-font-smoothing: grayscale;
}
.iconanzhuang:before {
content: "\e676";
}
.iconshouye:before {
content: "\e675";
}
.iconshouye-shouye:before {
content: "\e638";
}
.icondian:before {
content: "\ec1e";
}