mirror of https://github.com/halo-dev/halo-admin
Remove float more actions (#245)
* Remove float more actions * Use page header instead of list item * pref: theme list control button. Co-authored-by: Ryan Wang <i@ryanc.cc>pull/248/head
parent
6f083f3a85
commit
37573bf7f1
|
@ -2601,34 +2601,6 @@
|
|||
"webpack-sources": "^1.4.3"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.7.tgz",
|
||||
"integrity": "sha512-xQ8/GZmRPdQ3EinnE0IXwdVoDzh7Dowo0MowoyBuScEBXrRabw6At5/IdtD3waKklKW5PGokPsm8KRN6rvQ1cw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/mini-css-extract-plugin": "^0.9.1",
|
||||
"chalk": "^3.0.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
"merge-source-map": "^1.1.0",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
|
@ -16155,6 +16127,86 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.7.tgz",
|
||||
"integrity": "sha512-xQ8/GZmRPdQ3EinnE0IXwdVoDzh7Dowo0MowoyBuScEBXrRabw6At5/IdtD3waKklKW5PGokPsm8KRN6rvQ1cw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/mini-css-extract-plugin": "^0.9.1",
|
||||
"chalk": "^3.0.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
"merge-source-map": "^1.1.0",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
|
||||
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/color-name": "^1.1.1",
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-ls": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-ls/-/vue-ls-3.2.1.tgz",
|
||||
|
|
|
@ -130,7 +130,8 @@
|
|||
{
|
||||
"ignoreReadBeforeAssign": false
|
||||
}
|
||||
]
|
||||
],
|
||||
"comma-dangle": 0
|
||||
}
|
||||
},
|
||||
"husky": {
|
||||
|
|
|
@ -1,218 +0,0 @@
|
|||
<template>
|
||||
<div class="page-header">
|
||||
<div class="page-header-index-wide">
|
||||
<s-breadcrumb />
|
||||
<div class="detail">
|
||||
<div
|
||||
class="main"
|
||||
v-if="!$route.meta.hiddenHeaderContent"
|
||||
>
|
||||
<div class="row">
|
||||
<img
|
||||
v-if="logo"
|
||||
:src="logo"
|
||||
class="logo"
|
||||
/>
|
||||
<!-- <h1 v-if="title" class="title">{{ title }}</h1> -->
|
||||
<div class="action">
|
||||
<slot name="action"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div
|
||||
v-if="avatar"
|
||||
class="avatar"
|
||||
>
|
||||
<a-avatar :src="avatar" />
|
||||
</div>
|
||||
<div
|
||||
v-if="this.$slots.content"
|
||||
class="headerContent"
|
||||
>
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<div
|
||||
v-if="this.$slots.extra"
|
||||
class="extra"
|
||||
>
|
||||
<slot name="extra"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<slot name="pageMenu"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@/components/Tools/Breadcrumb'
|
||||
|
||||
export default {
|
||||
name: 'PageHeader',
|
||||
components: {
|
||||
's-breadcrumb': Breadcrumb
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: [String, Boolean],
|
||||
default: true,
|
||||
required: false
|
||||
},
|
||||
logo: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
avatar: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page-header {
|
||||
background: #fff;
|
||||
padding: 16px 32px 0;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
|
||||
.breadcrumb {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail {
|
||||
display: flex;
|
||||
/*margin-bottom: 16px;*/
|
||||
|
||||
.avatar {
|
||||
flex: 0 1 72px;
|
||||
margin: 0 24px 8px 0;
|
||||
|
||||
& > span {
|
||||
border-radius: 72px;
|
||||
display: block;
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
width: 100%;
|
||||
flex: 0 1 auto;
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.avatar {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
|
||||
font-size: 20px;
|
||||
line-height: 28px;
|
||||
font-weight: 500;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
margin-bottom: 16px;
|
||||
flex: auto;
|
||||
}
|
||||
.logo {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 4px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.content,
|
||||
.headerContent {
|
||||
flex: auto;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
line-height: 22px;
|
||||
|
||||
.link {
|
||||
margin-top: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
a {
|
||||
font-size: 14px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.extra {
|
||||
flex: 0 1 auto;
|
||||
margin-left: 88px;
|
||||
min-width: 242px;
|
||||
text-align: right;
|
||||
}
|
||||
.action {
|
||||
margin-left: 56px;
|
||||
min-width: 266px;
|
||||
flex: 0 1 auto;
|
||||
text-align: right;
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile .page-header {
|
||||
.main {
|
||||
.row {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.avatar {
|
||||
flex: 0 1 25%;
|
||||
margin: 0 2% 8px 0;
|
||||
}
|
||||
|
||||
.content,
|
||||
.headerContent {
|
||||
flex: 0 1 70%;
|
||||
|
||||
.link {
|
||||
margin-top: 16px;
|
||||
line-height: 24px;
|
||||
|
||||
a {
|
||||
font-size: 14px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.extra {
|
||||
flex: 1 1 auto;
|
||||
margin-left: 0;
|
||||
min-width: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.action {
|
||||
margin-left: unset;
|
||||
min-width: 266px;
|
||||
flex: 0 1 auto;
|
||||
text-align: left;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,2 +0,0 @@
|
|||
import PageHeader from './PageHeader'
|
||||
export default PageHeader
|
|
@ -1,45 +0,0 @@
|
|||
<template>
|
||||
<a-breadcrumb class="breadcrumb">
|
||||
<a-breadcrumb-item
|
||||
v-for="(item, index) in breadList"
|
||||
:key="item.name"
|
||||
>
|
||||
<router-link
|
||||
v-if="item.name != name && index != 1"
|
||||
:to="{ path: item.path === '' ? '/' : item.path }"
|
||||
>{{ item.meta.title }}</router-link>
|
||||
<span v-else>{{ item.meta.title }}</span>
|
||||
</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
breadList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
getBreadcrumb() {
|
||||
this.breadList = []
|
||||
// this.breadList.push({name: 'index', path: '/dashboard/', meta: {title: '首页'}})
|
||||
|
||||
this.name = this.$route.name
|
||||
this.$route.matched.forEach((item) => {
|
||||
// item.name !== 'index' && this.breadList.push(item)
|
||||
this.breadList.push(item)
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
// eslint-disable-next-line
|
||||
import { BasicLayout, PageView } from '@/layouts'
|
||||
import { BasicLayout, PageView, BlankLayout } from '@/layouts'
|
||||
|
||||
export const asyncRouterMap = [
|
||||
{
|
||||
|
@ -116,7 +116,7 @@ export const asyncRouterMap = [
|
|||
{
|
||||
path: '/interface',
|
||||
name: 'Interface',
|
||||
component: PageView,
|
||||
component: BlankLayout,
|
||||
redirect: '/interface/themes',
|
||||
meta: { title: '外观', icon: 'skin' },
|
||||
children: [
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
Menu,
|
||||
Modal,
|
||||
notification,
|
||||
PageHeader,
|
||||
Pagination,
|
||||
Popconfirm,
|
||||
Popover,
|
||||
|
@ -78,6 +79,7 @@ Vue.use(List)
|
|||
Vue.use(LocaleProvider)
|
||||
Vue.use(Menu)
|
||||
Vue.use(Modal)
|
||||
Vue.use(PageHeader)
|
||||
Vue.use(Pagination)
|
||||
Vue.use(Popconfirm)
|
||||
Vue.use(Popover)
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
<template>
|
||||
<div :style="!$route.meta.hiddenHeaderContent ? 'margin: -24px -24px 0px;' : null">
|
||||
<!-- pageHeader , route meta :true on hide -->
|
||||
<page-header v-if="!$route.meta.hiddenHeaderContent" :title="pageTitle" :logo="logo" :avatar="avatar">
|
||||
<slot slot="action" name="action"></slot>
|
||||
<slot slot="content" name="headerContent"></slot>
|
||||
<div slot="content" v-if="!this.$slots.headerContent && description">
|
||||
<p style="font-size: 14px;color: rgba(0,0,0,.65)">{{ description }}</p>
|
||||
<div class="link">
|
||||
<template v-for="(link, index) in linkList">
|
||||
<a :key="index" :href="link.href">
|
||||
<a-icon :type="link.icon" />
|
||||
<span>{{ link.title }}</span>
|
||||
</a>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
class="page-header"
|
||||
v-if="!$route.meta.hiddenHeaderContent"
|
||||
>
|
||||
<div class="page-header-index-wide">
|
||||
<a-page-header
|
||||
:title="title"
|
||||
:sub-title="subTitle"
|
||||
:breadcrumb="{ props: { routes:breadList } }"
|
||||
>
|
||||
<slot
|
||||
name="extra"
|
||||
slot="extra"
|
||||
>
|
||||
</slot>
|
||||
</a-page-header>
|
||||
</div>
|
||||
</page-header>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="page-header-index-wide">
|
||||
<slot>
|
||||
|
@ -27,90 +29,57 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import PageHeader from '@/components/PageHeader'
|
||||
|
||||
export default {
|
||||
name: 'PageView',
|
||||
components: {
|
||||
PageHeader
|
||||
},
|
||||
props: {
|
||||
avatar: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
title: {
|
||||
type: [String, Boolean],
|
||||
default: true
|
||||
},
|
||||
logo: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
default: null,
|
||||
},
|
||||
subTitle: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageTitle: null,
|
||||
description: null,
|
||||
linkList: [],
|
||||
extraImage: '',
|
||||
search: false,
|
||||
tabs: {}
|
||||
breadList: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getPageMeta()
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
updated() {
|
||||
this.getPageMeta()
|
||||
watch: {
|
||||
$route() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getPageMeta() {
|
||||
// eslint-disable-next-line
|
||||
this.pageTitle = (typeof(this.title) === 'string' || !this.title) ? this.title : this.$route.meta.title
|
||||
|
||||
const content = this.$refs.content
|
||||
if (content) {
|
||||
if (content.pageMeta) {
|
||||
Object.assign(this, content.pageMeta)
|
||||
} else {
|
||||
this.description = content.description
|
||||
this.linkList = content.linkList
|
||||
this.extraImage = content.extraImage
|
||||
this.search = content.search === true
|
||||
this.tabs = content.tabs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
getBreadcrumb() {
|
||||
this.breadList = []
|
||||
this.$route.matched.forEach((item) => {
|
||||
item.breadcrumbName = item.meta.title
|
||||
this.breadList.push(item)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.content {
|
||||
margin: 24px 24px 0;
|
||||
.link {
|
||||
margin-top: 16px;
|
||||
&:not(:empty) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
a {
|
||||
margin-right: 32px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
display: inline-block;
|
||||
i {
|
||||
font-size: 24px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
span {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-header {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
.ant-page-header {
|
||||
padding: 16px 0px;
|
||||
}
|
||||
margin: 0 0 24px 0;
|
||||
}
|
||||
|
||||
.mobile .page-header,
|
||||
.tablet .page-header {
|
||||
.ant-page-header {
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="10"
|
||||
|
@ -227,73 +227,74 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</page-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
import MenuSelectTree from './components/MenuSelectTree'
|
||||
import { PageView } from '@/layouts'
|
||||
import menuApi from '@/api/menu'
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
ellipsis: true,
|
||||
scopedSlots: { customRender: 'name' }
|
||||
scopedSlots: { customRender: 'name' },
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
ellipsis: true,
|
||||
dataIndex: 'url'
|
||||
dataIndex: 'url',
|
||||
},
|
||||
{
|
||||
title: '分组',
|
||||
ellipsis: true,
|
||||
dataIndex: 'team'
|
||||
dataIndex: 'team',
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'priority'
|
||||
dataIndex: 'priority',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
scopedSlots: { customRender: 'action' }
|
||||
}
|
||||
scopedSlots: { customRender: 'action' },
|
||||
},
|
||||
]
|
||||
export default {
|
||||
components: { MenuSelectTree },
|
||||
components: { MenuSelectTree, PageView },
|
||||
mixins: [mixin, mixinDevice],
|
||||
data() {
|
||||
return {
|
||||
table: {
|
||||
columns,
|
||||
data: [],
|
||||
loading: false
|
||||
loading: false,
|
||||
},
|
||||
form: {
|
||||
model: {
|
||||
target: '_self'
|
||||
target: '_self',
|
||||
},
|
||||
saving: false,
|
||||
errored: false,
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '* 菜单名称不能为空', trigger: ['change'] },
|
||||
{ max: 50, message: '* 菜单名称的字符长度不能超过 50', trigger: ['change'] }
|
||||
{ max: 50, message: '* 菜单名称的字符长度不能超过 50', trigger: ['change'] },
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: '* 菜单地址不能为空', trigger: ['change'] },
|
||||
{ max: 1023, message: '* 菜单地址的字符长度不能超过 1023', trigger: ['change'] }
|
||||
{ max: 1023, message: '* 菜单地址的字符长度不能超过 1023', trigger: ['change'] },
|
||||
],
|
||||
icon: [{ max: 50, message: '* 菜单图标的字符长度不能超过 50', trigger: ['change'] }],
|
||||
team: [{ max: 255, message: '* 菜单分组的字符长度不能超过 255', trigger: ['change'] }]
|
||||
team: [{ max: 255, message: '* 菜单分组的字符长度不能超过 255', trigger: ['change'] }],
|
||||
},
|
||||
moreField: false
|
||||
moreField: false,
|
||||
},
|
||||
teams: {
|
||||
data: []
|
||||
}
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -305,7 +306,7 @@ export default {
|
|||
},
|
||||
isUpdateMode() {
|
||||
return !!this.form.model.id
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.handleListMenus()
|
||||
|
@ -316,7 +317,7 @@ export default {
|
|||
this.table.loading = true
|
||||
menuApi
|
||||
.listTree()
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.table.data = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -326,14 +327,14 @@ export default {
|
|||
})
|
||||
},
|
||||
handleListTeams() {
|
||||
menuApi.listTeams().then(response => {
|
||||
menuApi.listTeams().then((response) => {
|
||||
this.teams.data = response.data.data
|
||||
})
|
||||
},
|
||||
handleDeleteMenu(id) {
|
||||
menuApi
|
||||
.delete(id)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -343,7 +344,7 @@ export default {
|
|||
},
|
||||
handleCreateOrUpdateMenu() {
|
||||
const _this = this
|
||||
_this.$refs.menuForm.validate(valid => {
|
||||
_this.$refs.menuForm.validate((valid) => {
|
||||
if (valid) {
|
||||
_this.form.saving = true
|
||||
if (_this.isUpdateMode) {
|
||||
|
@ -381,7 +382,7 @@ export default {
|
|||
_this.handleListMenus()
|
||||
_this.handleListTeams()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div>
|
||||
<page-view>
|
||||
<a-row :gutter="12">
|
||||
<a-col
|
||||
:xl="6"
|
||||
|
@ -70,18 +70,20 @@
|
|||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</page-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import themeApi from '@/api/theme'
|
||||
import ThemeFile from './components/ThemeFile'
|
||||
import { PageView } from '@/layouts'
|
||||
import { codemirror } from 'vue-codemirror-lite'
|
||||
import 'codemirror/mode/htmlmixed/htmlmixed.js'
|
||||
export default {
|
||||
components: {
|
||||
codemirror,
|
||||
ThemeFile
|
||||
ThemeFile,
|
||||
PageView,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -90,7 +92,7 @@ export default {
|
|||
tabSize: 4,
|
||||
mode: 'text/html',
|
||||
lineNumbers: true,
|
||||
line: true
|
||||
line: true,
|
||||
},
|
||||
files: [],
|
||||
filesLoading: false,
|
||||
|
@ -100,7 +102,7 @@ export default {
|
|||
themesLoading: false,
|
||||
selectedTheme: {},
|
||||
saving: false,
|
||||
saveErrored: false
|
||||
saveErrored: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -110,7 +112,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
handleGetActivatedTheme() {
|
||||
themeApi.getActivatedTheme().then(response => {
|
||||
themeApi.getActivatedTheme().then((response) => {
|
||||
this.selectedTheme = response.data.data
|
||||
})
|
||||
},
|
||||
|
@ -118,7 +120,7 @@ export default {
|
|||
this.filesLoading = true
|
||||
themeApi
|
||||
.listFilesActivated()
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.files = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -131,7 +133,7 @@ export default {
|
|||
this.themesLoading = true
|
||||
themeApi
|
||||
.listAll()
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.themes = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -145,7 +147,7 @@ export default {
|
|||
this.filesLoading = true
|
||||
themeApi
|
||||
.listFiles(themeId)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.files = response.data.data
|
||||
this.content = ''
|
||||
this.file = {}
|
||||
|
@ -178,10 +180,10 @@ export default {
|
|||
_this.content = ''
|
||||
_this.file = {}
|
||||
_this.buttonDisabled = true
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
themeApi.getContent(this.selectedTheme.id, file.path).then(response => {
|
||||
themeApi.getContent(this.selectedTheme.id, file.path).then((response) => {
|
||||
this.content = response.data.data
|
||||
this.file = file
|
||||
this.buttonDisabled = false
|
||||
|
@ -199,7 +201,7 @@ export default {
|
|||
this.saving = false
|
||||
}, 400)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
<template>
|
||||
<div>
|
||||
<page-view
|
||||
:title="activatedTheme?activatedTheme.name:'无'"
|
||||
subTitle="当前启用"
|
||||
>
|
||||
<template slot="extra">
|
||||
<a-button
|
||||
key="2"
|
||||
icon="reload"
|
||||
:loading="themeLoading"
|
||||
@click="handleReload"
|
||||
>
|
||||
刷新
|
||||
</a-button>
|
||||
<a-button
|
||||
key="1"
|
||||
type="primary"
|
||||
icon="plus"
|
||||
@click="uploadThemeVisible = true"
|
||||
>
|
||||
安装
|
||||
</a-button>
|
||||
</template>
|
||||
<a-row
|
||||
:gutter="12"
|
||||
type="flex"
|
||||
|
@ -26,7 +47,7 @@
|
|||
:alt="item.name"
|
||||
:src="item.screenshots || '/images/placeholder.jpg'"
|
||||
loading="lazy"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
<template
|
||||
class="ant-card-actions"
|
||||
|
@ -112,35 +133,6 @@
|
|||
@close="onThemeSettingsClose"
|
||||
/>
|
||||
|
||||
<div style="position: fixed;bottom: 30px;right: 30px;">
|
||||
<a-dropdown
|
||||
placement="topLeft"
|
||||
:trigger="['click']"
|
||||
>
|
||||
<a-button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
icon="plus"
|
||||
size="large"
|
||||
></a-button>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="javascript:void(0);"
|
||||
@click="uploadThemeVisible = true"
|
||||
>安装主题</a>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<a
|
||||
rel="noopener noreferrer"
|
||||
href="javascript:void(0);"
|
||||
@click="handleReload"
|
||||
>刷新列表</a>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
<a-modal
|
||||
title="安装主题"
|
||||
v-model="uploadThemeVisible"
|
||||
|
@ -162,8 +154,7 @@
|
|||
label="点击选择主题包或将主题包拖拽到此处<br>仅支持 ZIP 格式的文件"
|
||||
:uploadHandler="uploadHandler"
|
||||
@success="handleUploadSuccess"
|
||||
>
|
||||
</FilePondUpload>
|
||||
></FilePondUpload>
|
||||
<a-alert
|
||||
type="info"
|
||||
closable
|
||||
|
@ -255,7 +246,7 @@
|
|||
>
|
||||
<template slot="message">
|
||||
远程地址即主题仓库地址,使用这种方式安装的一般为开发版本,请谨慎使用。
|
||||
<br>更多主题请访问:
|
||||
<br />更多主题请访问:
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://halo.run/p/themes"
|
||||
|
@ -282,18 +273,20 @@
|
|||
:filed="prepareUpdateTheme.id"
|
||||
:multiple="false"
|
||||
@success="handleUploadSuccess"
|
||||
>
|
||||
</FilePondUpload>
|
||||
></FilePondUpload>
|
||||
</a-modal>
|
||||
</div>
|
||||
</page-view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ThemeSettingDrawer from './components/ThemeSettingDrawer'
|
||||
import { PageView } from '@/layouts'
|
||||
import themeApi from '@/api/theme'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ThemeSettingDrawer
|
||||
PageView,
|
||||
ThemeSettingDrawer,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -311,21 +304,24 @@ export default {
|
|||
fetchingUrl: null,
|
||||
uploadHandler: themeApi.upload,
|
||||
updateByUploadHandler: themeApi.updateByUpload,
|
||||
prepareUpdateTheme: {}
|
||||
prepareUpdateTheme: {},
|
||||
activatedTheme: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sortedThemes() {
|
||||
const data = this.themes.slice(0)
|
||||
return data.sort(function(a, b) {
|
||||
return data.sort((a, b) => {
|
||||
return b.activated - a.activated
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.handleListThemes()
|
||||
this.handleGetActivatedTheme()
|
||||
},
|
||||
destroyed: function() {
|
||||
this.$log.debug('Theme list destroyed.')
|
||||
if (this.themeSettingVisible) {
|
||||
this.themeSettingVisible = false
|
||||
}
|
||||
|
@ -337,11 +333,16 @@ export default {
|
|||
next()
|
||||
},
|
||||
methods: {
|
||||
handleGetActivatedTheme() {
|
||||
themeApi.getActivatedTheme().then((response) => {
|
||||
this.activatedTheme = response.data.data
|
||||
})
|
||||
},
|
||||
handleListThemes() {
|
||||
this.themeLoading = true
|
||||
themeApi
|
||||
.listAll()
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.themes = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -351,15 +352,20 @@ export default {
|
|||
})
|
||||
},
|
||||
handleActiveTheme(theme) {
|
||||
themeApi.active(theme.id).finally(() => {
|
||||
this.handleListThemes()
|
||||
})
|
||||
themeApi
|
||||
.active(theme.id)
|
||||
.finally(() => {
|
||||
this.handleListThemes()
|
||||
})
|
||||
.finally(() => {
|
||||
this.handleGetActivatedTheme()
|
||||
})
|
||||
},
|
||||
handleUpdateTheme(themeId) {
|
||||
const hide = this.$message.loading('更新中...', 0)
|
||||
themeApi
|
||||
.update(themeId)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.$message.success('更新成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -370,7 +376,7 @@ export default {
|
|||
handleDeleteTheme(themeId) {
|
||||
themeApi
|
||||
.delete(themeId)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.$message.success('删除成功!')
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -396,18 +402,18 @@ export default {
|
|||
if (!this.fetchingUrl) {
|
||||
this.$notification['error']({
|
||||
message: '提示',
|
||||
description: '远程地址不能为空!'
|
||||
description: '远程地址不能为空!',
|
||||
})
|
||||
return
|
||||
}
|
||||
this.fetchButtonLoading = true
|
||||
themeApi.fetchingBranches(this.fetchingUrl).then(response => {
|
||||
themeApi.fetchingBranches(this.fetchingUrl).then((response) => {
|
||||
this.branches = response.data.data
|
||||
this.fetchBranches = true
|
||||
})
|
||||
themeApi
|
||||
.fetchingReleases(this.fetchingUrl)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.releases = response.data.data
|
||||
})
|
||||
.finally(() => {
|
||||
|
@ -419,7 +425,7 @@ export default {
|
|||
handleBranchFetching() {
|
||||
themeApi
|
||||
.fetchingBranch(this.fetchingUrl, this.branches[this.selectedBranch].branch)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.$message.success('拉取成功')
|
||||
this.uploadThemeVisible = false
|
||||
})
|
||||
|
@ -430,7 +436,7 @@ export default {
|
|||
handleReleaseFetching() {
|
||||
themeApi
|
||||
.fetchingRelease(this.fetchingUrl, this.releases[this.selectedBranch].branch)
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
this.$message.success('拉取成功')
|
||||
this.uploadThemeVisible = false
|
||||
})
|
||||
|
@ -460,7 +466,7 @@ export default {
|
|||
onOk() {
|
||||
_this.handleDeleteTheme(item.id)
|
||||
},
|
||||
onCancel() {}
|
||||
onCancel() {},
|
||||
})
|
||||
},
|
||||
handleConfirmUpdate(item) {
|
||||
|
@ -472,7 +478,7 @@ export default {
|
|||
onOk() {
|
||||
that.handleUpdateTheme(item.id)
|
||||
},
|
||||
onCancel() {}
|
||||
onCancel() {},
|
||||
})
|
||||
},
|
||||
onSelectChange(value) {
|
||||
|
@ -496,7 +502,7 @@ export default {
|
|||
onThemeSettingsClose() {
|
||||
this.themeSettingVisible = false
|
||||
this.selectedTheme = {}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue