vue版本上线

This commit is contained in:
季圣华
2021-04-07 23:53:57 +08:00
parent 76a0033a4e
commit f4ef5aa067
803 changed files with 171959 additions and 27 deletions

View File

@@ -0,0 +1,71 @@
<template>
<a-menu :style="style" class="contextmenu" v-show="visible" @click="handleClick" :selectedKeys="selectedKeys">
<a-menu-item :key="item.key" v-for="item in itemList">
<a-icon role="menuitemicon" v-if="item.icon" :type="item.icon" />{{ item.text }}
</a-menu-item>
</a-menu>
</template>
<script>
export default {
name: 'Contextmenu',
props: {
visible: {
type: Boolean,
required: false,
default: false
},
itemList: {
type: Array,
required: true,
default: () => []
}
},
data () {
return {
left: 0,
top: 0,
target: null,
selectedKeys: []
}
},
computed: {
style () {
return {
left: this.left + 'px',
top: this.top + 'px'
}
}
},
created () {
window.addEventListener('mousedown', e => this.closeMenu(e))
window.addEventListener('contextmenu', e => this.setPosition(e))
},
methods: {
closeMenu (e) {
if (this.visible === true && ['menuitemicon', 'menuitem'].indexOf(e.target.getAttribute('role')) < 0) {
this.$emit('update:visible', false)
}
},
setPosition (e) {
this.left = e.clientX
this.top = e.clientY
this.target = e.target
},
handleClick ({key}) {
this.$emit('select', key, this.target)
this.$emit('update:visible', false)
}
}
}
</script>
<style lang="less" scoped>
.contextmenu{
position: fixed;
z-index: 1;
border: 1px solid #9e9e9e;
border-radius: 4px;
box-shadow: 2px 2px 10px #aaaaaa !important;
}
</style>

View File

@@ -0,0 +1,177 @@
<template>
<a-layout-sider
:class="['sider', isDesktop() ? null : 'shadow', theme, fixSiderbar ? 'ant-fixed-sidemenu' : null ]"
width="200px"
:collapsible="collapsible"
v-model="collapsed"
:trigger="null">
<logo />
<s-menu
:collapsed="collapsed"
:menu="menus"
:theme="theme"
@select="onSelect"
:mode="mode"
:style="smenuStyle">
</s-menu>
</a-layout-sider>
</template>
<script>
import ALayoutSider from "ant-design-vue/es/layout/Sider"
import Logo from '../tools/Logo'
import SMenu from './index'
import { mixin, mixinDevice } from '@/utils/mixin.js'
export default {
name: "SideMenu",
components: { ALayoutSider, Logo, SMenu },
mixins: [mixin, mixinDevice],
props: {
mode: {
type: String,
required: false,
default: 'inline'
},
theme: {
type: String,
required: false,
default: 'dark'
},
collapsible: {
type: Boolean,
required: false,
default: false
},
collapsed: {
type: Boolean,
required: false,
default: false
},
menus: {
type: Array,
required: true
}
},
computed:{
smenuStyle() {
let style = { 'padding': '0' }
if (this.fixSiderbar) {
style['height'] = 'calc(100% - 59px)'
style['overflow'] = 'auto'
style['overflow-x'] = 'hidden'
}
return style
}
},
methods: {
onSelect (obj) {
this.$emit('menuSelect', obj)
}
}
}
</script>
<style lang="less" scoped>
/* update_begin author:sunjianlei date:20190509 for: 修改侧边导航栏滚动条的样式 */
.sider {
@scrollBarSize: 10px;
ul.ant-menu {
/* 定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/
&::-webkit-scrollbar {
width: @scrollBarSize;
height: @scrollBarSize;
background-color: transparent;
display: none;
}
& .-o-scrollbar {
display: none;
}
/* 兼容IE */
-ms-overflow-style: none;
-ms-scroll-chaining: chained;
-ms-content-zooming: zoom;
-ms-scroll-rails: none;
-ms-content-zoom-limit-min: 100%;
-ms-content-zoom-limit-max: 500%;
-ms-scroll-snap-type: proximity;
-ms-scroll-snap-points-x: snapList(100%, 200%, 300%, 400%, 500%);
/* 定义滚动条轨道 */
&::-webkit-scrollbar-track {
background-color: transparent;
}
/* 定义滑块 */
&::-webkit-scrollbar-thumb {
border-radius: @scrollBarSize;
background-color: #eee;
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1);
&:hover {
background-color: #dddddd;
}
&:active {
background-color: #bbbbbb;
}
}
}
/** 暗色系滚动条样式 */
&.dark ul.ant-menu {
&::-webkit-scrollbar-thumb {
background-color: #666666;
&:hover {
background-color: #808080;
}
&:active {
background-color: #999999;
}
}
}
}
/* update_end author:sunjianlei date:20190509 for: 修改侧边导航栏滚动条的样式 */
</style>
<!-- update_begin author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
<style lang="less">
.ant-menu.ant-menu-root {
& > .ant-menu-item:first-child {
background-color: transparent;
& > a, & > a:hover {
color: rgba(0, 0, 0, 0.65);
}
&.ant-menu-item-selected {
& > a, & > a:hover {
color: @primary-color;
}
}
}
&.ant-menu-dark > .ant-menu-item:first-child {
& > a, & > a:hover {
color: rgba(255, 255, 255, 0.65);
}
&.ant-menu-item-selected {
& > a, & > a:hover {
color: rgba(255, 255, 255, 1);
}
}
}
}
</style>
<!-- update_end author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->

