增加基础页面的布局控件

This commit is contained in:
DESKTOP-VMMLSOQ\wangzg 2024-02-18 19:15:17 +08:00
parent d467e20dba
commit b3fcdf4c1b
12 changed files with 384 additions and 1 deletions

View File

@ -71,4 +71,10 @@
height: auto !important;
_height: @height;
}
.flex-start(@type: row) {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: @type;
}

161
layouts/manager.vue Normal file
View File

@ -0,0 +1,161 @@
<template>
<a-layout id="components-layout-demo-fixed-sider">
<a-layout-sider :trigger="null" v-model="collapsed" collapsible>
<div class="logo">
管理系统
</div>
<a-menu theme="dark" mode="inline" :default-selected-keys="['4']">
<a-menu-item key="1">
<a-icon type="user" />
<span class="nav-text">nav 1</span>
</a-menu-item>
<a-menu-item key="2">
<a-icon type="video-camera" />
<span class="nav-text">nav 2</span>
</a-menu-item>
<a-menu-item key="3">
<a-icon type="upload" />
<span class="nav-text">nav 3</span>
</a-menu-item>
<a-menu-item key="4">
<a-icon type="bar-chart" />
<span class="nav-text">nav 4</span>
</a-menu-item>
<a-menu-item key="5">
<a-icon type="cloud-o" />
<span class="nav-text">nav 5</span>
</a-menu-item>
<a-menu-item key="6">
<a-icon type="appstore-o" />
<span class="nav-text">nav 6</span>
</a-menu-item>
<a-menu-item key="7">
<a-icon type="team" />
<span class="nav-text">nav 7</span>
</a-menu-item>
<a-menu-item key="8">
<a-icon type="shop" />
<span class="nav-text">nav 8</span>
</a-menu-item>
</a-menu>
</a-layout-sider>
<a-layout >
<a-layout-header
style="background: #fff; padding: 0"
ref="header"
:title="pageTitle"
:breadcrumb="{ props: { routes } }"
>
<div class="header-con">
<a-icon
class="trigger"
:type="collapsed ? 'menu-unfold' : 'menu-fold'"
@click="() => (collapsed = !collapsed)"
/>
<a-icon type="arrow-left" style="font-size: 18px; padding-right: 24px;" />
<a-breadcrumb :routes="routes">
<template slot="itemRender" slot-scope="{ route, params, routes, paths }">
<span v-if="routes.indexOf(route) === routes.length - 1">
{{ route.breadcrumbName }}
</span>
<router-link v-else :to="`/${paths.join('/')}`">
{{ route.breadcrumbName }}
</router-link>
</template>
</a-breadcrumb>
</div>
</a-layout-header>
<a-layout-content :style="contentStyle">
<div :style="containerStyle">
<nuxt/>
</div>
</a-layout-content>
<!-- <a-layout-footer :style="{ textAlign: 'center' }" ref="footer">
Ant Design ©2018 Created by Ant UED
</a-layout-footer>-->
</a-layout>
</a-layout>
</template>
<script>
export default {
name: "manager",
data () {
return {
collapsed: false,
headerHeight: 0,
footerHeight: 0,
routes: [
{
path: 'index',
breadcrumbName: 'First-level Menu',
},
],
pageTitle: '123'
}
},
computed: {
contentStyle () {
return {
margin: '24px 16px 24px',
overflow: 'inherit',
height: `calc(100vh - ${this.headerHeight + this.footerHeight + 48}px)`,
}
},
containerStyle () {
return {
padding: '24px',
background: '#fff',
textAlign: 'center',
height: `100%`,
overflow: 'auto',
}
}
},
mounted () {
this.$nextTick( () => {
if (this.$refs.header) {
this.headerHeight = this.$refs.header.$el.offsetHeight
// this.footerHeight = this.$refs.footer.$el.offsetHeight
}
})
}
}
</script>
<style scoped lang="less">
#components-layout-demo-fixed-sider {
.header-con {
display: flex;
justify-content: flex-start;
align-items: center;
}
.trigger:hover {
color: #1890ff;
}
.trigger {
font-size: 18px;
line-height: 64px;
padding: 0 24px;
cursor: pointer;
transition: color 0.3s;
}
.logo {
width: 80%;
padding: 0 10px;
height: 31px;
background: rgba(255, 255, 255, 0.2);
margin: 16px auto 16px;
line-height: 31px;
text-align: center;
color: #fff;
font-size: 18px;
overflow: inherit;
//
}
}
</style>

