管理插件

This commit is contained in:
luJianJun 2023-08-31 19:10:16 +08:00
parent a4493420db
commit 6151ed40d7
5 changed files with 659 additions and 7 deletions

View File

@ -72,6 +72,19 @@ router.beforeEach(async (to, from, next) => {
api.system.index.get().then((response) => {
if (response.code == 200) {
// 缓存
// console.log(response.data)
response.data.menu[1].children.push({
component: "system/application",
meta:{ type: "application", icon: "x-icon-chrome-filled", title: "应用插件管理", app: "admin" },
app:"admin",
icon:"x-icon-code",
title:"应用插件管理",
type:"application",
name:"systemapplication",
path:"/system/application",
redirect:""
})
for (const key in response.data) {
tool.data.set(key, response.data[key]);
if (key == 'layout') {
@ -155,12 +168,14 @@ function loadComponent(component) {
function flatAsyncRoutes(routes, breadcrumb = []) {
let res = []
routes.forEach(route => {
const tmp = { ...route
const tmp = {
...route
}
if (tmp.children) {
let childrenBreadcrumb = [...breadcrumb]
childrenBreadcrumb.push(route)
let tmpRoute = { ...route
let tmpRoute = {
...route
}
tmpRoute.meta.breadcrumb = childrenBreadcrumb
delete tmpRoute.children
@ -180,7 +195,8 @@ function flatAsyncRoutes(routes, breadcrumb = []) {
}
//过滤树
function treeFilter(tree, func) {
return tree.map(node => ({ ...node
return tree.map(node => ({
...node
})).filter(node => {
node.children = node.children && treeFilter(node.children, func)
return func(node) || (node.children && node.children.length)

View File

@ -213,6 +213,7 @@ export default {
margin-bottom: 16px;
border:1px solid #e4e7ed;
border-radius:4px;
min-width:280px;
}
.tab-box {

View File

@ -0,0 +1,111 @@
<template>
<div class="dis-f" style="flex-direction: column;height:100%;">
<div class="tab-list-box dis-f jus-x al-item">
<div v-for="(item, i) in tabList" :key="i" class="tab-box" :class="{ 'click-tab': item.type === activeName }"
@click="changeTab(item.type)">
{{ item.title }}
</div>
</div>
<div class="flex-1 dis-f">
<div class="hid-box" :class="{ 'tab-info-box-hid': activeName != 'manage' }">
<div class="tran-width tab-info-box" :class="{ 'tab-info-box-hid': activeName != 'manage' }">1</div>
</div>
<div class="hid-box" :class="{ 'tab-info-box-hid': activeName != 'market' }">
<div class="tran-width tab-info-box">
<plugin-market></plugin-market>
</div>
</div>
</div>
</div>
</template>
<script>
import pluginMarket from './pluginMarket.vue';
export default {
data() {
return {
activeName: 'manage',
tabList: [{ title: '插件管理', type: 'manage' }, { title: '插件市场', type: 'market' }]
}
},
components: {
pluginMarket
},
mounted() {
},
methods: {
changeTab(type) {
this.activeName = type
}
}
}
</script>
<style scoped>
.dis-f {
display: flex;
}
.flex-1 {
flex: 1;
}
.jus-x {
justify-content: center;
}
.al-item {
align-items: center;
}
.tran-width {
transition: width linear 0.2s;
}
.hid-box{
width:100%;
overflow: hidden;
}
.tab-list-box {
width: 100%;
height: 60px;
background: #fff;
font-size: 16px;
color: #525967;
position: relative;
z-index: 666;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, .1);
}
.tab-box {
height: 100%;
width: 100px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
padding: 0 10px;
transition: all linear 0.3s;
border-bottom: 2px solid transparent;
}
.click-tab {
color: #409eff;
border-bottom: 2px solid #409eff;
}
.tab-box:hover {
color: #409eff;
}
.tab-info-box-hid {
width: 0% !important;
}
.tab-info-box {
min-width: 100%;
height: 100%;
overflow: hidden;
background: #fff;
}</style>

View File

@ -0,0 +1,171 @@
<template>
<div class="dis-f warp pd-15 pos-r" ref="tabBox">
<div class="pop-box" v-show="popShow">
<pop-info :showPop="installPlugin"></pop-info>
</div>
<div class="tab-box dis-f al-item" @click="installPlugin" v-for="(item, i) in list" :key="i" :class="[
windowType === 1 ? 'tab-box-two' : windowType === 2 ? 'tab-box-one' : '',
windowType === 1 ? ((i + 1) % 2) ? 'mg-r-25' : '' :
windowType === 2 ? '' : ((i + 1) % 3) ? 'mg-r-25' : '']">
<img src="" class="img" alt="">
<div class="info-box">
<div class="title">
123456
</div>
<div class="tag-box">
<el-tag class="tag-mg" type="danger" v-for="(item,i) in 5" :key="i">Tag {{ item }}</el-tag>
</div>
<div class="info-text">
111111111111111111111111111111111111111
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import popInfo from './popInfo.vue'
let windowType = ref(0)
let list = ref([1, 2, 3, 4, 5, 6, 7, 8, 9])
let tabBox = ref(null)
let popShow = ref(false)
let resize
//
let setWindowType = () => {
resize = new ResizeObserver((e) => {
let width = e[0].contentRect.width
console.log(width)
windowType.value = width <= 800 && width > 500 ? 1 : width <= 500 ? 2 : 0
})
resize.observe(tabBox.value)
}
//
let installPlugin=()=>{
popShow.value=!popShow.value
}
onMounted(() => {
nextTick(() => setWindowType())
})
onUnmounted(() => {
resize.unobserve()
})
</script>
<style scoped>
.dis-f {
display: flex;
}
.flex-1 {
flex: 1;
}
.jus-x {
justify-content: center;
}
.al-item{
align-items: center;
}
.warp {
flex-wrap: wrap;
}
.pd-15 {
padding: 15px;
}
.mg-r-25 {
margin-right: 25px;
}
.pos-r{
position: relative;
}
.pop-box{
position: fixed;
top:0;
left:0;
z-index:999;
background: rgba(0,0,0,.5);
width:100vw;
height:100vh;
}
.tab-box .tag-box{
display: flex;
flex-wrap: wrap;
margin:5px 0;
}
.tab-box .tag-box .tag-mg{
margin:0 5px 5px 0
}
.tab-box .img {
width: 48px;
height: 48px;
margin-right: 16px;
border-radius: 10px;
}
.tab-box .info-box {
flex: 0.9;
overflow: hidden;
}
.tab-box .info-box .title {
color: #141e31;
flex-shrink: 1;
font-size: 16px;
font-weight: 500;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tab-box .info-box .info-text {
color: #838892;
font-size: 14px;
font-weight: 400;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width:100%;
}
.tab-box {
background: #fff;
border: 1px solid #ebecee;
border-radius: 6px;
-webkit-box-shadow: 0 4px 12px 0 rgba(0, 0, 0, .06);
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, .06);
cursor: pointer;
margin-bottom: 25px;
padding: 16px;
position: relative;
-webkit-transition: all .2s ease;
transition: all .2s ease;
width: calc(33.33333% - 16.7px);
}
.tab-box-two {
width: calc(50% - 12.5px) !important;
}
.tab-box-one {
width: 100% !important;
}
.tab-box:hover {
transform: translateY(-6px);
box-shadow: 0 10px 12px 0 rgba(0, 0, 0, .1);
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<div class="info-box dis-f jus-x al-item text-f">
<div class="title">
{{ 123456 }}
<div class="close" @click="closePop">
<el-icon><el-icon-close-bold /></el-icon>
</div>
</div>
<div class="info-data-box">
<div class="dis-f al-item jus-bet">
<div class="dis-f al-item">
<img src="" class="img" alt="">
<div>
<div class="data-title">123</div>
<div class="data-info-text">123456</div>
<div class="data-info-type data-info-type-m jus-x">
免费
</div>
</div>
</div>
<div class="install-btn">
安装
</div>
</div>
<div class="plugin-tag-title">
插件详情
</div>
<div class="dis-f jus-bet al-item">
<source src="/media/cc0-videos/flower.mp4" class="info-video" type="video/mp4" />
<img src="" class="info-video" alt="">
</div>
<div class="plugin-introduce">
1234567894513
</div>
<div class="plugin-tag-title">
相关详情
</div>
<div class="related-details">
<div class="box">
<div style="margin-bottom:8px;">
版本
</div>
<div class="text">
v1.10.1 <span class="history-text">版本历史</span>
</div>
</div>
<div class="line"></div>
<div class="box">
<div style="margin-bottom:8px;">开发者</div>
<div class="text">
123456456456456
</div>
</div>
<div class="line"></div>
<div class="box">
<div style="margin-bottom:8px;">业务场景</div>
<div class="dis-f" style="flex-wrap: wrap;">
<div class="business-type">123456</div>
<div class="business-type">2</div>
</div>
</div>
<div class="line"></div>
<div class="box">
<div style="margin-bottom:8px;">
帮助
</div>
<div class="dis-f al-item help-btn jus-x">
<el-icon><el-icon-collection /></el-icon>
<span class="text-mg">
使用说明
</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
let props=defineProps({
showPop:Function,
})
//
let closePop = ()=>{
props.showPop()
}
</script>
<style scoped>
img{
object-fit: contain;
}
.text-f{
font-family: -apple-system,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
font-variant-numeric: tabular-nums;
}
.dis-f {
display: flex;
}
.flex-1 {
flex: 1;
}
.jus-x {
justify-content: center;
}
.al-item {
align-items: center;
}
.jus-bet {
justify-content: space-between;
}
.pd-15 {
padding: 15px;
}
.mg-r-25 {
margin-right: 25px;
}
.pos-r {
position: relative;
}
.help-btn{
background: #fff;
color: #141e31;
height: 32px;
line-height: 30px;
padding: 0 20px;
border: 1px solid #d7d9dc;
border-radius: 3px;
cursor: pointer;
font-size: 14px;
font-weight: 400;
outline: none;
overflow: hidden;
position: relative;
text-align: center;
text-overflow: ellipsis;
cursor: pointer;
width:120px;
}
.help-btn .text-mg{
margin-left:5px ;
}
.history-text{
color: #409eff;
color: #409eff;
cursor: pointer;
display: inline-block;
margin-left: 4px;
text-decoration: underline;
}
.business-type{
background: #e6e8ed;
border: 1px solid #e6e8ed;
border-radius: 12px;
color: #525967;
font-size: 13px;
line-height: 18px;
padding: 2px 6px;
margin:0 4px 4px 0;
}
.related-details{
-webkit-box-align: start;
-ms-flex-align: start;
align-items: flex-start;
background: #f5f6f8;
border-radius: 4px;
display: -webkit-inline-box;
display: -ms-inline-flexbox;
display: inline-flex;
height: -webkit-fit-content;
height: -moz-fit-content;
height: fit-content;
padding: 20px;
color: #838892;
font-size: 12px;
font-weight: 400;
width: 100%;
}
.related-details .line{
height:76px;
margin:0 20px;
background:#ebecee;
width:1px;
}
.related-details .text{
color: #141e31;
}
.related-details .box{
width: calc(25% - 1px);
}
.plugin-introduce{
white-space: pre-wrap;
color: #141e31;
font-family: -apple-system,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
font-variant-numeric: tabular-nums;
font-size: 14px;
}
.info-video{
width:calc(50% - 20px);
height:330px;
margin-bottom:20px;
}
.plugin-tag-title {
color: #141e31;
font-size: 16px;
font-weight: 500;
height: 22px;
line-height: 22px;
margin-bottom: 10px;
margin-top: 30px;
font-family: -apple-system,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
font-variant-numeric: tabular-nums;
}
.install-btn {
border: 1px solid;
border-radius: 3px;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: 400;
outline: none;
overflow: hidden;
position: relative;
text-align: center;
text-overflow: ellipsis;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
white-space: nowrap;
background: #409eff;
border-color: #409eff;
color: #fff;
cursor: pointer;
font-size: 14px;
font-weight: 400;
height: 36px;
padding: 0 20px;
line-height: 34px;
}
.install-btn:hover{
background:#65affb;
}
.info-box {
position: absolute;
bottom: 0;
left: 0;
height: 90%;
background: #fff;
width: 100%;
flex-direction: column;
}
.info-box .title {
height: 60px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid #ebecee;
font-size: 20px;
width: 100%;
}
.info-box .title .close {
position: absolute;
right: 30px;
cursor: pointer;
width: 20px;
height: 20px;
}
.info-box .title .close:hover {
background: #f0f1f4;
}
.info-data-box {
padding: 40px;
flex: 1;
max-width: 1200px;
width: 100%;
overflow-y:hidden;
}
.info-data-box .img {
width: 80px;
height: 80px;
border-radius: 10px;
margin-right: 16px;
}
.info-data-box .data-title {
color: #141e31;
display: inline-block;
font-size: 16px;
font-weight: 500;
line-height: 22px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.info-data-box .data-info-text {
word-wrap: break-word;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
color: #838892;
display: -webkit-box;
font-size: 14px;
font-weight: 400;
line-height: 20px;
margin-top: 6px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
}
.info-data-box .data-info-type {
-webkit-box-align: start;
-ms-flex-align: start;
align-items: flex-start;
background: #f0f1f4;
border: 1px solid #f0f1f4;
border-radius: 12px;
color: #525967;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
font-size: 13px;
line-height: 18px;
padding: 2px 6px;
margin-top: 6px;
}
.info-data-box .data-info-type-m {
background-color: rgba(36, 138, 249, .15);
color: #2f7deb;
}
</style>