View File

@@ -0,0 +1,188 @@
import Menu from 'ant-design-vue/es/menu'
import Icon from 'ant-design-vue/es/icon'
const { Item, SubMenu } = Menu
export default {
name: 'SMenu',
props: {
menu: {
type: Array,
required: true
},
theme: {
type: String,
required: false,
default: 'dark'
},
mode: {
type: String,
required: false,
default: 'inline'
},
collapsed: {
type: Boolean,
required: false,
default: false
}
},
data () {
return {
openKeys: [],
selectedKeys: [],
cachedOpenKeys: []
}
},
computed: {
rootSubmenuKeys: vm => {
const keys = []
vm.menu.forEach(item => keys.push(item.path))
return keys
}
},
mounted () {
this.updateMenu()
},
watch: {
collapsed (val) {
if (val) {
this.cachedOpenKeys = this.openKeys.concat()
this.openKeys = []
} else {
this.openKeys = this.cachedOpenKeys
}
},
$route: function () {
this.updateMenu()
}
},
methods: {
// select menu item
onOpenChange (openKeys) {
// 在水平模式下时执行,并且不再执行后续
if (this.mode === 'horizontal') {
this.openKeys = openKeys
return
}
// 非水平模式时
const latestOpenKey = openKeys.find(key => !this.openKeys.includes(key))
if (!this.rootSubmenuKeys.includes(latestOpenKey)) {
this.openKeys = openKeys
} else {
this.openKeys = latestOpenKey ? [latestOpenKey] : []
}
},
updateMenu () {
const routes = this.$route.matched.concat()
const { hidden } = this.$route.meta
if (routes.length >= 3 && hidden) {
routes.pop()
this.selectedKeys = [routes[routes.length - 1].path]
} else {
this.selectedKeys = [routes.pop().path]
}
const openKeys = []
if (this.mode === 'inline') {
routes.forEach(item => {
openKeys.push(item.path)
})
}
//update-begin-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
if(!this.selectedKeys|| this.selectedKeys[0].indexOf(":")<0){
this.collapsed ? (this.cachedOpenKeys = openKeys) : (this.openKeys = openKeys)
}
//update-end-author:taoyan date:20190510 for:online表单菜单点击展开的一级目录不对
},
// render
renderItem (menu) {
if (!menu.hidden) {
return menu.children && !menu.alwaysShow ? this.renderSubMenu(menu) : this.renderMenuItem(menu)
}
return null
},
renderMenuItem (menu) {
// const target = menu.meta.target || null
// const tag = target && 'a' || 'router-link'
let props = { to: { name: menu.name } }
if(menu.route && menu.route === '0'){
props = { to: { path: menu.path } }
}
const attrs = { href: menu.url, target: menu.text }
if (menu.children) {
// 把有子菜单的 并且 父菜单是要隐藏子菜单的
// 都给子菜单增加一个 hidden 属性
// 用来给刷新页面时, selectedKeys 做控制用
menu.children.forEach(item => {
item.meta = Object.assign(item.meta, { hidden: true })
})
}
return (
<Item {...{ key: menu.url }}>
<tag {...{ props, attrs }}>
{this.renderIcon(menu.icon)}
<span>{menu.text}</span>
</tag>
</Item>
)
},
renderSubMenu (menu) {
const itemArr = []
if (!menu.alwaysShow) {
menu.children.forEach(item => itemArr.push(this.renderItem(item)))
}
return (
<SubMenu {...{ key: menu.url }}>
<span slot="title">
{this.renderIcon(menu.icon)}
<span>{menu.text}</span>
</span>
{itemArr}
</SubMenu>
)
},
renderIcon (icon) {
if (icon === 'none' || icon === undefined) {
return null
}
const props = {}
typeof (icon) === 'object' ? props.component = icon : props.type = icon
return (
<Icon {... { props } }/>
)
}
},
render () {
const { mode, theme, menu } = this
const props = {
mode: mode,
theme: theme,
openKeys: this.openKeys
}
const on = {
select: obj => {
this.selectedKeys = obj.selectedKeys
this.$emit('select', obj)
},
openChange: this.onOpenChange
}
const menuTree = menu.map(item => {
if (item.hidden) {
return null
}
return this.renderItem(item)
})
// {...{ props, on: on }}
return (
<Menu vModel={this.selectedKeys} {...{ props, on: on }}>
{menuTree}
</Menu>
)
}
}