View File

@ -17,7 +17,9 @@ export default {
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
],
css: [],
js: []
},
// Global CSS: https://go.nuxtjs.dev/config-css

15
pages/manager/test.vue Normal file
View File

@ -0,0 +1,15 @@
<template>
<div>test</div>
</template>
<script>
import base from "~/templates/base";
export default {
name: "test",
extends: base,
}
</script>
<style scoped>
</style>

13
pages/test/index.vue Normal file
View File

@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "index"
}
</script>
<style scoped>
</style>

4
templates/base.js Normal file
View File

@ -0,0 +1,4 @@
export default {
name: "manager",
layout: 'manager'
}

View File

@ -0,0 +1,53 @@
import {recursionTree} from "./utils";
const mapComponents = {
complete: 'a-auto-complete',
cascader: 'a-cascader',
checkbox: 'a-checkbox-group',
radio: 'a-radio-group',
datePicker: 'a-date-picker',
monthPicker: 'a-month-picker',
rangePicker: 'a-range-picker',
weekPicker: 'a-week-picker',
timePicker: 'a-time-picker',
input: 'a-input',
rate: 'a-rate',
slider: 'a-slider',
switch: 'a-switch',
upload: 'a-upload',
button: 'a-button',
inputNumber: 'a-input-number',
mentions: ['a-mentions', 'a-mentions-option'],
select: ['a-select', 'a-select-option'],
treeSelect: ['a-tree-select', 'a-tree-select-node'],
}
export default function createControlComponent (h, componentType, vueCreateElementProps = {}) {
const component = mapComponents[componentType]
// 没有子组件的情况下直接导出
if (typeof component === "string") {
return h(component, vueCreateElementProps)
}
// 子组件进行判断是否提供子内容
const { props } = vueCreateElementProps
if (!props.children || !Array.isArray(props.children)) {
return null
}
const [ outer, inner ] = component
return h(
outer,
vueCreateElementProps,
recursionTree(props.children, (node) => {
const {label, value, ...otherProps} = node
return h(inner, {
props: {
value: value,
title: label,
...otherProps
}
}, [h(label)])
})
)
}

View File

@ -0,0 +1,20 @@
/**
* 创建具有栅格化的表单项
* @param h
* @param formItemProps
* @param rowConfig
* @param colConfig
* @param children
* @returns {*}
*/
export default function createFormComponent(h, formItemProps, rowConfig, colConfig, children = []) {
if (rowConfig) {
return h('a-row', rowConfig, [
h('a-col', colConfig, [
h('a-form-item', formItemProps, children)
])
])
}
return h('a-form-item', formItemProps, children)
}

View File

@ -0,0 +1,67 @@
import createControlComponent from "./createControlComponent";
import createFormComponent from "./createFormComponent";
export default {
name: 'dynamicForm',
props: {
/**
* 表单配置项
*/
formOption: {
type: Object,
default: () => ({})
},
/**
* 控件列表配置项
*/
options: {
type: Array,
default: () => []
},
/**
* 表单全局列配置
*/
colOption: {
type: Object,
default: () => ({})
},
/**
* 表单全局行配置
*/
rowOption: {
type: Object,
default: null
}
},
methods: {
/**
* 校验结果正确触发回调
* @param cb
*/
validate (cb) {},
/**
* 重置表单内容
*/
reset () {}
},
render (h) {
return h(
'a-form-model',
this.formOption,
this.options.map(({ type, formItemOption, elementOption }) => {
return createFormComponent(
h, formItemOption,
this.rowOption,
this.colOption,
[createControlComponent(h, type, elementOption)]
)
})
)
}
}

View File

@ -0,0 +1,14 @@
/**
* 递归处理树节点
* @param treeNodes
* @param cb
* @returns {*[]}
*/
export const recursionTree = function (treeNodes, cb) {
return ([].concat(treeNodes)).map(node => {
if (node.children && node.children.length > 0) {
node.children = recursionTree(node.children, cb)
}
return cb(node)
})
}

5
templates/form.js Normal file
View File

@ -0,0 +1,5 @@
import base from './base'
export default {
name: "form",
extends: base
}

23
templates/table.vue Normal file
View File

@ -0,0 +1,23 @@
<template>
<a-layout>
</a-layout>
</template>
<script>
import base from './base'
export default {
name: 'table',
extends: base,
data () {
return {
dataSource: [],
loading: false,
}
}
}
</script>