parent
d375bf5619
commit
2e835ae853
File diff suppressed because it is too large
Load Diff
@ -1,48 +1,48 @@ |
|||||||
<template> |
<template> |
||||||
<div |
<div |
||||||
class="el-select-dropdown el-popper" |
class="el-select-dropdown el-popper" |
||||||
:class="[{ 'is-multiple': $parent.multiple }, popperClass]" |
:class="[{ 'is-multiple': $parent.multiple }, popperClass]" |
||||||
:style="{ minWidth }" |
:style="{ minWidth }" |
||||||
> |
> |
||||||
<slot/> |
<slot/> |
||||||
</div> |
</div> |
||||||
</template> |
</template> |
||||||
|
|
||||||
<script type="text/babel"> |
<script type="text/babel"> |
||||||
import Popper from '@ele/mixins/vue-popper' |
import Popper from '@ele/mixins/vue-popper' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'ElSelectDropdown', |
name: 'ElSelectDropdown', |
||||||
|
|
||||||
componentName: 'ElSelectDropdown', |
componentName: 'ElSelectDropdown', |
||||||
|
|
||||||
mixins: [Popper], |
mixins: [Popper], |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
minWidth: '' |
minWidth: '' |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
computed: { |
computed: { |
||||||
popperClass() { |
popperClass() { |
||||||
return this.$parent.popperClass |
return this.$parent.popperClass |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
watch: { |
watch: { |
||||||
'$parent.inputWidth'() { |
'$parent.inputWidth'() { |
||||||
this.minWidth = this.$parent.$el.getBoundingClientRect().width + 'px' |
this.minWidth = this.$parent.$el.getBoundingClientRect().width + 'px' |
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
mounted() { |
|
||||||
this.referenceElm = this.$parent.$refs.reference.$el |
|
||||||
this.$parent.popperElm = this.popperElm = this.$el |
|
||||||
this.$on('updatePopper', () => { |
|
||||||
this.$parent.visible && this.updatePopper() |
|
||||||
}) |
|
||||||
this.$on('destroyPopper', this.destroyPopper) |
|
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
this.referenceElm = this.$parent.$refs.reference.$el |
||||||
|
this.$parent.popperElm = this.popperElm = this.$el |
||||||
|
this.$on('updatePopper', () => { |
||||||
|
this.$parent.visible && this.updatePopper() |
||||||
|
}) |
||||||
|
this.$on('destroyPopper', this.destroyPopper) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,25 +1,25 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "AbstractFormItem", |
name: "AbstractFormItem", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: {full: Boolean, dense: Boolean, label: String, prop: String}, |
props: {full: Boolean, dense: Boolean, label: String, prop: String}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {full, dense, label, prop} = context.props |
const {full, dense, label, prop} = context.props |
||||||
let attrs = {xs: 24, sm: 12, lg: 8} |
let attrs = {xs: 24, sm: 12, lg: 8} |
||||||
|
|
||||||
if (full) attrs = {span: 24} |
if (full) attrs = {span: 24} |
||||||
else if (dense) attrs.lg = 12 |
else if (dense) attrs.lg = 12 |
||||||
|
|
||||||
return ( |
return ( |
||||||
<el-col {...{attrs}}> |
<el-col {...{attrs}}> |
||||||
<el-form-item label={label} prop={prop}> |
<el-form-item label={label} prop={prop}> |
||||||
{context.children} |
{context.children} |
||||||
</el-form-item> |
</el-form-item> |
||||||
</el-col> |
</el-col> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,23 +1,23 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "AbstractForm", |
name: "AbstractForm", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {data, children} = context |
const {data, children} = context |
||||||
return ( |
return ( |
||||||
<el-form |
<el-form |
||||||
ref="form" |
ref="form" |
||||||
label-position="right" |
label-position="right" |
||||||
label-width="100px" |
label-width="100px" |
||||||
size="small" |
size="small" |
||||||
status-icon |
status-icon |
||||||
{...data} |
{...data} |
||||||
> |
> |
||||||
<el-row>{children}</el-row> |
<el-row>{children}</el-row> |
||||||
</el-form> |
</el-form> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,36 +1,36 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import Empty from "@/components/Empty" |
import Empty from "@/components/Empty" |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "AbstractTable", |
name: "AbstractTable", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {data, children, scopedSlots} = context |
const {data, children, scopedSlots} = context |
||||||
|
|
||||||
if (!scopedSlots.empty) { |
if (!scopedSlots.empty) { |
||||||
scopedSlots.empty = () => <Empty/> |
scopedSlots.empty = () => <Empty/> |
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<el-table |
|
||||||
ref="table" |
|
||||||
current-row-key="id" |
|
||||||
row-key="id" |
|
||||||
highlight-current-row |
|
||||||
{...data} |
|
||||||
> |
|
||||||
{children} |
|
||||||
{ |
|
||||||
Object |
|
||||||
.entries(scopedSlots) |
|
||||||
.map(([name, slot]) => ( |
|
||||||
name !== 'default' && <slot slot={name}>{slot()}</slot> |
|
||||||
)) |
|
||||||
} |
|
||||||
</el-table> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<el-table |
||||||
|
ref="table" |
||||||
|
current-row-key="id" |
||||||
|
row-key="id" |
||||||
|
highlight-current-row |
||||||
|
{...data} |
||||||
|
> |
||||||
|
{children} |
||||||
|
{ |
||||||
|
Object |
||||||
|
.entries(scopedSlots) |
||||||
|
.map(([name, slot]) => ( |
||||||
|
name !== 'default' && <slot slot={name}>{slot()}</slot> |
||||||
|
)) |
||||||
|
} |
||||||
|
</el-table> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,11 +1,11 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "ContextMenuItem", |
name: "ContextMenuItem", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
return <li class="contextmenu-item" {...context.data}>{context.children}</li> |
return <li class="contextmenu-item" {...context.data}>{context.children}</li> |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,51 +1,51 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: 'DefaultEmptyImage', |
name: 'DefaultEmptyImage', |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
render() { |
render() { |
||||||
return ( |
return ( |
||||||
<svg width="184" height="152" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg"> |
<svg width="184" height="152" viewBox="0 0 184 152" xmlns="http://www.w3.org/2000/svg"> |
||||||
<g fill="none" fillRule="evenodd"> |
<g fill="none" fillRule="evenodd"> |
||||||
<g transform="translate(24 31.67)"> |
<g transform="translate(24 31.67)"> |
||||||
<ellipse |
<ellipse |
||||||
fillOpacity=".8" |
fillOpacity=".8" |
||||||
fill="#F5F5F7" |
fill="#F5F5F7" |
||||||
cx="67.797" |
cx="67.797" |
||||||
cy="106.89" |
cy="106.89" |
||||||
rx="67.797" |
rx="67.797" |
||||||
ry="12.668" |
ry="12.668" |
||||||
/> |
/> |
||||||
<path |
<path |
||||||
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z" |
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z" |
||||||
fill="#AEB8C2" |
fill="#AEB8C2" |
||||||
/> |
/> |
||||||
<path |
<path |
||||||
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z" |
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z" |
||||||
fill="url(#linearGradient-1)" |
fill="url(#linearGradient-1)" |
||||||
transform="translate(13.56)" |
transform="translate(13.56)" |
||||||
/> |
/> |
||||||
<path |
<path |
||||||
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z" |
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z" |
||||||
fill="#F5F5F7" |
fill="#F5F5F7" |
||||||
/> |
/> |
||||||
<path |
|
||||||
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z" |
|
||||||
fill="#DCE0E6" |
|
||||||
/> |
|
||||||
</g> |
|
||||||
<path |
<path |
||||||
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z" |
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z" |
||||||
fill="#DCE0E6" |
fill="#DCE0E6" |
||||||
/> |
/> |
||||||
<g transform="translate(149.65 15.383)" fill="#FFF"> |
|
||||||
<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"/> |
|
||||||
<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"/> |
|
||||||
</g> |
|
||||||
</g> |
</g> |
||||||
</svg> |
<path |
||||||
) |
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z" |
||||||
} |
fill="#DCE0E6" |
||||||
|
/> |
||||||
|
<g transform="translate(149.65 15.383)" fill="#FFF"> |
||||||
|
<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"/> |
||||||
|
<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"/> |
||||||
|
</g> |
||||||
|
</g> |
||||||
|
</svg> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,38 +1,38 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import DefaultEmptyImage from "./DefaultEmptyImage" |
import DefaultEmptyImage from "./DefaultEmptyImage" |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "AEmpty", |
name: "AEmpty", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
description: String, |
description: String, |
||||||
image: [String, Object], |
image: [String, Object], |
||||||
imageStyle: [String, Object] |
imageStyle: [String, Object] |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {description = '暂无数据', image, imageStyle} = context.props |
const {description = '暂无数据', image, imageStyle} = context.props |
||||||
const prefixCls = 'ant-empty' |
const prefixCls = 'ant-empty' |
||||||
const cls = {[prefixCls]: true} |
const cls = {[prefixCls]: true} |
||||||
|
|
||||||
let imageNode = null |
let imageNode = null |
||||||
if (typeof image === 'string') { |
if (typeof image === 'string') { |
||||||
imageNode = <img alt={description} src={image}/> |
imageNode = <img alt={description} src={image}/> |
||||||
} |
|
||||||
else { |
|
||||||
imageNode = <DefaultEmptyImage/> |
|
||||||
} |
|
||||||
return ( |
|
||||||
<div class={cls} {...{on: context.listeners}}> |
|
||||||
<div class={`${prefixCls}-image`} style={imageStyle}>{imageNode}</div> |
|
||||||
{description && <p class={`${prefixCls}-description`}>{description}</p>} |
|
||||||
{context.children && <div class={`${prefixCls}-footer`}>{context.children}</div>} |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
else { |
||||||
|
imageNode = <DefaultEmptyImage/> |
||||||
|
} |
||||||
|
return ( |
||||||
|
<div class={cls} {...{on: context.listeners}}> |
||||||
|
<div class={`${prefixCls}-image`} style={imageStyle}>{imageNode}</div> |
||||||
|
{description && <p class={`${prefixCls}-description`}>{description}</p>} |
||||||
|
{context.children && <div class={`${prefixCls}-footer`}>{context.children}</div>} |
||||||
|
</div> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss" src="./style.scss"></style> |
<style lang="scss" src="./style.scss"></style> |
||||||
|
|||||||
@ -1,54 +1,54 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import LoadingMask from '@/components/LoadingMask' |
import LoadingMask from '@/components/LoadingMask' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "FormDialog", |
name: "FormDialog", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
value: Boolean, |
value: Boolean, |
||||||
title: String, |
title: String, |
||||||
loading: {type: Boolean, default: true}, |
loading: {type: Boolean, default: true}, |
||||||
top: {type: String, default: '50px'}, |
top: {type: String, default: '50px'}, |
||||||
width: {type: String, default: '30%'} |
width: {type: String, default: '30%'} |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {value, title, loading, top, width} = context.props |
const {value, title, loading, top, width} = context.props |
||||||
const l = context.listeners |
const l = context.listeners |
||||||
|
|
||||||
function onClose() { |
function onClose() { |
||||||
l.input && l.input(false) |
l.input && l.input(false) |
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<el-dialog |
|
||||||
v-drag-dialog |
|
||||||
visible={value} |
|
||||||
custom-class="form-dialog" |
|
||||||
top={top} |
|
||||||
width={width} |
|
||||||
on-close={onClose} |
|
||||||
{...context.data} |
|
||||||
> |
|
||||||
<slot slot="title" name="title">{title}</slot> |
|
||||||
|
|
||||||
<div class="form-dialog-container"> |
|
||||||
<LoadingMask show={loading}/> |
|
||||||
<el-scrollbar> |
|
||||||
<div class="form-dialog-body"> |
|
||||||
{context.children} |
|
||||||
</div> |
|
||||||
<div style="margin-bottom: 17px"/> |
|
||||||
</el-scrollbar> |
|
||||||
</div> |
|
||||||
|
|
||||||
<slot slot="footer" name="footer"/> |
|
||||||
</el-dialog> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<el-dialog |
||||||
|
v-drag-dialog |
||||||
|
visible={value} |
||||||
|
custom-class="form-dialog" |
||||||
|
top={top} |
||||||
|
width={width} |
||||||
|
on-close={onClose} |
||||||
|
{...context.data} |
||||||
|
> |
||||||
|
<slot slot="title" name="title">{title}</slot> |
||||||
|
|
||||||
|
<div class="form-dialog-container"> |
||||||
|
<LoadingMask show={loading}/> |
||||||
|
<el-scrollbar> |
||||||
|
<div class="form-dialog-body"> |
||||||
|
{context.children} |
||||||
|
</div> |
||||||
|
<div style="margin-bottom: 17px"/> |
||||||
|
</el-scrollbar> |
||||||
|
</div> |
||||||
|
|
||||||
|
<slot slot="footer" name="footer"/> |
||||||
|
</el-dialog> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss" src="./style.scss"></style> |
<style lang="scss" src="./style.scss"></style> |
||||||
|
|||||||
@ -1,23 +1,23 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
//从muse-ui处搬运,https://muse-ui.org/#/zh-CN/progress |
//从muse-ui处搬运,https://muse-ui.org/#/zh-CN/progress |
||||||
export default { |
export default { |
||||||
name: "LinerProgress", |
name: "LinerProgress", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: {show: Boolean}, |
props: {show: Boolean}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
if (context.props.show) { |
if (context.props.show) { |
||||||
return ( |
return ( |
||||||
<div class="liner-progress"> |
<div class="liner-progress"> |
||||||
<div class="liner-progress-background"/> |
<div class="liner-progress-background"/> |
||||||
<div class="linear-progress-indeterminate"/> |
<div class="linear-progress-indeterminate"/> |
||||||
</div> |
</div> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss" src="./style.scss"></style> |
<style lang="scss" src="./style.scss"></style> |
||||||
|
|||||||
@ -1,24 +1,24 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "LoadingMask", |
name: "LoadingMask", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: {show: Boolean}, |
props: {show: Boolean}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
if (context.props.show) { |
if (context.props.show) { |
||||||
return ( |
return ( |
||||||
<div class="el-loading-mask"> |
<div class="el-loading-mask"> |
||||||
<div class="el-loading-spinner"> |
<div class="el-loading-spinner"> |
||||||
<svg viewBox="25 25 50 50" class="circular"> |
<svg viewBox="25 25 50 50" class="circular"> |
||||||
<circle cx="50" cy="50" r="20" fill="none" class="path"/> |
<circle cx="50" cy="50" r="20" fill="none" class="path"/> |
||||||
</svg> |
</svg> |
||||||
<p>加载中...</p> |
<p>加载中...</p> |
||||||
</div> |
|
||||||
</div> |
</div> |
||||||
) |
</div> |
||||||
} |
) |
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,84 +1,84 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import {store, init} from '../store' |
import {store, init} from '../store' |
||||||
import FormDialog from "@/components/FormDialog" |
import FormDialog from "@/components/FormDialog" |
||||||
import {createLimitTree, getNodeId} from "@/utils/tree" |
import {createLimitTree, getNodeId} from "@/utils/tree" |
||||||
|
|
||||||
export default { |
export default { |
||||||
components: {FormDialog}, |
components: {FormDialog}, |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
loading: false, |
loading: false, |
||||||
visible: false, |
visible: false, |
||||||
handler: null, |
handler: null, |
||||||
limitTree: [], |
limitTree: [], |
||||||
getChildrenOnSelect: false, |
getChildrenOnSelect: false, |
||||||
limit: false, |
limit: false, |
||||||
limitApi: null |
limitApi: null |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
computed: { |
|
||||||
regionTree() { |
|
||||||
return store.data |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
methods: { |
computed: { |
||||||
closeDialog() { |
regionTree() { |
||||||
this.visible = false |
return store.data |
||||||
}, |
} |
||||||
|
}, |
||||||
|
|
||||||
nodeClick(obj) { |
methods: { |
||||||
const payload = [obj] |
closeDialog() { |
||||||
|
this.visible = false |
||||||
|
}, |
||||||
|
|
||||||
if (this.getChildrenOnSelect) { |
nodeClick(obj) { |
||||||
const ids = getNodeId(obj.children) |
const payload = [obj] |
||||||
ids.unshift(obj.id) |
|
||||||
payload.push(ids) |
|
||||||
} |
|
||||||
|
|
||||||
this.handler(payload) |
if (this.getChildrenOnSelect) { |
||||||
|
const ids = getNodeId(obj.children) |
||||||
|
ids.unshift(obj.id) |
||||||
|
payload.push(ids) |
||||||
|
} |
||||||
|
|
||||||
this.closeDialog() |
this.handler(payload) |
||||||
}, |
|
||||||
|
|
||||||
init() { |
this.closeDialog() |
||||||
this.loading = true |
|
||||||
const hasInit = this.regionTree.length > 0 |
|
||||||
const promise = () => hasInit ? Promise.resolve() : init() |
|
||||||
return promise() |
|
||||||
.then(() => this.limit ? this.limitApi() : Promise.resolve()) |
|
||||||
.then(data => data && (this.limitTree = createLimitTree(this.regionTree, data))) |
|
||||||
.finally(() => this.loading = false) |
|
||||||
} |
|
||||||
}, |
}, |
||||||
|
|
||||||
render() { |
init() { |
||||||
return ( |
this.loading = true |
||||||
<form-dialog |
const hasInit = this.regionTree.length > 0 |
||||||
v-model={this.visible} |
const promise = () => hasInit ? Promise.resolve() : init() |
||||||
directives={[{name: 'drag-dialog'}]} |
return promise() |
||||||
class="tree-dialog" |
.then(() => this.limit ? this.limitApi() : Promise.resolve()) |
||||||
title="选择行政区域" |
.then(data => data && (this.limitTree = createLimitTree(this.regionTree, data))) |
||||||
loading={this.loading} |
.finally(() => this.loading = false) |
||||||
appendToBody={true} |
} |
||||||
v-on:close={this.closeDialog} |
}, |
||||||
|
|
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<form-dialog |
||||||
|
v-model={this.visible} |
||||||
|
directives={[{name: 'drag-dialog'}]} |
||||||
|
class="tree-dialog" |
||||||
|
title="选择行政区域" |
||||||
|
loading={this.loading} |
||||||
|
appendToBody={true} |
||||||
|
v-on:close={this.closeDialog} |
||||||
|
> |
||||||
|
<el-tree |
||||||
|
data={this.limit ? this.limitTree : this.regionTree} |
||||||
|
expand-on-click-node={false} |
||||||
|
node-key="id" |
||||||
|
v-on:node-click={this.nodeClick} |
||||||
> |
> |
||||||
<el-tree |
{({data}) => ( |
||||||
data={this.limit ? this.limitTree : this.regionTree} |
<span className="el-tree-node__label"> |
||||||
expand-on-click-node={false} |
|
||||||
node-key="id" |
|
||||||
v-on:node-click={this.nodeClick} |
|
||||||
> |
|
||||||
{({data}) => ( |
|
||||||
<span className="el-tree-node__label"> |
|
||||||
{this.limit ? data.name + `(${data.value})` : data.name} |
{this.limit ? data.name + `(${data.value})` : data.name} |
||||||
</span> |
</span> |
||||||
)} |
)} |
||||||
</el-tree> |
</el-tree> |
||||||
</form-dialog> |
</form-dialog> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,79 +1,79 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import Vue from 'vue' |
import Vue from 'vue' |
||||||
import TreeDialog from "./TreeDialog" |
import TreeDialog from "./TreeDialog" |
||||||
import common from '../mixin' |
import common from '../mixin' |
||||||
|
|
||||||
const TreeDialogConstructor = Vue.extend(TreeDialog) |
const TreeDialogConstructor = Vue.extend(TreeDialog) |
||||||
|
|
||||||
let limit, full |
let limit, full |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "RegionTreeSelector", |
name: "RegionTreeSelector", |
||||||
|
|
||||||
mixins: [common], |
mixins: [common], |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
dialogVisible: false, |
dialogVisible: false, |
||||||
limitTree: [] |
limitTree: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
openDialog() { |
||||||
|
if (this.limit) { |
||||||
|
this.initLimit() |
||||||
|
return limit.visible = true |
||||||
|
} |
||||||
|
else { |
||||||
|
!full && this.initFull() |
||||||
|
full.visible = true |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
methods: { |
handler(payload) { |
||||||
openDialog() { |
this.$emit('select', ...payload) |
||||||
if (this.limit) { |
}, |
||||||
this.initLimit() |
|
||||||
return limit.visible = true |
|
||||||
} |
|
||||||
else { |
|
||||||
!full && this.initFull() |
|
||||||
full.visible = true |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
handler(payload) { |
|
||||||
this.$emit('select', ...payload) |
|
||||||
}, |
|
||||||
|
|
||||||
initLimit() { |
|
||||||
if (limit) { |
|
||||||
limit.getChildrenOnSelect = this.getChildrenOnSelect |
|
||||||
limit.limit = this.limit |
|
||||||
limit.limitApi = this.limitApi |
|
||||||
return limit.init() |
|
||||||
} |
|
||||||
|
|
||||||
const data = {...this.$props, handler: this.handler} |
|
||||||
limit = new TreeDialogConstructor({data}).$mount() |
|
||||||
document.body.appendChild(limit.$el) |
|
||||||
|
|
||||||
|
initLimit() { |
||||||
|
if (limit) { |
||||||
|
limit.getChildrenOnSelect = this.getChildrenOnSelect |
||||||
|
limit.limit = this.limit |
||||||
|
limit.limitApi = this.limitApi |
||||||
return limit.init() |
return limit.init() |
||||||
}, |
} |
||||||
|
|
||||||
initFull() { |
const data = {...this.$props, handler: this.handler} |
||||||
if (full) { |
limit = new TreeDialogConstructor({data}).$mount() |
||||||
return full.getChildrenOnSelect = this.getChildrenOnSelect |
document.body.appendChild(limit.$el) |
||||||
} |
|
||||||
|
|
||||||
const data = {getChildrenOnSelect: this.getChildrenOnSelect, handler: this.handler} |
return limit.init() |
||||||
full = new TreeDialogConstructor({data}).$mount() |
}, |
||||||
document.body.appendChild(full.$el) |
|
||||||
|
|
||||||
return full.init() |
initFull() { |
||||||
|
if (full) { |
||||||
|
return full.getChildrenOnSelect = this.getChildrenOnSelect |
||||||
} |
} |
||||||
}, |
|
||||||
|
|
||||||
render() { |
const data = {getChildrenOnSelect: this.getChildrenOnSelect, handler: this.handler} |
||||||
return ( |
full = new TreeDialogConstructor({data}).$mount() |
||||||
<el-input |
document.body.appendChild(full.$el) |
||||||
value={this.value} |
|
||||||
readonly={this.readonly} |
return full.init() |
||||||
size={this.size} |
|
||||||
clearable |
|
||||||
v-on:clear={() => this.$emit('clear')} |
|
||||||
v-on:focus={this.openDialog} |
|
||||||
/> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<el-input |
||||||
|
value={this.value} |
||||||
|
readonly={this.readonly} |
||||||
|
size={this.size} |
||||||
|
clearable |
||||||
|
v-on:clear={() => this.$emit('clear')} |
||||||
|
v-on:focus={this.openDialog} |
||||||
|
/> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,18 +1,18 @@ |
|||||||
<script> |
<script> |
||||||
const Tree = () => import('./Tree').then(_ => _.default) |
const Tree = () => import('./Tree').then(_ => _.default) |
||||||
const Tab = () => import('./Tab').then(_ => _.default) |
const Tab = () => import('./Tab').then(_ => _.default) |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "RegionSelector", |
name: "RegionSelector", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
type: {type: String, default: 'tab', validator: v => ['tree', 'tab'].includes(v)} |
type: {type: String, default: 'tab', validator: v => ['tree', 'tab'].includes(v)} |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
return h(context.props.type === 'tree' ? Tree : Tab, context.data) |
return h(context.props.type === 'tree' ? Tree : Tab, context.data) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,24 +1,24 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "SearchFormItem", |
name: "SearchFormItem", |
||||||
|
|
||||||
inject: { |
inject: { |
||||||
searchForm: { |
searchForm: { |
||||||
default: () => ({width: 'auto'}) |
default: () => ({width: 'auto'}) |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
props: {label: String}, |
props: {label: String}, |
||||||
|
|
||||||
render() { |
render() { |
||||||
const {width} = this.searchForm |
const {width} = this.searchForm |
||||||
return ( |
return ( |
||||||
<el-col style={{width}} span={100}> |
<el-col style={{width}} span={100}> |
||||||
<el-form-item label={this.label}> |
<el-form-item label={this.label}> |
||||||
{this.$slots.default} |
{this.$slots.default} |
||||||
</el-form-item> |
</el-form-item> |
||||||
</el-col> |
</el-col> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,124 +1,124 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import {getElementInnerWidth} from '@/utils/browser' |
import {getElementInnerWidth} from '@/utils/browser' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "SearchForm", |
name: "SearchForm", |
||||||
|
|
||||||
provide() { |
provide() { |
||||||
return { |
return { |
||||||
searchForm: this |
searchForm: this |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
props: { |
props: { |
||||||
labelWidth: {type: String, default: '120px'}, |
labelWidth: {type: String, default: '120px'}, |
||||||
xs: {type: Number, default: 1},// <768px |
xs: {type: Number, default: 1},// <768px |
||||||
sm: {type: Number, default: 2},// >=768px |
sm: {type: Number, default: 2},// >=768px |
||||||
md: {type: Number, default: 3}, // >=998px |
md: {type: Number, default: 3}, // >=998px |
||||||
lg: {type: Number, default: 4} // >=1200px |
lg: {type: Number, default: 4} // >=1200px |
||||||
}, |
}, |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
showCollapse: false, |
showCollapse: false, |
||||||
collapse: true, |
collapse: true, |
||||||
num: 0, |
num: 0, |
||||||
width: 'auto' |
width: 'auto' |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
methods: { |
methods: { |
||||||
handleCollapse() { |
handleCollapse() { |
||||||
this.collapse = !this.collapse |
this.collapse = !this.collapse |
||||||
}, |
|
||||||
|
|
||||||
getElementNumInRow() { |
|
||||||
const vw = getElementInnerWidth(this.$el.parentNode) |
|
||||||
|
|
||||||
if (vw < 768) return this.xs |
|
||||||
else if (vw < 998) return this.sm |
|
||||||
else if (vw < 1200) return this.md |
|
||||||
return this.lg |
|
||||||
}, |
|
||||||
|
|
||||||
resize() { |
|
||||||
const num = this.getElementNumInRow() |
|
||||||
this.num = num |
|
||||||
this.width = `${100 / num}%` |
|
||||||
this.showCollapse = num < this.$slots.default.length |
|
||||||
} |
|
||||||
}, |
}, |
||||||
|
|
||||||
mounted() { |
getElementNumInRow() { |
||||||
this.resize() |
const vw = getElementInnerWidth(this.$el.parentNode) |
||||||
|
|
||||||
window.addEventListener('resize', this.resize) |
if (vw < 768) return this.xs |
||||||
|
else if (vw < 998) return this.sm |
||||||
this.$once('hook:beforeDestroy', () => { |
else if (vw < 1200) return this.md |
||||||
window.removeEventListener('resize', this.resize) |
return this.lg |
||||||
}) |
|
||||||
}, |
}, |
||||||
|
|
||||||
render() { |
resize() { |
||||||
const slots = this.$slots.default |
const num = this.getElementNumInRow() |
||||||
const collapseChildren = [] |
this.num = num |
||||||
if (this.showCollapse) { |
this.width = `${100 / num}%` |
||||||
//此处直接对el-row使用v-show会无效 |
this.showCollapse = num < this.$slots.default.length |
||||||
collapseChildren.push( |
} |
||||||
<el-collapse-transition> |
}, |
||||||
<div v-show={!this.collapse}> |
|
||||||
<el-row gutter={20}> |
mounted() { |
||||||
{slots.slice(this.num)} |
this.resize() |
||||||
</el-row> |
|
||||||
</div> |
window.addEventListener('resize', this.resize) |
||||||
</el-collapse-transition> |
|
||||||
) |
this.$once('hook:beforeDestroy', () => { |
||||||
const collapseSlot = this.$scopedSlots.collapse |
window.removeEventListener('resize', this.resize) |
||||||
|
}) |
||||||
collapseChildren.push( |
}, |
||||||
collapseSlot ? |
|
||||||
collapseSlot({collapse: this.collapse, handle: this.handleCollapse}) |
render() { |
||||||
: |
const slots = this.$slots.default |
||||||
<div class="searchForm__collapse"> |
const collapseChildren = [] |
||||||
<el-button |
if (this.showCollapse) { |
||||||
type="text" |
//此处直接对el-row使用v-show会无效 |
||||||
size="mini" |
collapseChildren.push( |
||||||
icon={this.collapse ? 'el-icon-arrow-down' : 'el-icon-arrow-up'} |
<el-collapse-transition> |
||||||
on-click={this.handleCollapse} |
<div v-show={!this.collapse}> |
||||||
> |
<el-row gutter={20}> |
||||||
{this.collapse ? '展开' : '收起'} |
{slots.slice(this.num)} |
||||||
</el-button> |
</el-row> |
||||||
</div> |
</div> |
||||||
) |
</el-collapse-transition> |
||||||
} |
) |
||||||
|
const collapseSlot = this.$scopedSlots.collapse |
||||||
return ( |
|
||||||
<el-form class="searchForm" label-position="right" label-width={this.labelWidth} size="small"> |
collapseChildren.push( |
||||||
<el-row gutter={20}> |
collapseSlot ? |
||||||
{this.num > slots.length ? slots : slots.slice(0, this.num)} |
collapseSlot({collapse: this.collapse, handle: this.handleCollapse}) |
||||||
</el-row> |
: |
||||||
{this.showCollapse && collapseChildren} |
<div class="searchForm__collapse"> |
||||||
</el-form> |
<el-button |
||||||
|
type="text" |
||||||
|
size="mini" |
||||||
|
icon={this.collapse ? 'el-icon-arrow-down' : 'el-icon-arrow-up'} |
||||||
|
on-click={this.handleCollapse} |
||||||
|
> |
||||||
|
{this.collapse ? '展开' : '收起'} |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
) |
) |
||||||
} |
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<el-form class="searchForm" label-position="right" label-width={this.labelWidth} size="small"> |
||||||
|
<el-row gutter={20}> |
||||||
|
{this.num > slots.length ? slots : slots.slice(0, this.num)} |
||||||
|
</el-row> |
||||||
|
{this.showCollapse && collapseChildren} |
||||||
|
</el-form> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss"> |
<style lang="scss"> |
||||||
.searchForm { |
.searchForm { |
||||||
margin-bottom: -15px; |
margin-bottom: -15px; |
||||||
|
|
||||||
> .el-row { |
> .el-row { |
||||||
display: flex; |
display: flex; |
||||||
flex-direction: row; |
flex-direction: row; |
||||||
flex-wrap: wrap; |
flex-wrap: wrap; |
||||||
} |
} |
||||||
|
|
||||||
.searchForm__collapse { |
.searchForm__collapse { |
||||||
position: relative; |
position: relative; |
||||||
bottom: 20px; |
bottom: 20px; |
||||||
margin: 0 auto; |
margin: 0 auto; |
||||||
text-align: center; |
text-align: center; |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,75 +1,75 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
//样式搬的https://antdv.com/components/skeleton-cn/ |
//样式搬的https://antdv.com/components/skeleton-cn/ |
||||||
import QSkeleton from './index' |
import QSkeleton from './index' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "PageSkeleton", |
name: "PageSkeleton", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
render() { |
render() { |
||||||
const single = ( |
const single = ( |
||||||
<div class="page-skeleton"> |
<div class="page-skeleton"> |
||||||
<div class="page-skeleton__header"> |
<div class="page-skeleton__header"> |
||||||
<QSkeleton type="circle"/> |
<QSkeleton type="circle"/> |
||||||
</div> |
|
||||||
<div class="page-skeleton__content"> |
|
||||||
<QSkeleton tag="h3"/> |
|
||||||
<ul class="page-skeleton__paragraph">{new Array(3).fill(<QSkeleton/>)}</ul> |
|
||||||
</div> |
|
||||||
</div> |
</div> |
||||||
) |
<div class="page-skeleton__content"> |
||||||
|
<QSkeleton tag="h3"/> |
||||||
|
<ul class="page-skeleton__paragraph">{new Array(3).fill(<QSkeleton/>)}</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
|
||||||
return <div class="page-skeleton-wrapper">{new Array(4).fill(single)}</div> |
return <div class="page-skeleton-wrapper">{new Array(4).fill(single)}</div> |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss"> |
<style lang="scss"> |
||||||
@import "~@/assets/styles/variables.scss"; |
@import "~@/assets/styles/variables.scss"; |
||||||
|
|
||||||
|
.page-skeleton-wrapper { |
||||||
|
margin: $page-view-margin; |
||||||
|
} |
||||||
|
|
||||||
.page-skeleton-wrapper { |
.page-skeleton { |
||||||
margin: $page-view-margin; |
width: 100%; |
||||||
|
display: table; |
||||||
|
|
||||||
|
& + & { |
||||||
|
margin-top: 20px; |
||||||
} |
} |
||||||
|
|
||||||
.page-skeleton { |
&__header, |
||||||
width: 100%; |
&__content { |
||||||
display: table; |
display: table-cell; |
||||||
|
} |
||||||
|
|
||||||
& + & { |
&__header { |
||||||
margin-top: 20px; |
padding-top: 2px; |
||||||
} |
padding-right: 16px; |
||||||
|
vertical-align: top; |
||||||
|
} |
||||||
|
|
||||||
&__header, |
&__content { |
||||||
&__content { |
width: 100%; |
||||||
display: table-cell; |
|
||||||
} |
|
||||||
|
|
||||||
&__header { |
> .q-skeleton { |
||||||
padding-top: 2px; |
width: 50%; |
||||||
padding-right: 16px; |
|
||||||
vertical-align: top; |
|
||||||
} |
} |
||||||
|
|
||||||
&__content { |
.page-skeleton__paragraph { |
||||||
width: 100%; |
margin-top: 28px; |
||||||
|
padding: 0; |
||||||
|
|
||||||
> .q-skeleton { |
.q-skeleton:last-child:not(:first-child):not(:nth-child(2)) { |
||||||
width: 50%; |
width: 61%; |
||||||
} |
} |
||||||
|
|
||||||
.page-skeleton__paragraph { |
.q-skeleton + .q-skeleton { |
||||||
margin-top: 28px; |
margin-top: 16px; |
||||||
padding: 0; |
|
||||||
|
|
||||||
.q-skeleton:last-child:not(:first-child):not(:nth-child(2)) { |
|
||||||
width: 61%; |
|
||||||
} |
|
||||||
|
|
||||||
.q-skeleton + .q-skeleton { |
|
||||||
margin-top: 16px; |
|
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,50 +1,50 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
//由quasar处搬运,https://quasar.dev/vue-components/skeleton |
//由quasar处搬运,https://quasar.dev/vue-components/skeleton |
||||||
import {skeletonAnimations, skeletonTypes} from './constant' |
import {skeletonAnimations, skeletonTypes} from './constant' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'QSkeleton', |
name: 'QSkeleton', |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
type: { |
type: { |
||||||
type: String, |
type: String, |
||||||
validator: v => skeletonTypes.includes(v), |
validator: v => skeletonTypes.includes(v), |
||||||
default: 'text' |
default: 'text' |
||||||
}, |
|
||||||
animation: { |
|
||||||
type: String, |
|
||||||
validator: v => skeletonAnimations.includes(v), |
|
||||||
default: 'wave' |
|
||||||
}, |
|
||||||
className: String, |
|
||||||
tag: {type: String, default: 'div'}, |
|
||||||
dark: Boolean, |
|
||||||
square: Boolean, |
|
||||||
bordered: Boolean, |
|
||||||
size: String, |
|
||||||
width: String, |
|
||||||
height: String |
|
||||||
}, |
}, |
||||||
|
animation: { |
||||||
|
type: String, |
||||||
|
validator: v => skeletonAnimations.includes(v), |
||||||
|
default: 'wave' |
||||||
|
}, |
||||||
|
className: String, |
||||||
|
tag: {type: String, default: 'div'}, |
||||||
|
dark: Boolean, |
||||||
|
square: Boolean, |
||||||
|
bordered: Boolean, |
||||||
|
size: String, |
||||||
|
width: String, |
||||||
|
height: String |
||||||
|
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {type, animation, className, tag, dark, square, bordered, size, width, height} = context.props |
const {type, animation, className, tag, dark, square, bordered, size, width, height} = context.props |
||||||
const style = size !== undefined ? {width: size, height: size} : {width, height} |
const style = size !== undefined ? {width: size, height: size} : {width, height} |
||||||
const classes = `q-skeleton--${dark === true ? 'dark' : 'light'} q-skeleton--type-${type}` + |
const classes = `q-skeleton--${dark === true ? 'dark' : 'light'} q-skeleton--type-${type}` + |
||||||
(animation !== 'none' ? ` q-skeleton--anim-${animation}` : '') + |
(animation !== 'none' ? ` q-skeleton--anim-${animation}` : '') + |
||||||
(square === true ? ' q-skeleton--square' : '') + |
(square === true ? ' q-skeleton--square' : '') + |
||||||
(bordered === true ? ' q-skeleton--bordered' : '') + |
(bordered === true ? ' q-skeleton--bordered' : '') + |
||||||
(className !== undefined ? ' ' + className : '') |
(className !== undefined ? ' ' + className : '') |
||||||
|
|
||||||
return h(tag, { |
return h(tag, { |
||||||
staticClass: 'q-skeleton', |
staticClass: 'q-skeleton', |
||||||
class: classes, |
class: classes, |
||||||
style, |
style, |
||||||
on: context.$listeners |
on: context.$listeners |
||||||
}, context.children) |
}, context.children) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss" src="./style.scss"></style> |
<style lang="scss" src="./style.scss"></style> |
||||||
|
|||||||
@ -1,50 +1,50 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import {isExternal} from '@/utils/validate' |
import {isExternal} from '@/utils/validate' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'SvgIcon', |
name: 'SvgIcon', |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
icon: String, |
icon: String, |
||||||
className: String |
className: String |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {listeners} = context |
const {listeners} = context |
||||||
const {icon, className} = context.props |
const {icon, className} = context.props |
||||||
const c = 'svg-icon ' + (className || '') |
const c = 'svg-icon ' + (className || '') |
||||||
if (isExternal(icon)) { |
if (isExternal(icon)) { |
||||||
const style = { |
const style = { |
||||||
mask: `url(${this.icon}) no-repeat 50% 50%`, |
mask: `url(${this.icon}) no-repeat 50% 50%`, |
||||||
'-webkit-mask': `url(${this.icon}) no-repeat 50% 50%` |
'-webkit-mask': `url(${this.icon}) no-repeat 50% 50%` |
||||||
} |
|
||||||
return <div {...{on: listeners}} class={'svg-external-icon ' + c} style={style}/> |
|
||||||
} |
|
||||||
else { |
|
||||||
const iconName = `#icon-${icon}` |
|
||||||
return ( |
|
||||||
<svg {...{on: listeners}} class={c} aria-hidden="true"> |
|
||||||
<use href={iconName}/> |
|
||||||
</svg> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
return <div {...{on: listeners}} class={'svg-external-icon ' + c} style={style}/> |
||||||
|
} |
||||||
|
else { |
||||||
|
const iconName = `#icon-${icon}` |
||||||
|
return ( |
||||||
|
<svg {...{on: listeners}} class={c} aria-hidden="true"> |
||||||
|
<use href={iconName}/> |
||||||
|
</svg> |
||||||
|
) |
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style> |
<style> |
||||||
.svg-icon { |
.svg-icon { |
||||||
width: 1em; |
width: 1em; |
||||||
height: 1em; |
height: 1em; |
||||||
fill: currentColor; |
fill: currentColor; |
||||||
overflow: hidden; |
overflow: hidden; |
||||||
} |
} |
||||||
|
|
||||||
.svg-external-icon { |
.svg-external-icon { |
||||||
background-color: currentColor; |
background-color: currentColor; |
||||||
mask-size: cover !important; |
mask-size: cover !important; |
||||||
display: inline-block; |
display: inline-block; |
||||||
} |
} |
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,47 +1,47 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "ZoomControl", |
name: "ZoomControl", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
value: {type: Number, default: 100}, |
value: {type: Number, default: 100}, |
||||||
step: {type: Number, default: 20}, |
step: {type: Number, default: 20}, |
||||||
min: {type: Number, default: 10}, |
min: {type: Number, default: 10}, |
||||||
max: {type: Number, default: 200} |
max: {type: Number, default: 200} |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {value, step, max, min} = context.props |
const {value, step, max, min} = context.props |
||||||
const input = context.listeners.input |
const input = context.listeners.input |
||||||
|
|
||||||
function zoomIn() { |
function zoomIn() { |
||||||
const zoom = value + step |
const zoom = value + step |
||||||
if (zoom <= max) input(zoom) |
if (zoom <= max) input(zoom) |
||||||
} |
} |
||||||
|
|
||||||
function zoomOut() { |
|
||||||
const zoom = value - step |
|
||||||
if (zoom >= min) input(zoom) |
|
||||||
} |
|
||||||
|
|
||||||
return ( |
function zoomOut() { |
||||||
<div class="zoom-wrapper"> |
const zoom = value - step |
||||||
<el-button circle icon="el-icon-minus" size="small" title="缩小" type="info" on-click={zoomOut}/> |
if (zoom >= min) input(zoom) |
||||||
<span class="zoom-number">{value}%</span> |
|
||||||
<el-button circle icon="el-icon-plus" size="small" title="放大" type="info" on-click={zoomIn}/> |
|
||||||
</div> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div class="zoom-wrapper"> |
||||||
|
<el-button circle icon="el-icon-minus" size="small" title="缩小" type="info" on-click={zoomOut}/> |
||||||
|
<span class="zoom-number">{value}%</span> |
||||||
|
<el-button circle icon="el-icon-plus" size="small" title="放大" type="info" on-click={zoomIn}/> |
||||||
|
</div> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style> |
<style> |
||||||
.zoom-wrapper .zoom-number { |
.zoom-wrapper .zoom-number { |
||||||
color: #657180; |
color: #657180; |
||||||
padding: 0 10px; |
padding: 0 10px; |
||||||
display: inline-block; |
display: inline-block; |
||||||
width: 60px; |
width: 60px; |
||||||
text-align: center; |
text-align: center; |
||||||
} |
} |
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,41 +1,41 @@ |
|||||||
<template> |
<template> |
||||||
<el-tree |
<el-tree |
||||||
ref="tree" |
ref="tree" |
||||||
:data="data" |
:data="data" |
||||||
:expand-on-click-node="false" |
:expand-on-click-node="false" |
||||||
:props="{label:'name'}" |
:props="{label:'name'}" |
||||||
:filter-node-method="filterNodeMethod" |
:filter-node-method="filterNodeMethod" |
||||||
highlight-current |
highlight-current |
||||||
node-key="id" |
node-key="id" |
||||||
v-on="$listeners" |
v-on="$listeners" |
||||||
/> |
/> |
||||||
</template> |
</template> |
||||||
|
|
||||||
<script> |
<script> |
||||||
import {getAll} from "@/api/system/category" |
import {getAll} from "@/api/system/category" |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "CategoryTree", |
name: "CategoryTree", |
||||||
|
|
||||||
props: {filterNodeMethod: Function}, |
props: {filterNodeMethod: Function}, |
||||||
|
|
||||||
computed: { |
computed: { |
||||||
data() { |
data() { |
||||||
return this.$store.state.dataCache.categoryTree |
return this.$store.state.dataCache.categoryTree |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
methods: { |
|
||||||
filter(v){ |
|
||||||
this.$refs.tree.filter(v) |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
mounted() { |
methods: { |
||||||
if (this.data.length > 0) return |
filter(v) { |
||||||
getAll() |
this.$refs.tree.filter(v) |
||||||
.then(data => this.$store.commit('dataCache/categories', data)) |
|
||||||
.finally(() => this.loading = false) |
|
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
if (this.data.length > 0) return |
||||||
|
getAll() |
||||||
|
.then(data => this.$store.commit('dataCache/categories', data)) |
||||||
|
.finally(() => this.loading = false) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,40 +1,40 @@ |
|||||||
<template> |
<template> |
||||||
<el-select :value="value" :disabled="disabled" multiple size="small" @input="emit"> |
<el-select :value="value" :disabled="disabled" multiple size="small" @input="emit"> |
||||||
<el-option |
<el-option |
||||||
v-for="user in data" |
v-for="user in data" |
||||||
:key="user.id" |
:key="user.id" |
||||||
:label="user.name" |
:label="user.name" |
||||||
:value="user.id" |
:value="user.id" |
||||||
/> |
/> |
||||||
</el-select> |
</el-select> |
||||||
</template> |
</template> |
||||||
|
|
||||||
<script> |
<script> |
||||||
import {getUsers} from '@/api/system/user' |
import {getUsers} from '@/api/system/user' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "SimpleMultipleUserSelector", |
name: "SimpleMultipleUserSelector", |
||||||
|
|
||||||
props: { |
props: { |
||||||
value: Array, |
value: Array, |
||||||
disabled: Boolean |
disabled: Boolean |
||||||
}, |
}, |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
data: [] |
data: [] |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
methods: { |
|
||||||
emit(v) { |
|
||||||
this.$emit('input', v) |
|
||||||
} |
|
||||||
}, |
|
||||||
|
|
||||||
mounted() { |
methods: { |
||||||
getUsers({page: 1, pageSize: 9999}) |
emit(v) { |
||||||
.then(({list}) => this.data = list) |
this.$emit('input', v) |
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
getUsers({page: 1, pageSize: 9999}) |
||||||
|
.then(({list}) => this.data = list) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,29 +1,29 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: 'Hamburger', |
name: 'Hamburger', |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: {active: Boolean}, |
props: {active: Boolean}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {active} = context.props |
const {active} = context.props |
||||||
const className = {'navbar-icon': true, 'el-icon-s-unfold': true, 'hamburger': true, 'is-active': active} |
const className = {'navbar-icon': true, 'el-icon-s-unfold': true, 'hamburger': true, 'is-active': active} |
||||||
return ( |
return ( |
||||||
<div {...context.data}> |
<div {...context.data}> |
||||||
<i class={className}/> |
<i class={className}/> |
||||||
</div> |
</div> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style> |
<style> |
||||||
.hamburger { |
.hamburger { |
||||||
font-size: 20px; |
font-size: 20px; |
||||||
} |
} |
||||||
|
|
||||||
.hamburger.is-active { |
.hamburger.is-active { |
||||||
transform: rotate(180deg); |
transform: rotate(180deg); |
||||||
} |
} |
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,26 +1,26 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import {sidebarLogoUrl, title} from '@/config' |
import {sidebarLogoUrl, title} from '@/config' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'SidebarLogo', |
name: 'SidebarLogo', |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: {collapse: Boolean}, |
props: {collapse: Boolean}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {collapse} = context.props |
const {collapse} = context.props |
||||||
|
|
||||||
const logoClass = {'sidebar-logo-container': true, 'collapse': collapse} |
const logoClass = {'sidebar-logo-container': true, 'collapse': collapse} |
||||||
|
|
||||||
return ( |
return ( |
||||||
<div class={logoClass}> |
<div class={logoClass}> |
||||||
<router-link class="sidebar-logo-link" to="/"> |
<router-link class="sidebar-logo-link" to="/"> |
||||||
{sidebarLogoUrl && <img src={sidebarLogoUrl} class="sidebar-logo"/>} |
{sidebarLogoUrl && <img src={sidebarLogoUrl} class="sidebar-logo"/>} |
||||||
{!collapse && <h1 class="sidebar-title">{title}</h1>} |
{!collapse && <h1 class="sidebar-title">{title}</h1>} |
||||||
</router-link> |
</router-link> |
||||||
</div> |
</div> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,72 +1,72 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import SidebarItemContent from './SidebarItemContent' |
import SidebarItemContent from './SidebarItemContent' |
||||||
|
|
||||||
function getOnlyChild(item) { |
function getOnlyChild(item) { |
||||||
const children = item.children || [] |
const children = item.children || [] |
||||||
|
|
||||||
if (children.length === 1) return item.alwaysShow ? null : children[0] |
if (children.length === 1) return item.alwaysShow ? null : children[0] |
||||||
|
|
||||||
if (children.length < 1) return {...item, path: undefined, children: undefined} |
if (children.length < 1) return {...item, path: undefined, children: undefined} |
||||||
|
|
||||||
return null |
return null |
||||||
} |
} |
||||||
|
|
||||||
function renderNode(h, {item, showParent, collapse}) { |
function renderNode(h, {item, showParent, collapse}) { |
||||||
let onlyOneChild = getOnlyChild(item) |
let onlyOneChild = getOnlyChild(item) |
||||||
|
|
||||||
const showSingle = onlyOneChild && !onlyOneChild.children |
const showSingle = onlyOneChild && !onlyOneChild.children |
||||||
|
|
||||||
if (showSingle) { |
if (showSingle) { |
||||||
const {icon, title} = onlyOneChild.meta |
const {icon, title} = onlyOneChild.meta |
||||||
|
|
||||||
return ( |
return ( |
||||||
<el-menu-item index={onlyOneChild.fullPath}> |
<el-menu-item index={onlyOneChild.fullPath}> |
||||||
<SidebarItemContent icon={icon} title={title}/> |
<SidebarItemContent icon={icon} title={title}/> |
||||||
</el-menu-item> |
</el-menu-item> |
||||||
) |
) |
||||||
} |
} |
||||||
else { |
else { |
||||||
const {icon, title} = item.meta |
const {icon, title} = item.meta |
||||||
|
|
||||||
let children = item.children.map(child => renderNode(h, { |
let children = item.children.map(child => renderNode(h, { |
||||||
item: child, |
item: child, |
||||||
showParent, |
showParent, |
||||||
collapse |
collapse |
||||||
})) |
})) |
||||||
|
|
||||||
//弹出菜单如果包裹滚动条,则在触发mouseleave时,不会触发父菜单的mouseleave事件 |
//弹出菜单如果包裹滚动条,则在触发mouseleave时,不会触发父菜单的mouseleave事件 |
||||||
if (collapse) { |
if (collapse) { |
||||||
//弹出菜单显示父级信息 |
//弹出菜单显示父级信息 |
||||||
if (showParent) { |
if (showParent) { |
||||||
children = [ |
children = [ |
||||||
<div class="popover-menu__title el-menu-item"> |
<div class="popover-menu__title el-menu-item"> |
||||||
<SidebarItemContent icon={icon} title={title}/> |
<SidebarItemContent icon={icon} title={title}/> |
||||||
</div>, |
</div>, |
||||||
<div class="el-menu el-menu--inline">{children}</div> |
<div class="el-menu el-menu--inline">{children}</div> |
||||||
] |
] |
||||||
} |
|
||||||
} |
} |
||||||
|
|
||||||
return ( |
|
||||||
<el-submenu index={item.fullPath} popper-append-to-body> |
|
||||||
<SidebarItemContent slot="title" icon={icon} title={title}/> |
|
||||||
{children} |
|
||||||
</el-submenu> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<el-submenu index={item.fullPath} popper-append-to-body> |
||||||
|
<SidebarItemContent slot="title" icon={icon} title={title}/> |
||||||
|
{children} |
||||||
|
</el-submenu> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
export default { |
export default { |
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
item: Object, |
item: Object, |
||||||
showParent: Boolean, |
showParent: Boolean, |
||||||
collapse: Boolean |
collapse: Boolean |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
return renderNode(h, context.props) |
return renderNode(h, context.props) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,31 +1,31 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
export default { |
export default { |
||||||
name: "SidebarItemContent", |
name: "SidebarItemContent", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
icon: String, |
icon: String, |
||||||
title: String |
title: String |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {icon, title} = context.props |
const {icon, title} = context.props |
||||||
const vnodes = [] |
const vnodes = [] |
||||||
|
|
||||||
let iconComponent |
let iconComponent |
||||||
|
|
||||||
if (icon) { |
if (icon) { |
||||||
const isElIcon = icon.startsWith('el-icon-') |
const isElIcon = icon.startsWith('el-icon-') |
||||||
iconComponent = isElIcon ? <i class={`svg-icon ${icon}`}/> : <svg-icon icon={icon}/> |
iconComponent = isElIcon ? <i class={`svg-icon ${icon}`}/> : <svg-icon icon={icon}/> |
||||||
} |
} |
||||||
else iconComponent = <span class="svg-icon"/> |
else iconComponent = <span class="svg-icon"/> |
||||||
|
|
||||||
vnodes.push(iconComponent) |
vnodes.push(iconComponent) |
||||||
|
|
||||||
if (title) vnodes.push(<span slot="title" class="sidebar-item-content">{title}</span>) |
if (title) vnodes.push(<span slot="title" class="sidebar-item-content">{title}</span>) |
||||||
|
|
||||||
return vnodes |
return vnodes |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,149 +1,149 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import {mapState} from 'vuex' |
import {mapState} from 'vuex' |
||||||
import Logo from './components/Logo' |
import Logo from './components/Logo' |
||||||
import SidebarItem from './components/SidebarItem' |
import SidebarItem from './components/SidebarItem' |
||||||
import {isExternal} from "@/utils/validate" |
import {isExternal} from "@/utils/validate" |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: 'sidebar', |
name: 'sidebar', |
||||||
|
|
||||||
components: {SidebarItem, Logo}, |
components: {SidebarItem, Logo}, |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
mouseOutside: true |
mouseOutside: true |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
computed: { |
||||||
|
...mapState('app', ['device']), |
||||||
|
|
||||||
|
...mapState('resource', ['sidebarMenus']), |
||||||
|
|
||||||
|
...mapState('setting', ['showLogo', 'sidebarCollapse', 'sidebarUniqueOpen', 'sidebarShowParent', 'sidebarAutoHidden']), |
||||||
|
|
||||||
|
activeMenu() { |
||||||
|
const route = this.$route |
||||||
|
const {meta, path} = route |
||||||
|
if (path.startsWith('/redirect')) { |
||||||
|
return path.replace('/redirect', '') |
||||||
} |
} |
||||||
|
return meta.activeMenu || path |
||||||
}, |
}, |
||||||
|
|
||||||
computed: { |
//仅在pc端可折叠 |
||||||
...mapState('app', ['device']), |
collapse() { |
||||||
|
return this.sidebarCollapse && this.device === 'pc' |
||||||
...mapState('resource', ['sidebarMenus']), |
|
||||||
|
|
||||||
...mapState('setting', ['showLogo', 'sidebarCollapse', 'sidebarUniqueOpen', 'sidebarShowParent', 'sidebarAutoHidden']), |
|
||||||
|
|
||||||
activeMenu() { |
|
||||||
const route = this.$route |
|
||||||
const {meta, path} = route |
|
||||||
if (path.startsWith('/redirect')) { |
|
||||||
return path.replace('/redirect', '') |
|
||||||
} |
|
||||||
return meta.activeMenu || path |
|
||||||
}, |
|
||||||
|
|
||||||
//仅在pc端可折叠 |
|
||||||
collapse() { |
|
||||||
return this.sidebarCollapse && this.device === 'pc' |
|
||||||
}, |
|
||||||
|
|
||||||
hideSidebar() { |
|
||||||
return this.sidebarAutoHidden && this.mouseOutside |
|
||||||
|| this.sidebarCollapse && this.device === 'mobile' |
|
||||||
}, |
|
||||||
|
|
||||||
sidebarClass() { |
|
||||||
return { |
|
||||||
'sidebar-container': true, |
|
||||||
'mobile': this.device === 'mobile', |
|
||||||
'collapse-sidebar': this.collapse, |
|
||||||
'hide-sidebar': this.hideSidebar |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
}, |
||||||
|
|
||||||
watch: { |
hideSidebar() { |
||||||
//由于elMenu的initOpenedMenu()不会触发select事件,所以手动实现菜单收起 |
return this.sidebarAutoHidden && this.mouseOutside |
||||||
'$route.path'(nv, ov) { |
|| this.sidebarCollapse && this.device === 'mobile' |
||||||
//如果是redirect刷新,则跳过 |
|
||||||
if (nv === `/redirect${ov}`) return |
|
||||||
const menu = this.$refs.menu |
|
||||||
if (!menu) return |
|
||||||
const item = menu.items[this.activeMenu] |
|
||||||
if (!item) menu.openedMenus = [] |
|
||||||
else this.select(item.index, item.indexPath, item, false) |
|
||||||
}, |
|
||||||
|
|
||||||
hideSidebar(v) { |
|
||||||
if (v) document.addEventListener('mousemove', this.moveEvent) |
|
||||||
else document.removeEventListener('mousemove', this.moveEvent) |
|
||||||
} |
|
||||||
}, |
}, |
||||||
|
|
||||||
methods: { |
sidebarClass() { |
||||||
moveEvent(e) { |
return { |
||||||
if (e.clientX <= 15) this.mouseOutside = false |
'sidebar-container': true, |
||||||
}, |
'mobile': this.device === 'mobile', |
||||||
|
'collapse-sidebar': this.collapse, |
||||||
select(index, indexPath, item, jump = true) { |
'hide-sidebar': this.hideSidebar |
||||||
//开启手风琴模式时,激活没有子级的菜单时收起其它展开项 |
|
||||||
if (this.sidebarUniqueOpen && indexPath.length === 1) { |
|
||||||
const menu = this.$refs.menu |
|
||||||
const opened = menu.openedMenus |
|
||||||
opened.forEach(i => i !== index && menu.closeMenu(i)) |
|
||||||
} |
|
||||||
|
|
||||||
//mobile时激活隐藏侧边栏 |
|
||||||
this.device === 'mobile' && this.$store.commit('setting/sidebarCollapse', true) |
|
||||||
|
|
||||||
if (!jump) return |
|
||||||
|
|
||||||
//外部链接时打开新窗口 |
|
||||||
if (isExternal(index)) { |
|
||||||
return window.open(index) |
|
||||||
} |
|
||||||
|
|
||||||
if (this.$route.path === index) { |
|
||||||
this.$store.commit('tagsView/delCachedView', this.$route) |
|
||||||
this.$nextTick(() => this.$router.replace({path: '/redirect' + this.$route.fullPath})) |
|
||||||
} |
|
||||||
else this.$router.push(index) |
|
||||||
} |
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
watch: { |
||||||
|
//由于elMenu的initOpenedMenu()不会触发select事件,所以手动实现菜单收起 |
||||||
|
'$route.path'(nv, ov) { |
||||||
|
//如果是redirect刷新,则跳过 |
||||||
|
if (nv === `/redirect${ov}`) return |
||||||
|
const menu = this.$refs.menu |
||||||
|
if (!menu) return |
||||||
|
const item = menu.items[this.activeMenu] |
||||||
|
if (!item) menu.openedMenus = [] |
||||||
|
else this.select(item.index, item.indexPath, item, false) |
||||||
}, |
}, |
||||||
|
|
||||||
mounted() { |
hideSidebar(v) { |
||||||
if (this.sidebarAutoHidden) { |
if (v) document.addEventListener('mousemove', this.moveEvent) |
||||||
document.addEventListener('mousemove', this.moveEvent) |
else document.removeEventListener('mousemove', this.moveEvent) |
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
this.$once('hook:beforeDestroy', () => { |
methods: { |
||||||
document.removeEventListener('mousemove', this.moveEvent) |
moveEvent(e) { |
||||||
}) |
if (e.clientX <= 15) this.mouseOutside = false |
||||||
}, |
}, |
||||||
|
|
||||||
render() { |
select(index, indexPath, item, jump = true) { |
||||||
const menu = ( |
//开启手风琴模式时,激活没有子级的菜单时收起其它展开项 |
||||||
<el-menu |
if (this.sidebarUniqueOpen && indexPath.length === 1) { |
||||||
ref="menu" |
const menu = this.$refs.menu |
||||||
collapse={this.collapse} |
const opened = menu.openedMenus |
||||||
collapse-transition={false} |
opened.forEach(i => i !== index && menu.closeMenu(i)) |
||||||
default-active={this.activeMenu} |
} |
||||||
unique-opened={this.sidebarUniqueOpen} |
|
||||||
mode="vertical" |
//mobile时激活隐藏侧边栏 |
||||||
on-select={this.select} |
this.device === 'mobile' && this.$store.commit('setting/sidebarCollapse', true) |
||||||
> |
|
||||||
{this.sidebarMenus.map(route => ( |
if (!jump) return |
||||||
<sidebar-item |
|
||||||
key={route.path} |
//外部链接时打开新窗口 |
||||||
show-parent={this.sidebarShowParent} |
if (isExternal(index)) { |
||||||
collapse={this.sidebarCollapse} |
return window.open(index) |
||||||
item={route} |
} |
||||||
/> |
|
||||||
))} |
if (this.$route.path === index) { |
||||||
</el-menu> |
this.$store.commit('tagsView/delCachedView', this.$route) |
||||||
) |
this.$nextTick(() => this.$router.replace({path: '/redirect' + this.$route.fullPath})) |
||||||
|
} |
||||||
return ( |
else this.$router.push(index) |
||||||
<aside |
|
||||||
class={this.sidebarClass} |
|
||||||
on-mouseenter={() => this.mouseOutside = false} |
|
||||||
on-mouseleave={() => this.mouseOutside = true} |
|
||||||
> |
|
||||||
{this.showLogo && <logo collapse={this.collapse}/>} |
|
||||||
{<el-scrollbar noresize native>{menu}</el-scrollbar>} |
|
||||||
</aside> |
|
||||||
) |
|
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
if (this.sidebarAutoHidden) { |
||||||
|
document.addEventListener('mousemove', this.moveEvent) |
||||||
|
} |
||||||
|
|
||||||
|
this.$once('hook:beforeDestroy', () => { |
||||||
|
document.removeEventListener('mousemove', this.moveEvent) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
render() { |
||||||
|
const menu = ( |
||||||
|
<el-menu |
||||||
|
ref="menu" |
||||||
|
collapse={this.collapse} |
||||||
|
collapse-transition={false} |
||||||
|
default-active={this.activeMenu} |
||||||
|
unique-opened={this.sidebarUniqueOpen} |
||||||
|
mode="vertical" |
||||||
|
on-select={this.select} |
||||||
|
> |
||||||
|
{this.sidebarMenus.map(route => ( |
||||||
|
<sidebar-item |
||||||
|
key={route.path} |
||||||
|
show-parent={this.sidebarShowParent} |
||||||
|
collapse={this.sidebarCollapse} |
||||||
|
item={route} |
||||||
|
/> |
||||||
|
))} |
||||||
|
</el-menu> |
||||||
|
) |
||||||
|
|
||||||
|
return ( |
||||||
|
<aside |
||||||
|
class={this.sidebarClass} |
||||||
|
on-mouseenter={() => this.mouseOutside = false} |
||||||
|
on-mouseleave={() => this.mouseOutside = true} |
||||||
|
> |
||||||
|
{this.showLogo && <logo collapse={this.collapse}/>} |
||||||
|
{<el-scrollbar noresize native>{menu}</el-scrollbar>} |
||||||
|
</aside> |
||||||
|
) |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss" src="./style.scss"></style> |
<style lang="scss" src="./style.scss"></style> |
||||||
|
|||||||
@ -1,49 +1,49 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
const animations = [ |
const animations = [ |
||||||
{name: '无', value: ''}, |
{name: '无', value: ''}, |
||||||
{name: '烟花', value: 'firework'}, |
{name: '烟花', value: 'firework'}, |
||||||
{name: '上帝之光', value: 'godrays'}, |
{name: '上帝之光', value: 'godrays'}, |
||||||
{name: '简单粒子', value: 'moveFollowMouse'}, |
{name: '简单粒子', value: 'moveFollowMouse'}, |
||||||
{name: '球', value: 'particleBall'}, |
{name: '球', value: 'particleBall'}, |
||||||
{name: '网络', value: 'particleNetwork'}, |
{name: '网络', value: 'particleNetwork'}, |
||||||
{name: '波浪', value: 'particleWave'}, |
{name: '波浪', value: 'particleWave'}, |
||||||
{name: '雨', value: 'reflectRain'}, |
{name: '雨', value: 'reflectRain'}, |
||||||
{name: '流星雨', value: 'sparkRain'}, |
{name: '流星雨', value: 'sparkRain'}, |
||||||
{name: '阳光', value: 'sunlight'}, |
{name: '阳光', value: 'sunlight'}, |
||||||
] |
] |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "SetAnimation", |
name: "SetAnimation", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
value: String, |
value: String, |
||||||
customClass: String |
customClass: String |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {value, customClass} = context.props |
const {value, customClass} = context.props |
||||||
return ( |
return ( |
||||||
<el-dropdown class={customClass} size="medium" trigger="click" onCommand={context.listeners.select}> |
<el-dropdown class={customClass} size="medium" trigger="click" onCommand={context.listeners.select}> |
||||||
<el-button type="text" title="选择背景动画"> |
<el-button type="text" title="选择背景动画"> |
||||||
<svg-icon icon="show"/> |
<svg-icon icon="show"/> |
||||||
</el-button> |
</el-button> |
||||||
<el-dropdown-menu slot="dropdown"> |
<el-dropdown-menu slot="dropdown"> |
||||||
{ |
{ |
||||||
animations.map(animation => ( |
animations.map(animation => ( |
||||||
<el-dropdown-item |
<el-dropdown-item |
||||||
key={animation.value} |
key={animation.value} |
||||||
disabled={animation.value === value} |
disabled={animation.value === value} |
||||||
command={animation.value} |
command={animation.value} |
||||||
> |
> |
||||||
{animation.name} |
{animation.name} |
||||||
</el-dropdown-item> |
</el-dropdown-item> |
||||||
)) |
)) |
||||||
} |
} |
||||||
</el-dropdown-menu> |
</el-dropdown-menu> |
||||||
</el-dropdown> |
</el-dropdown> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,15 +1,15 @@ |
|||||||
<script> |
<script> |
||||||
export default { |
export default { |
||||||
created() { |
created() { |
||||||
const {params, query} = this.$route |
const {params, query} = this.$route |
||||||
//如果使用了name+params传参 |
//如果使用了name+params传参 |
||||||
if ('params' in query) { |
if ('params' in query) { |
||||||
const {name, params} = JSON.parse(query.params) |
const {name, params} = JSON.parse(query.params) |
||||||
this.$router.replace({name, params}) |
this.$router.replace({name, params}) |
||||||
} |
} |
||||||
else this.$router.replace({path: `/${params.path}`, query}) |
else this.$router.replace({path: `/${params.path}`, query}) |
||||||
}, |
}, |
||||||
|
|
||||||
render: h => h() |
render: h => h() |
||||||
} |
} |
||||||
</script> |
</script> |
||||||
|
|||||||
@ -1,98 +1,98 @@ |
|||||||
<script type="text/jsx"> |
<script type="text/jsx"> |
||||||
import CountTo from 'vue-count-to' |
import CountTo from 'vue-count-to' |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "PanelGroupItem", |
name: "PanelGroupItem", |
||||||
|
|
||||||
functional: true, |
functional: true, |
||||||
|
|
||||||
props: { |
props: { |
||||||
icon: String, |
icon: String, |
||||||
color: String, |
color: String, |
||||||
text: String, |
text: String, |
||||||
value: Number |
value: Number |
||||||
}, |
}, |
||||||
|
|
||||||
render(h, context) { |
render(h, context) { |
||||||
const {icon, color, text, value} = context.props |
const {icon, color, text, value} = context.props |
||||||
return ( |
return ( |
||||||
<el-row class="card-panel" type="flex" justify="space-between" {...context.data}> |
<el-row class="card-panel" type="flex" justify="space-between" {...context.data}> |
||||||
<div class="card-panel-icon-wrapper" style={'color:' + color}> |
<div class="card-panel-icon-wrapper" style={'color:' + color}> |
||||||
<svg-icon icon={icon} class-name="card-panel-icon"/> |
<svg-icon icon={icon} class-name="card-panel-icon"/> |
||||||
</div> |
</div> |
||||||
<div class="card-panel-description"> |
<div class="card-panel-description"> |
||||||
<div class="card-panel-text">{text}</div> |
<div class="card-panel-text">{text}</div> |
||||||
<CountTo class="card-panel-num" end-val={value} start-val={0}/> |
<CountTo class="card-panel-num" end-val={value} start-val={0}/> |
||||||
</div> |
</div> |
||||||
</el-row> |
</el-row> |
||||||
) |
) |
||||||
} |
|
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|
||||||
<style lang="scss"> |
<style lang="scss"> |
||||||
.card-panel { |
.card-panel { |
||||||
height: 108px; |
height: 108px; |
||||||
cursor: pointer; |
cursor: pointer; |
||||||
font-size: 12px; |
font-size: 12px; |
||||||
position: relative; |
position: relative; |
||||||
overflow: hidden; |
overflow: hidden; |
||||||
color: #666; |
color: #666; |
||||||
background: #fff; |
background: #fff; |
||||||
border-radius: 4px; |
border-radius: 4px; |
||||||
-webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); |
-webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); |
||||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); |
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); |
||||||
border-color: rgba(0, 0, 0, .05); |
border-color: rgba(0, 0, 0, .05); |
||||||
|
|
||||||
&:hover .card-panel-icon-wrapper { |
&:hover .card-panel-icon-wrapper { |
||||||
color: #fff; |
color: #fff; |
||||||
} |
} |
||||||
|
|
||||||
.card-panel-icon-wrapper { |
.card-panel-icon-wrapper { |
||||||
margin: 14px 0 14px 14px; |
margin: 14px 0 14px 14px; |
||||||
padding: 16px; |
padding: 16px; |
||||||
transition: all 0.38s ease-out; |
transition: all 0.38s ease-out; |
||||||
border-radius: 6px; |
border-radius: 6px; |
||||||
} |
} |
||||||
|
|
||||||
.card-panel-icon { |
.card-panel-icon { |
||||||
font-size: 48px; |
font-size: 48px; |
||||||
} |
} |
||||||
|
|
||||||
.card-panel-description { |
.card-panel-description { |
||||||
font-weight: bold; |
font-weight: bold; |
||||||
margin: 26px 20px 0 26px; |
margin: 26px 20px 0 26px; |
||||||
|
|
||||||
.card-panel-text { |
.card-panel-text { |
||||||
line-height: 18px; |
line-height: 18px; |
||||||
color: rgba(0, 0, 0, 0.45); |
color: rgba(0, 0, 0, 0.45); |
||||||
font-size: 16px; |
font-size: 16px; |
||||||
margin-bottom: 12px; |
margin-bottom: 12px; |
||||||
} |
} |
||||||
|
|
||||||
.card-panel-num { |
.card-panel-num { |
||||||
font-size: 20px; |
font-size: 20px; |
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
@media (max-width: 550px) { |
@media (max-width: 550px) { |
||||||
.card-panel-description { |
.card-panel-description { |
||||||
display: none; |
display: none; |
||||||
} |
} |
||||||
|
|
||||||
.card-panel-icon-wrapper { |
.card-panel-icon-wrapper { |
||||||
float: none !important; |
float: none !important; |
||||||
width: 100%; |
width: 100%; |
||||||
height: 100%; |
height: 100%; |
||||||
margin: 0 !important; |
margin: 0 !important; |
||||||
|
|
||||||
.svg-icon { |
.svg-icon { |
||||||
display: block; |
display: block; |
||||||
margin: 14px auto !important; |
margin: 14px auto !important; |
||||||
float: none !important; |
float: none !important; |
||||||
} |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
} |
||||||
|
|
||||||
</style> |
</style> |
||||||
|
|||||||
@ -1,88 +1,88 @@ |
|||||||
<template> |
<template> |
||||||
<tree-select |
<tree-select |
||||||
:value="value" |
:value="value" |
||||||
:data="tree" |
:data="tree" |
||||||
:disabled="disabled" |
:disabled="disabled" |
||||||
:props="props" |
:props="props" |
||||||
size="small" |
size="small" |
||||||
popper-append-to-body |
popper-append-to-body |
||||||
@change="change" |
@change="change" |
||||||
@input="emit" |
@input="emit" |
||||||
/> |
/> |
||||||
</template> |
</template> |
||||||
|
|
||||||
<script> |
<script> |
||||||
import TreeSelect from '@/components/TreeSelect' |
import TreeSelect from '@/components/TreeSelect' |
||||||
import {getAll} from "@/api/system/category" |
import {getAll} from "@/api/system/category" |
||||||
import {isEmpty} from "@/utils" |
import {isEmpty} from "@/utils" |
||||||
import {elError} from "@/utils/message" |
import {elError} from "@/utils/message" |
||||||
|
|
||||||
export default { |
export default { |
||||||
name: "CategorySelector", |
name: "CategorySelector", |
||||||
|
|
||||||
components: {TreeSelect}, |
components: {TreeSelect}, |
||||||
|
|
||||||
props: { |
props: { |
||||||
value: {required: true}, |
value: {required: true}, |
||||||
disabled: Boolean, |
disabled: Boolean, |
||||||
selected: {type: Array, default: () => []} |
selected: {type: Array, default: () => []} |
||||||
}, |
}, |
||||||
|
|
||||||
data() { |
data() { |
||||||
return { |
return { |
||||||
props: { |
props: { |
||||||
label: 'name', |
label: 'name', |
||||||
children: 'children', |
children: 'children', |
||||||
disabled: '_disabled' |
disabled: '_disabled' |
||||||
} |
|
||||||
} |
} |
||||||
}, |
} |
||||||
|
}, |
||||||
|
|
||||||
computed: { |
computed: { |
||||||
tree() { |
tree() { |
||||||
const arr = this.$store.state.dataCache.categoryTree |
const arr = this.$store.state.dataCache.categoryTree |
||||||
this.addDisabledAttr(arr) |
this.addDisabledAttr(arr) |
||||||
return arr |
return arr |
||||||
}, |
|
||||||
selectableCategories() { |
|
||||||
return this.$store.state.dataCache.categories.filter(i => i.type === 1) |
|
||||||
}, |
|
||||||
}, |
}, |
||||||
|
selectableCategories() { |
||||||
|
return this.$store.state.dataCache.categories.filter(i => i.type === 1) |
||||||
|
}, |
||||||
|
}, |
||||||
|
|
||||||
methods: { |
methods: { |
||||||
init() { |
init() { |
||||||
if (this.tree.length === 0) { |
if (this.tree.length === 0) { |
||||||
getAll().then(data => this.$store.commit('dataCache/categories', data)) |
getAll().then(data => this.$store.commit('dataCache/categories', data)) |
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
addDisabledAttr(arr) { |
|
||||||
arr.forEach(i => { |
|
||||||
i._disabled = i.type !== 1 |
|
||||||
i.children && this.addDisabledAttr(i.children) |
|
||||||
}) |
|
||||||
}, |
|
||||||
|
|
||||||
change(v) { |
addDisabledAttr(arr) { |
||||||
if (isEmpty(v) || this.selected.length <= 0) return |
arr.forEach(i => { |
||||||
if (this.selected.includes(v)) { |
i._disabled = i.type !== 1 |
||||||
elError('该分类已选择') |
i.children && this.addDisabledAttr(i.children) |
||||||
this.emit(null) |
}) |
||||||
} |
}, |
||||||
}, |
|
||||||
|
|
||||||
emit(v) { |
change(v) { |
||||||
this.$emit('input', v) |
if (isEmpty(v) || this.selected.length <= 0) return |
||||||
if (!isEmpty(v)) { |
if (this.selected.includes(v)) { |
||||||
let item = this.selectableCategories.find(i => i.id === v) |
elError('该分类已选择') |
||||||
this.$emit('get-name', item ? item.name : null) |
this.emit(null) |
||||||
} |
|
||||||
else this.$emit('get-name', null) |
|
||||||
} |
} |
||||||
}, |
}, |
||||||
|
|
||||||
mounted() { |
emit(v) { |
||||||
this.init() |
this.$emit('input', v) |
||||||
|
if (!isEmpty(v)) { |
||||||
|
let item = this.selectableCategories.find(i => i.id === v) |
||||||
|
this.$emit('get-name', item ? item.name : null) |
||||||
|
} |
||||||
|
else this.$emit('get-name', null) |
||||||
} |
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
this.init() |
||||||
} |
} |
||||||
|
} |
||||||
</script> |
</script> |
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue