修复高阶函数式组件的slot问题

修复了根据后台数据构建路有菜单时因引用传递导致的一些问题

修复用户导航的一些问题

增加了一些示例页面

部分文件位置调整

代码优化
master
toesbieya 6 years ago
parent fc13279ba4
commit de61b0f2e2
  1. 17
      vue/element-ui-personal/component/Message/main.vue
  2. 2
      vue/src/asset/style/element-ui.scss
  3. 2
      vue/src/asset/style/index.scss
  4. 8
      vue/src/component/CollapseCard/index.vue
  5. 4
      vue/src/component/OrgTree/index.vue
  6. 0
      vue/src/component/OrgTree/node.vue
  7. 0
      vue/src/component/OrgTree/style.scss
  8. 2
      vue/src/component/RegionSelector/Tree/TreeDialog.vue
  9. 9
      vue/src/component/abstract/Dialog/index.vue
  10. 16
      vue/src/component/abstract/Table/index.vue
  11. 34
      vue/src/component/form/Anchor/index.vue
  12. 7
      vue/src/component/form/Search/index.vue
  13. 96
      vue/src/component/form/ValidateInfo/index.vue
  14. 50
      vue/src/component/form/ValidateInfo/style.scss
  15. 2
      vue/src/globalMethod/BottomTip/main.vue
  16. 8
      vue/src/globalMethod/Guide/index.js
  17. 82
      vue/src/globalMethod/Guide/main.vue
  18. 31
      vue/src/globalMethod/Guide/style.scss
  19. 28
      vue/src/globalMethod/Guide/utils.js
  20. 4
      vue/src/globalMethod/Verify/index.js
  21. 7
      vue/src/layout/component/Navbar/component/HeadMenu.vue
  22. 27
      vue/src/layout/component/Navbar/index.vue
  23. 6
      vue/src/mixin/docDetailMixin.js
  24. 2
      vue/src/mixin/docTableMixin.js
  25. 60
      vue/src/mixin/guide/base.js
  26. 23
      vue/src/mixin/guide/data/navbar.js
  27. 18
      vue/src/mixin/guide/index.js
  28. 10
      vue/src/router/define.js
  29. 6
      vue/src/router/module/admin/child/default.js
  30. 4
      vue/src/router/module/admin/child/message.js
  31. 12
      vue/src/router/module/admin/child/purchase.js
  32. 12
      vue/src/router/module/admin/child/sell.js
  33. 2
      vue/src/router/module/admin/child/stock.js
  34. 14
      vue/src/router/module/admin/child/system.js
  35. 2
      vue/src/router/module/admin/index.js
  36. 0
      vue/src/router/module/dev/child/uploadFileDev.js
  37. 0
      vue/src/router/module/dev/index.js
  38. 0
      vue/src/router/module/doc/index.js
  39. 18
      vue/src/router/module/example/child/component.js
  40. 0
      vue/src/router/module/example/child/cool.js
  41. 16
      vue/src/router/module/example/child/directive.js
  42. 36
      vue/src/router/module/example/child/globalMethod.js
  43. 0
      vue/src/router/module/example/child/icon.js
  44. 0
      vue/src/router/module/example/child/iframe.js
  45. 0
      vue/src/router/module/example/child/test.js
  46. 2
      vue/src/router/module/example/index.js
  47. 10
      vue/src/router/module/index.js
  48. 4
      vue/src/router/util.js
  49. 5
      vue/src/store/module/resource.js
  50. 4
      vue/src/util/browser.js
  51. 31
      vue/src/util/tree.js
  52. 2
      vue/src/view/_app/403.vue
  53. 2
      vue/src/view/_app/404.vue
  54. 2
      vue/src/view/_app/500.vue
  55. 0
      vue/src/view/_app/login/LoginForm.vue
  56. 0
      vue/src/view/_app/login/RegisterForm.vue
  57. 0
      vue/src/view/_app/login/SetAnimation.vue
  58. 0
      vue/src/view/_app/login/index.vue
  59. 4
      vue/src/view/_app/login/style.scss
  60. 0
      vue/src/view/_app/redirect.vue
  61. 0
      vue/src/view/_common/DetailPage/index.vue
  62. 2
      vue/src/view/_common/DetailPage/style.scss
  63. 0
      vue/src/view/_common/ExceptionPage/index.vue
  64. 0
      vue/src/view/_common/ExceptionPage/style.scss
  65. 2
      vue/src/view/_common/ListPage/autoAdaptHeightMixin.js
  66. 0
      vue/src/view/_common/ListPage/index.vue
  67. 0
      vue/src/view/_common/SkeletonPage/index.vue
  68. 0
      vue/src/view/_common/SkeletonPage/style.scss
  69. 0
      vue/src/view/admin/index/component/DailyFinishOrderStat.vue
  70. 0
      vue/src/view/admin/index/component/DailyProfitStat.vue
  71. 2
      vue/src/view/admin/index/component/PanelGroup/PanelGroupItem.vue
  72. 0
      vue/src/view/admin/index/component/PanelGroup/index.vue
  73. 0
      vue/src/view/admin/index/component/TotalProfitGoods.vue
  74. 0
      vue/src/view/admin/index/indexPage.vue
  75. 0
      vue/src/view/admin/message/manage/EditDialog.vue
  76. 2
      vue/src/view/admin/message/manage/indexPage.vue
  77. 0
      vue/src/view/admin/message/user/AutoHidden.vue
  78. 0
      vue/src/view/admin/message/user/MessageStream.vue
  79. 0
      vue/src/view/admin/message/user/indexPage.vue
  80. 0
      vue/src/view/admin/purchase/inbound/component/OrderSelector.vue
  81. 24
      vue/src/view/admin/purchase/inbound/detailPage.vue
  82. 0
      vue/src/view/admin/purchase/inbound/indexPage.vue
  83. 0
      vue/src/view/admin/purchase/order/component/CategorySelector.vue
  84. 0
      vue/src/view/admin/purchase/order/component/SupplierSelector.vue
  85. 24
      vue/src/view/admin/purchase/order/detailPage.vue
  86. 0
      vue/src/view/admin/purchase/order/indexPage.vue
  87. 0
      vue/src/view/admin/sell/order/component/CustomerSelector.vue
  88. 0
      vue/src/view/admin/sell/order/component/StockSelector.vue
  89. 24
      vue/src/view/admin/sell/order/detailPage.vue
  90. 0
      vue/src/view/admin/sell/order/indexPage.vue
  91. 0
      vue/src/view/admin/sell/outbound/component/OrderSelector.vue
  92. 0
      vue/src/view/admin/sell/outbound/component/StockSelector.vue
  93. 24
      vue/src/view/admin/sell/outbound/detailPage.vue
  94. 0
      vue/src/view/admin/sell/outbound/indexPage.vue
  95. 0
      vue/src/view/admin/stock/current/DetailDialog.vue
  96. 0
      vue/src/view/admin/stock/current/indexPage.vue
  97. 0
      vue/src/view/admin/system/category/component/Form.vue
  98. 0
      vue/src/view/admin/system/category/component/List.vue
  99. 0
      vue/src/view/admin/system/category/indexPage.vue
  100. 0
      vue/src/view/admin/system/customer/EditDialog.vue
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,11 +1,12 @@
<template> <template>
<transition name="el-message-fade" @after-leave="handleAfterLeave"> <transition name="el-message-fade" @after-leave="handleAfterLeave">
<div v-show="visible" <div
:class="messageClass" v-show="visible"
:style="positionStyle" :class="messageClass"
role="alert" :style="positionStyle"
@mouseenter="clearTimer" role="alert"
@mouseleave="startTimer" @mouseenter="clearTimer"
@mouseleave="startTimer"
> >
<i v-if="iconClass" :class="iconClass"/> <i v-if="iconClass" :class="iconClass"/>
<i v-else :class="typeClass"/> <i v-else :class="typeClass"/>
@ -44,6 +45,7 @@ export default {
center: false center: false
} }
}, },
computed: { computed: {
messageClass() { messageClass() {
return [ return [
@ -70,11 +72,13 @@ export default {
return `animation-duration: ${this.duration}ms;animation-play-state:running` return `animation-duration: ${this.duration}ms;animation-play-state:running`
} }
}, },
watch: { watch: {
closed(newVal) { closed(newVal) {
if (newVal) this.visible = false if (newVal) this.visible = false
} }
}, },
methods: { methods: {
handleAfterLeave() { handleAfterLeave() {
this.$destroy(true) this.$destroy(true)
@ -98,6 +102,7 @@ export default {
} }
} }
}, },
mounted() { mounted() {
this.startTimer() this.startTimer()
} }

@ -89,7 +89,7 @@
} }
.el-loading-mask { .el-loading-mask {
background: #fff; background: #ffffff;
color: $--color-primary; color: $--color-primary;
} }

@ -165,7 +165,7 @@ $page-header-offsetHeight: $page-header-line-height + #{$page-view-margin * 2};
a { a {
color: #337ab7; color: #337ab7;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: underline;
} }
} }

@ -2,7 +2,7 @@
<el-card :class="{collapsed}"> <el-card :class="{collapsed}">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<slot name="header">{{ header }}</slot> <slot name="header">{{ header }}</slot>
<i class="el-icon-arrow-up form-collapse-card-icon"/> <i class="el-icon-arrow-up collapse-card-icon"/>
</div> </div>
<slot/> <slot/>
</el-card> </el-card>
@ -10,7 +10,7 @@
<script> <script>
export default { export default {
name: "FormCollapseCard", name: "CollapseCard",
props: { props: {
header: String header: String
@ -35,14 +35,14 @@ export default {
</script> </script>
<style> <style>
.form-collapse-card-icon { .collapse-card-icon {
float: right; float: right;
font-weight: bold; font-weight: bold;
transition: transform .3s; transition: transform .3s;
cursor: pointer; cursor: pointer;
} }
.collapsed .form-collapse-card-icon { .collapsed .collapse-card-icon {
transform: rotate(180deg); transform: rotate(180deg);
} }

@ -16,7 +16,7 @@
</template> </template>
<script> <script>
import OrgTreeNode from "./OrgTreeNode" import OrgTreeNode from "./node"
export default { export default {
name: 'OrgTree', name: 'OrgTree',
@ -136,4 +136,4 @@ export default {
} }
</script> </script>
<style lang="scss" src="./tree.scss"></style> <style lang="scss" src="./style.scss"></style>

@ -58,11 +58,9 @@ export default {
return ( return (
<abstract-dialog <abstract-dialog
v-model={this.visible} v-model={this.visible}
directives={[{name: 'drag-dialog'}]}
class="tree-dialog" class="tree-dialog"
title="选择行政区域" title="选择行政区域"
loading={this.loading} loading={this.loading}
appendToBody={true}
v-on:close={this.closeDialog} v-on:close={this.closeDialog}
> >
<el-tree <el-tree

@ -9,13 +9,12 @@ export default {
props: { props: {
value: Boolean, value: Boolean,
title: String,
loading: {type: Boolean, default: true}, loading: {type: Boolean, default: true},
width: {type: String, default: '30%'} width: {type: String, default: '30%'}
}, },
render(h, context) { render(h, context) {
const {data, children, listeners, props: {value, title, loading, width}} = context const {data, children, listeners, props: {value, loading, width}} = context
const onClose = function () { const onClose = function () {
return listeners.close ? () => listeners.close(false) : () => ({}) return listeners.close ? () => listeners.close(false) : () => ({})
@ -26,13 +25,11 @@ export default {
v-drag-dialog v-drag-dialog
visible={value} visible={value}
custom-class="abstract-dialog" custom-class="abstract-dialog"
top={cssVariables['dialogTop']} top={cssVariables.dialogTop}
width={width} width={width}
on-close={onClose} on-close={onClose}
{...data} {...data}
> >
<slot slot="title" name="title">{title}</slot>
<div class="abstract-dialog-container"> <div class="abstract-dialog-container">
<LoadingMask show={loading}/> <LoadingMask show={loading}/>
<el-scrollbar> <el-scrollbar>
@ -42,8 +39,6 @@ export default {
<div style="margin-bottom: 17px"/> <div style="margin-bottom: 17px"/>
</el-scrollbar> </el-scrollbar>
</div> </div>
<slot slot="footer" name="footer"/>
</el-dialog> </el-dialog>
) )
} }

@ -7,10 +7,13 @@ export default {
functional: true, functional: true,
render(h, context) { render(h, context) {
const {data, children, scopedSlots} = context const {data, children} = context
if (!scopedSlots.empty) { if (!data.scopedSlots) {
scopedSlots.empty = () => <Empty/> data.scopedSlots = {}
}
if (!data.scopedSlots.empty) {
data.scopedSlots.empty = () => <Empty/>
} }
return ( return (
@ -22,13 +25,6 @@ export default {
{...data} {...data}
> >
{children} {children}
{
Object
.entries(scopedSlots)
.map(([name, slot]) => (
name !== 'default' && <slot slot={name}>{slot()}</slot>
))
}
</el-table> </el-table>
) )
} }

@ -21,9 +21,17 @@ export default {
props: { props: {
reference: Function, reference: Function,
//{refref使reference()[ref]dom, label}
data: {type: Array, default: () => []}, data: {type: Array, default: () => []},
//px
offsetTop: {type: Number, default: 15}, offsetTop: {type: Number, default: 15},
//px
bounds: {type: Number, default: 0}, bounds: {type: Number, default: 0},
//
getContainer: { getContainer: {
type: Function, type: Function,
default: () => document.querySelector('#app .page-main>.scroll-container') default: () => document.querySelector('#app .page-main>.scroll-container')
@ -33,33 +41,44 @@ export default {
data: () => ({cur: null}), data: () => ({cur: null}),
methods: { methods: {
//
close() { close() {
this.$el.remove() this.$el.remove()
this.$destroy() this.$destroy()
}, },
//ref
getCur(offsetTop, bounds) { getCur(offsetTop, bounds) {
const sections = [] const sections = []
const container = this.getContainer() const container = this.getContainer()
for (const {ref} of this.data) { for (const {ref} of this.data) {
const target = this.getDomFromRef(ref) const target = this.getDomFromRef(ref)
if (!target) continue if (!target) continue
const top = getTopDistance(target, container) const top = getTopDistance(target, container)
if (top <= offsetTop + bounds) { if (top <= offsetTop + bounds) {
sections.push({ref, top}) sections.push({ref, top})
} }
} }
//dom
if (sections.length) { if (sections.length) {
const max = sections.reduce((prev, curr) => (curr.top > prev.top ? curr : prev)) const max = sections.reduce((prev, curr) => (curr.top > prev.top ? curr : prev))
return max.ref return max.ref
} }
return null return null
}, },
getDomFromRef(ref) { getDomFromRef(ref) {
const refs = this.reference() const refs = this.reference()
if (!refs) return null if (!refs) return null
return refs[ref]['$el'] || refs[ref][0]['$el']
const target = Array.isArray(refs[ref]) ? refs[ref][0] : refs[ref]
//vuedom
return target.$el || target
}, },
click(ref) { click(ref) {
@ -88,14 +107,15 @@ export default {
}, },
mounted() { mounted() {
this.scroll = debounce(this.scroll)
this.scroll() this.scroll()
const container = this.getContainer() const container = this.getContainer()
this.handleScroll = debounce(this.scroll)
container.addEventListener('scroll', this.handleScroll) container.addEventListener('scroll', this.scroll)
this.$once('hook:beforeDestroy', () => { this.$once('hook:beforeDestroy', () => {
container.removeEventListener('scroll', this.handleScroll) container.removeEventListener('scroll', this.scroll)
}) })
} }
} }
@ -110,7 +130,7 @@ export default {
top: 200px; top: 200px;
min-width: 72px; min-width: 72px;
border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px;
background: #fff; background: #ffffff;
box-shadow: 0 2px 12px 0 rgba(166, 167, 173, 0.5); box-shadow: 0 2px 12px 0 rgba(166, 167, 173, 0.5);
z-index: 100; z-index: 100;
@ -119,7 +139,7 @@ export default {
height: 28px; height: 28px;
line-height: 28px; line-height: 28px;
text-align: center; text-align: center;
color: #7C7E85; color: #909399;
padding: 0 10px; padding: 0 10px;
font-size: 12px; font-size: 12px;
cursor: pointer; cursor: pointer;
@ -130,7 +150,7 @@ export default {
} }
&:not(:last-child) { &:not(:last-child) {
box-shadow: 0 1px 0 0 rgba(166, 167, 173, 0.1); border-bottom: 1px solid rgba(166, 167, 173, 0.1);
} }
} }
} }

@ -34,11 +34,9 @@ export default {
handleCollapse() { handleCollapse() {
this.collapse = !this.collapse this.collapse = !this.collapse
}, },
handleSearch() { handleSearch() {
this.$emit('search') this.$emit('search')
}, },
handleReset() { handleReset() {
if (!this.initialModel || !this.model) { if (!this.initialModel || !this.model) {
return return
@ -51,8 +49,8 @@ export default {
const vw = getElementInnerWidth(this.$el.parentNode) const vw = getElementInnerWidth(this.$el.parentNode)
if (vw < 768) return this.xs if (vw < 768) return this.xs
else if (vw < 998) return this.sm if (vw < 998) return this.sm
else if (vw < 1200) return this.md if (vw < 1200) return this.md
return this.lg return this.lg
}, },
@ -63,6 +61,7 @@ export default {
// //
this.num = num === 1 ? num : num - 1 this.num = num === 1 ? num : num - 1
this.showCollapse = this.num < this.$slots.default.length this.showCollapse = this.num < this.$slots.default.length
}, },

@ -38,6 +38,25 @@ export default {
}, },
methods: { methods: {
//
onClick({prop}) {
const formItem = this.getFormItem(prop)
formItem && formItem.$el.scrollIntoView({block: 'center'})
this.$refs.popover.doClose()
},
//el-form
getForm() {
return typeof this.form === 'function' ? this.form() : this.form
},
//propel-form-item
getFormItem(prop) {
const form = this.getForm()
return form && form.fields.find(i => i.prop === prop)
},
//el-formvalidate
onValidate(prop, success, msg) { onValidate(prop, success, msg) {
const alreadyIndex = this.error.findIndex(i => i.prop === prop) const alreadyIndex = this.error.findIndex(i => i.prop === prop)
if (alreadyIndex !== -1) { if (alreadyIndex !== -1) {
@ -46,31 +65,16 @@ export default {
} }
else { else {
if (success) return if (success) return
const formItem = this.findFormItem(prop) const formItem = this.getFormItem(prop)
this.error.push({prop, msg, label: formItem.label}) this.error.push({prop, msg, label: formItem.label})
} }
},
onClick({prop}) {
const formItem = this.findFormItem(prop)
formItem && formItem.$el.scrollIntoView({block: 'center'})
this.$refs.popover.doClose()
},
getFormRef() {
return typeof this.form === 'function' ? this.form() : this.form
},
findFormItem(prop) {
const form = this.getFormRef()
if (!form) return
return form.fields.find(i => i.prop === prop)
} }
}, },
mounted() { mounted() {
const form = this.getFormRef() const form = this.getForm()
if (!form) return if (!form) return
form.$on('validate', this.onValidate) form.$on('validate', this.onValidate)
this.$once('hook:beforeDestroy', () => { this.$once('hook:beforeDestroy', () => {
form.$off('validate', this.onValidate) form.$off('validate', this.onValidate)
@ -79,58 +83,4 @@ export default {
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
@import "~@/asset/style/variables.scss";
.form-validate-info {
&.el-popper {
padding: 0;
}
&-ref {
padding: 0 10px;
cursor: pointer;
}
&-title {
text-align: center;
padding: 5px 16px 4px;
border-bottom: 1px solid #f0f0f0;
}
&-content {
max-height: 300px;
overflow: overlay;
}
&-item {
padding: 8px 16px;
background-color: #ffffff;
border-bottom: 1px solid #f0f0f0;
cursor: pointer;
transition: background-color .3s;
&:hover {
background-color: #e6f7ff;
}
.el-icon-circle-close {
float: left;
margin-top: 4px;
margin-right: 12px;
padding-bottom: 22px;
}
&-label {
margin-top: 2px;
color: rgba(0, 0, 0, .45);
font-size: 12px;
}
}
&-ref,
&-item .el-icon-circle-close {
color: $--color-danger;
}
}
</style>

@ -0,0 +1,50 @@
@import "~@/asset/style/variables.scss";
.form-validate-info {
&.el-popper {
padding: 0;
}
&-ref {
padding: 0 10px;
cursor: pointer;
}
&-ref,
&-item .el-icon-circle-close {
color: $--color-danger;
}
&-title {
text-align: center;
padding: 5px 16px 4px;
}
&-content {
max-height: 300px;
overflow: auto;
}
&-item {
padding: 8px 16px;
border-top: 1px solid $border-color-light;
cursor: pointer;
&:hover {
background-color: rgba($--color-primary, .1);
}
.el-icon-circle-close {
float: left;
margin-top: 4px;
margin-right: 12px;
padding-bottom: 22px;
}
&-label {
margin-top: 2px;
color: #909399;
font-size: 12px;
}
}
}

@ -30,7 +30,7 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss">
.bottom-tip { .bottom-tip {
position: absolute; position: absolute;
width: 100%; width: 100%;

@ -14,7 +14,7 @@ const defaultOptions = {
prevBtnText: '上一步', prevBtnText: '上一步',
} }
const guide = function (start, steps, beforeExit) { const guide = function (steps, index, beforeExit) {
if (instance) instance.exit() if (instance) instance.exit()
else { else {
instance = new GuideConstructor({data: {options: defaultOptions}}) instance = new GuideConstructor({data: {options: defaultOptions}})
@ -25,15 +25,15 @@ const guide = function (start, steps, beforeExit) {
instance.steps = steps instance.steps = steps
instance.beforeExit = beforeExit instance.beforeExit = beforeExit
this.$nextTick(() => instance.start(start)) this.$nextTick(() => instance.start(index))
} }
guide.config = function (config) { guide.config = function (config) {
mergeObj(defaultOptions, config) mergeObj(defaultOptions, config)
} }
guide.exit = function () { guide.exit = function (force) {
instance && instance.exit() instance && instance.exit(force)
} }
export default guide export default guide

@ -1,25 +1,24 @@
<template> <template>
<div> <div>
<el-popover ref="popover" :value="showPopover" trigger="manual" width="300"> <el-popover ref="popover" :value="showPopover" trigger="manual">
<div v-html="step.content" style="padding: 10px"/> <div class="guide-popover-container">
<div v-html="step.content"/>
<div class="guide-popover-action">
<div class="action-close"> <div class="guide-popover-action">
<el-button v-if="hasDone" size="small" @click="exit"> <div class="action-close">
{{ step.doneBtnText }} <el-button size="mini" type="dashed" plain @click="exit">
</el-button> {{ hasDone ? step.doneBtnText : step.closeBtnText }}
<el-button v-else size="small" @click="exit"> </el-button>
{{ step.closeBtnText }} </div>
</el-button>
</div> <div class="action-step">
<el-button v-if="showPrevBtn" class="prev-btn" size="mini" plain @click="previous">
<div class="action-step"> {{ step.prevBtnText }}
<el-button v-if="showPrevBtn" class="prev-btn" size="small" @click="previous"> </el-button>
{{ step.prevBtnText }} <el-button v-if="showNextBtn" class="next-btn" size="mini" plain @click="next">
</el-button> {{ step.nextBtnText }}
<el-button v-if="showNextBtn" class="next-btn" size="small" @click="next"> </el-button>
{{ step.nextBtnText }} </div>
</el-button>
</div> </div>
</div> </div>
@ -35,10 +34,9 @@
<script> <script>
/** /**
* 由driver.js改造而来 * 由driver.js改造而来
* vue里交互型的导航不太行太多东西做不到换成引导手册吧
*/ */
import {debounce, isEmpty, deepClone} from "@/util" import {debounce, isEmpty, deepClone} from "@/util"
import {addHighlightClasses, getCalculatedPosition, inMainPage, jump, removeHighlightClasses} from "./utils" import {addHighlightClasses, getCalculatedPosition, removeHighlightClasses} from "./utils"
export default { export default {
name: "Guide", name: "Guide",
@ -73,9 +71,7 @@ export default {
return this.currentStep === this.steps.length - 1 return this.currentStep === this.steps.length - 1
}, },
step() { step() {
if (!this.isActive if (!this.isActive || this.steps.length <= 0 || !this.steps[this.currentStep]) {
|| this.steps.length <= 0
|| !this.steps[this.currentStep]) {
return {} return {}
} }
@ -89,7 +85,7 @@ export default {
watch: { watch: {
isActive(v) { isActive(v) {
v ? document.body.classList.add('overflow-hidden') : document.body.classList.remove('overflow-hidden') document.body.classList[v ? 'add' : 'remove']('overflow-hidden')
} }
}, },
@ -115,11 +111,10 @@ export default {
this.showOverlay = true this.showOverlay = true
this.showStage = true this.showStage = true
}, },
exit(force) {
exit() {
if (!this.isActive) return if (!this.isActive) return
if (this.beforeExit) { if (!force && this.beforeExit) {
const result = this.beforeExit(this.hasDone) const result = this.beforeExit(this.hasDone)
if (result && result.then) { if (result && result.then) {
result.then(this.$_clear) result.then(this.$_clear)
@ -138,13 +133,12 @@ export default {
if (this.step.onPrevious) { if (this.step.onPrevious) {
const result = this.step.onPrevious() const result = this.step.onPrevious()
if (result && result.then) { if (result && result.then) {
result.then(this.$_movePrevious) result.then(this.$_movePrevious, this.$_moveEnd)
} }
else result !== false && this.$_movePrevious() else result ? this.$_movePrevious() : this.$_moveEnd()
} }
else this.$_movePrevious() else this.$_movePrevious()
}, },
next() { next() {
if (!this.isActive || this.moving) return if (!this.isActive || this.moving) return
this.moving = true this.moving = true
@ -152,9 +146,9 @@ export default {
if (this.step.onNext) { if (this.step.onNext) {
const result = this.step.onNext() const result = this.step.onNext()
if (result && result.then) { if (result && result.then) {
result.then(this.$_moveNext) result.then(this.$_moveNext, this.$_moveEnd)
} }
else result !== false && this.$_moveNext() else result ? this.$_moveNext() : this.$_moveEnd()
} }
else this.$_moveNext() else this.$_moveNext()
}, },
@ -170,13 +164,15 @@ export default {
this.currentStep-- this.currentStep--
this.$_highlight() this.$_highlight()
}, },
$_moveNext() { $_moveNext() {
if (!this.isActive) return if (!this.isActive) return
this.currentStep++ this.currentStep++
this.$_highlight() this.$_highlight()
}, },
$_moveEnd() {
this.$refs.popover.updatePopper()
this.moving = false
},
$_clear() { $_clear() {
if (!this.isActive) return if (!this.isActive) return
this.isActive = false this.isActive = false
@ -185,11 +181,10 @@ export default {
this.currentStep = 0 this.currentStep = 0
this.steps = [] this.steps = []
this.beforeExit = null this.beforeExit = null
if (this.highlightedElement) removeHighlightClasses(this.highlightedElement) this.highlightedElement && removeHighlightClasses(this.highlightedElement)
this.highlightedElement = null this.highlightedElement = null
this.lastHighlightedElement = null this.lastHighlightedElement = null
}, },
$_highlight() { $_highlight() {
if (isEmpty(this.step.element)) throw new Error(`step${this.currentStep}中element为空`) if (isEmpty(this.step.element)) throw new Error(`step${this.currentStep}中element为空`)
@ -199,23 +194,22 @@ export default {
if (el === this.highlightedElement) return if (el === this.highlightedElement) return
if (this.highlightedElement) removeHighlightClasses(this.highlightedElement) this.highlightedElement && removeHighlightClasses(this.highlightedElement)
this.lastHighlightedElement = this.highlightedElement this.lastHighlightedElement = this.highlightedElement
this.highlightedElement = el this.highlightedElement = el
if (inMainPage(el)) jump(el) el.scrollIntoView({block: 'center'})
this.$_setStageStyle(getCalculatedPosition(el)) this.$_setStageStyle(getCalculatedPosition(el))
window.setTimeout(() => { window.setTimeout(() => {
this.$refs.popover.updatePopper() this.$_moveEnd()
this.moving = false this.step.onHighlighted && this.step.onHighlighted()
}, 300) }, 300)
addHighlightClasses(el) addHighlightClasses(el)
}, },
$_setStageStyle({top, left, right, bottom}) { $_setStageStyle({top, left, right, bottom}) {
const width = right - left const width = right - left
const height = bottom - top const height = bottom - top
@ -224,7 +218,7 @@ export default {
`height:${height}px;` + `height:${height}px;` +
`top:${top}px;` + `top:${top}px;` +
`left:${left}px;` + `left:${left}px;` +
`backgroundColor:${this.step.stageBackground}` `background-color:${this.step.stageBackground}`
} }
}, },

@ -16,23 +16,28 @@
will-change: unset !important; will-change: unset !important;
} }
.guide-popover-action { .guide-popover-container {
position: relative; min-width: 300px;
height: 100%;
width: 100%;
.action-close { .guide-popover-action {
display: inline-block; position: relative;
} height: 100%;
width: 100%;
margin-top: 20px;
.action-step { .action-close {
display: inline-block; display: inline-block;
right: 0; }
position: absolute;
.prev-btn { .action-step {
display: inline-block;
right: 0;
position: absolute; position: absolute;
right: 90px;
.prev-btn {
position: absolute;
right: 90px;
}
} }
} }
} }

@ -31,26 +31,6 @@ export function getStyleProperty(element, propertyName, prefixVendor = false) {
return propertyValue && propertyValue.toLowerCase ? propertyValue.toLowerCase() : propertyValue return propertyValue && propertyValue.toLowerCase ? propertyValue.toLowerCase() : propertyValue
} }
export function inMainPage(element) {
const appView = document.querySelector('.page-main')
if (!appView) throw new Error('路由页面未加载')
return appView.contains(element)
}
export function jump(element) {
if (!element.scrollIntoView) {
scrollManually(element)
return
}
try {
element.scrollIntoView({behavior: 'instant', block: 'center'})
}
catch (e) {
scrollManually(element)
}
}
export function removeHighlightClasses(element) { export function removeHighlightClasses(element) {
element.classList.remove(CLASS_HIGHLIGHTED_ELEMENT) element.classList.remove(CLASS_HIGHLIGHTED_ELEMENT)
element.classList.remove(CLASS_POSITION_RELATIVE) element.classList.remove(CLASS_POSITION_RELATIVE)
@ -124,11 +104,3 @@ function fixStackingContext(element) {
parentNode = parentNode.parentNode parentNode = parentNode.parentNode
} }
} }
function scrollManually(element) {
const elementRect = element.getBoundingClientRect()
const absoluteElementTop = elementRect.top + window.pageYOffset
const middle = absoluteElementTop - (window.innerHeight / 2)
window.scrollTo(0, middle)
}

@ -4,7 +4,7 @@ import {isEmpty} from "@/util"
let Constructor = Vue.extend(Main) let Constructor = Vue.extend(Main)
const PuzzleVerify = function ({left, top} = {}) { export default function ({left, top} = {}) {
const instance = new Constructor() const instance = new Constructor()
const position = getPosition({height: instance.height + 130, width: instance.width + 20, left, top}) const position = getPosition({height: instance.height + 130, width: instance.width + 20, left, top})
@ -42,5 +42,3 @@ function getPosition({height, width, left, top} = {}) {
function center(full, part) { function center(full, part) {
return Math.round((full - part) / 2) return Math.round((full - part) / 2)
} }
export default PuzzleVerify

@ -7,6 +7,7 @@ import {getters as appGetters, mutations as appMutations} from "@/layout/store/a
import NavMenu from "@/component/menu/NavMenu" import NavMenu from "@/component/menu/NavMenu"
import NavMenuItem from "@/component/menu/NavMenu/item" import NavMenuItem from "@/component/menu/NavMenu/item"
import {getActiveMenuByRoute} from "@/layout/util" import {getActiveMenuByRoute} from "@/layout/util"
import {isDom} from "@/util/browser"
export default { export default {
name: "HeadMenu", name: "HeadMenu",
@ -130,9 +131,11 @@ export default {
//mounted //mounted
setChildrenWidth() { setChildrenWidth() {
const ul = this.getMenuEl() const ul = this.getMenuEl()
if (!ul) return if (!isDom(ul)) return
const menuItemNodes = ul.children const menuItemNodes = ul.children
if (!menuItemNodes || menuItemNodes.length === 0) return if (!menuItemNodes || menuItemNodes.length === 0) return
//'' //''
this.overflowedIndicatorWidth = 50 this.overflowedIndicatorWidth = 50
this.menuItemSizes = Array.from(menuItemNodes).map(i => i.getBoundingClientRect().width) this.menuItemSizes = Array.from(menuItemNodes).map(i => i.getBoundingClientRect().width)
@ -163,7 +166,7 @@ export default {
}, },
createResizeObserver() { createResizeObserver() {
//observer //observer
if (!this.getMenuEl()) { if (!isDom(this.getMenuEl())) {
if (this.resizeObserver) { if (this.resizeObserver) {
this.resizeObserver.disconnect() this.resizeObserver.disconnect()
this.resizeObserver = null this.resizeObserver = null

@ -1,6 +1,5 @@
<script type="jsx"> <script type="jsx">
import {mapState} from 'vuex' import {mapState} from 'vuex'
import guideMixin from '@/mixin/guide'
import hamburgerMixin from '@/layout/mixin/hamburger' import hamburgerMixin from '@/layout/mixin/hamburger'
import Bell from "./component/Bell" import Bell from "./component/Bell"
import HeadMenu from "./component/HeadMenu" import HeadMenu from "./component/HeadMenu"
@ -14,10 +13,32 @@ import {refreshPage} from "@/util/route"
export default { export default {
name: 'navbar', name: 'navbar',
mixins: [guideMixin.navbar, hamburgerMixin], mixins: [hamburgerMixin],
components: {Bell, HeadMenu, Logo}, components: {Bell, HeadMenu, Logo},
data() {
return {
guideSteps: [
{
element: '.setting-btn.navbar-item',
content: '这是个性设置按钮,可以根据自己喜好进行一些设置',
},
{
element: '.navbar .el-dropdown.navbar-item',
content: '这是用户中心',
},
{
element: '.tags-view-container',
content: `<p>这是tab栏,可以右键tab页进行相关操作</p>
<p>ctrl + 可以进行tab页的左右切换</p>
<p>当tab过多时通过鼠标滚轮来滚动</p>
<p>双击可以关闭</p>`,
},
]
}
},
computed: { computed: {
...mapState('user', ['avatar', 'name', 'prepareLogout']), ...mapState('user', ['avatar', 'name', 'prepareLogout']),
@ -51,7 +72,7 @@ export default {
this.$route.path !== path && this.$router.push(path) this.$route.path !== path && this.$router.push(path)
break break
case 'guide': case 'guide':
this.$guide(0, this.guideSteps) this.$guide(this.guideSteps)
break break
case 'logout': case 'logout':
if (!this.prepareLogout) { if (!this.prepareLogout) {

@ -2,10 +2,10 @@ import {commonMethods} from "@/mixin/docTableMixin"
import AbstractForm from '@/component/abstract/Form' import AbstractForm from '@/component/abstract/Form'
import AbstractFormItem from "@/component/abstract/Form/item" import AbstractFormItem from "@/component/abstract/Form/item"
import AbstractTable from "@/component/abstract/Table" import AbstractTable from "@/component/abstract/Table"
import DetailPage from "@/view/app/common/DetailPage" import CollapseCard from '@/component/CollapseCard'
import DetailPage from "@/view/_common/DetailPage"
import DocHistory from '@/component/biz/doc/DocHistory' import DocHistory from '@/component/biz/doc/DocHistory'
import DocSteps from '@/component/biz/doc/DocSteps' import DocSteps from '@/component/biz/doc/DocSteps'
import FormCollapseCard from '@/component/form/CollapseCard'
import UploadFile from '@/component/UploadFile' import UploadFile from '@/component/UploadFile'
import {isEmpty, mergeObj} from '@/util' import {isEmpty, mergeObj} from '@/util'
import {auth} from "@/util/auth" import {auth} from "@/util/auth"
@ -18,10 +18,10 @@ export default {
AbstractForm, AbstractForm,
AbstractFormItem, AbstractFormItem,
AbstractTable, AbstractTable,
CollapseCard,
DetailPage, DetailPage,
DocHistory, DocHistory,
DocSteps, DocSteps,
FormCollapseCard,
UploadFile UploadFile
}, },

@ -1,6 +1,6 @@
import tableMixin from '@/mixin/tablePageMixin' import tableMixin from '@/mixin/tablePageMixin'
import LinerProgress from '@/component/LinerProgress' import LinerProgress from '@/component/LinerProgress'
import ListPage from '@/view/app/common/ListPage' import ListPage from '@/view/_common/ListPage'
import {isEmpty} from "@/util" import {isEmpty} from "@/util"
import {elConfirm, elError, elSuccess} from "@/util/message" import {elConfirm, elError, elSuccess} from "@/util/message"
import {auth} from "@/util/auth" import {auth} from "@/util/auth"

@ -1,60 +0,0 @@
//删除所有url参数
function delAllUrlParam() {
let paramStartIndex = location.href.indexOf('?')
if (paramStartIndex > -1) {
const href = location.href.substring(0, paramStartIndex)
history.replaceState(null, null, [...href].join(''))
}
}
//将引导步骤中函数的this绑定为组件实例
function transformGuideSteps(instance, steps) {
steps.forEach(step => {
Object.keys(step).forEach(key => {
if (typeof step[key] === 'function') {
step[key] = step[key].bind(instance)
}
})
})
}
export default {
methods: {
$_prepareGuide(params) {
if (!['navbar', 'sidebar'].includes(this.$options.name)) return
if ('guide' in params) {
delAllUrlParam()
for (const key of ['navbar', 'sidebar']) {
if (params[key] && this.$options.name === key) {
return this.$guide(params.guide, this.guideSteps)
}
}
}
}
},
computed: {
routeParams() {
return this.$route.params
}
},
watch: {
routeParams(v) {
this.$_prepareGuide(v)
}
},
created() {
transformGuideSteps(this, this.guideSteps)
},
activated() {
const params = this.$route.params
if (!params.navbar && !params.sidebar && 'guide' in params) {
delAllUrlParam()
this.$guide(params.guide, this.guideSteps)
}
}
}

@ -1,23 +0,0 @@
/*
* 导航栏引导步骤
* */
const steps = [
{
element: '.setting-btn.navbar-item',
content: '这是个性设置按钮,可以根据自己喜好进行一些设置',
},
{
element: '.navbar .el-dropdown.navbar-item',
content: '这是用户中心',
},
{
element: '.tags-view-container',
content: `<p>这是tab栏,可以右键tab页进行相关操作</p>
<p>ctrl + 可以进行tab页的左右切换</p>
<p>当tab过多时通过鼠标滚轮来滚动</p>
<p>双击可以关闭</p>`,
},
]
export default steps

@ -1,18 +0,0 @@
const modulesFiles = require.context('./data', false, /\.js$/)
import baseMixin from './base'
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = {
data() {
return {
guideSteps: value.default
}
},
...baseMixin
}
return modules
}, {})
export default modules

@ -1,9 +1,9 @@
import Layout from "@/layout/index" import Layout from "@/layout/index"
import Redirect from "@/view/app/redirect" import Redirect from "@/view/_app/redirect"
import Login from "@/view/app/login/index" import Login from "@/view/_app/login/index"
import Page403 from "@/view/app/403" import Page403 from "@/view/_app/403"
import Page404 from "@/view/app/404" import Page404 from "@/view/_app/404"
import Page500 from "@/view/app/500" import Page500 from "@/view/_app/500"
import routes from './module' import routes from './module'
import {deepClone} from "@/util" import {deepClone} from "@/util"

@ -1,16 +1,16 @@
//路由表:系统页面 //路由表:默认页面
const router = [ const router = [
{ {
path: 'index', path: 'index',
component: 'index/', component: 'admin/index/',
name: 'index', name: 'index',
meta: {title: '首页', affix: true, icon: 'svg-home', noAuth: true, pageHeader: false, sort: 0} meta: {title: '首页', affix: true, icon: 'svg-home', noAuth: true, pageHeader: false, sort: 0}
}, },
{ {
path: 'user', path: 'user',
name: 'userCenter', name: 'userCenter',
component: 'userCenter/', component: 'admin/userCenter/',
meta: {title: '个人中心', noCache: true, icon: 'svg-user', noAuth: true, pageHeader: false, hidden: true}, meta: {title: '个人中心', noCache: true, icon: 'svg-user', noAuth: true, pageHeader: false, hidden: true},
} }
] ]

@ -7,13 +7,13 @@ const router = {
{ {
path: 'manage', path: 'manage',
name: 'messageManagement', name: 'messageManagement',
component: 'message/manage/', component: 'admin/message/manage/',
meta: {title: '消息管理'} meta: {title: '消息管理'}
}, },
{ {
path: 'user', path: 'user',
name: 'userMessage', name: 'userMessage',
component: 'message/user/', component: 'admin/message/user/',
meta: {title: '个人消息', noAuth: true, noCache: true} meta: {title: '个人消息', noAuth: true, noCache: true}
} }
] ]

@ -7,12 +7,12 @@ const router = {
{ {
path: 'order', path: 'order',
name: 'purchaseOrder', name: 'purchaseOrder',
component: 'purchase/order/', component: 'admin/purchase/order/',
meta: {title: '采购订单'} meta: {title: '采购订单'}
}, },
{ {
path: 'order/detail/:type(see|add|edit)/:id?', path: 'order/detail/:type(see|add|edit)/:id?',
component: 'purchase/order/detail', component: 'admin/purchase/order/detail',
meta: { meta: {
title: '采购订单详情页', title: '采购订单详情页',
hidden: true, hidden: true,
@ -30,18 +30,18 @@ const router = {
}, },
activeMenu: '/purchase/order', activeMenu: '/purchase/order',
usePathKey: true, usePathKey: true,
commonModule: '@/view/purchase/order/detail' commonModule: '@/view/admin/purchase/order/detail'
} }
}, },
{ {
path: 'inbound', path: 'inbound',
name: 'purchaseInbound', name: 'purchaseInbound',
component: 'purchase/inbound/', component: 'admin/purchase/inbound/',
meta: {title: '采购入库'} meta: {title: '采购入库'}
}, },
{ {
path: 'inbound/detail/:type(see|add|edit)/:id?', path: 'inbound/detail/:type(see|add|edit)/:id?',
component: 'purchase/inbound/detail', component: 'admin/purchase/inbound/detail',
meta: { meta: {
title: '采购入库详情页', title: '采购入库详情页',
hidden: true, hidden: true,
@ -59,7 +59,7 @@ const router = {
}, },
activeMenu: '/purchase/inbound', activeMenu: '/purchase/inbound',
usePathKey: true, usePathKey: true,
commonModule: '@/view/purchase/inbound/detail' commonModule: '@/view/admin/purchase/inbound/detail'
} }
} }
] ]

@ -7,12 +7,12 @@ const router = {
{ {
path: 'order', path: 'order',
name: 'sellOrder', name: 'sellOrder',
component: 'sell/order/', component: 'admin/sell/order/',
meta: {title: '销售订单'} meta: {title: '销售订单'}
}, },
{ {
path: 'order/detail/:type(see|add|edit)/:id?', path: 'order/detail/:type(see|add|edit)/:id?',
component: 'sell/order/detail', component: 'admin/sell/order/detail',
meta: { meta: {
title: '销售订单详情页', title: '销售订单详情页',
hidden: true, hidden: true,
@ -30,18 +30,18 @@ const router = {
}, },
activeMenu: '/sell/order', activeMenu: '/sell/order',
usePathKey: true, usePathKey: true,
commonModule: '@/view/sell/order/detail' commonModule: '@/view/admin/sell/order/detail'
} }
}, },
{ {
path: 'outbound', path: 'outbound',
name: 'sellOutbound', name: 'sellOutbound',
component: 'sell/outbound/', component: 'admin/sell/outbound/',
meta: {title: '销售出库'} meta: {title: '销售出库'}
}, },
{ {
path: 'outbound/detail/:type(see|add|edit)/:id?', path: 'outbound/detail/:type(see|add|edit)/:id?',
component: 'sell/outbound/detail', component: 'admin/sell/outbound/detail',
meta: { meta: {
title: '销售出库详情页', title: '销售出库详情页',
hidden: true, hidden: true,
@ -59,7 +59,7 @@ const router = {
}, },
activeMenu: '/sell/outbound', activeMenu: '/sell/outbound',
usePathKey: true, usePathKey: true,
commonModule: '@/view/sell/outbound/detail' commonModule: '@/view/admin/sell/outbound/detail'
} }
} }
] ]

@ -7,7 +7,7 @@ const router = {
{ {
path: 'current', path: 'current',
name: 'currentStock', name: 'currentStock',
component: 'stock/current/', component: 'admin/stock/current/',
meta: {title: '当前库存'} meta: {title: '当前库存'}
} }
] ]

@ -7,43 +7,43 @@ const router = {
{ {
path: 'department', path: 'department',
name: 'departmentManagement', name: 'departmentManagement',
component: 'system/department/', component: 'admin/system/department/',
meta: {title: '部门管理'} meta: {title: '部门管理'}
}, },
{ {
path: 'menu', path: 'menu',
name: 'menuManagement', name: 'menuManagement',
component: 'system/menu/', component: 'admin/system/menu/',
meta: {title: '菜单管理', noCache: true} meta: {title: '菜单管理', noCache: true}
}, },
{ {
path: 'role', path: 'role',
name: 'roleManagement', name: 'roleManagement',
component: 'system/role/', component: 'admin/system/role/',
meta: {title: '角色管理'} meta: {title: '角色管理'}
}, },
{ {
path: 'user', path: 'user',
name: 'userManagement', name: 'userManagement',
component: 'system/user/', component: 'admin/system/user/',
meta: {title: '用户管理'} meta: {title: '用户管理'}
}, },
{ {
path: 'category', path: 'category',
name: 'categorySetting', name: 'categorySetting',
component: 'system/category/', component: 'admin/system/category/',
meta: {title: '商品分类'} meta: {title: '商品分类'}
}, },
{ {
path: 'customer', path: 'customer',
name: 'customerManagement', name: 'customerManagement',
component: 'system/customer/', component: 'admin/system/customer/',
meta: {title: '客户管理'} meta: {title: '客户管理'}
}, },
{ {
path: 'supplier', path: 'supplier',
name: 'supplierManagement', name: 'supplierManagement',
component: 'system/supplier/', component: 'admin/system/supplier/',
meta: {title: '供应商管理'} meta: {title: '供应商管理'}
} }
] ]

@ -1,4 +1,4 @@
/*顶级菜单:默认*/ /*顶级菜单:后台管理*/
import {context2array} from '@/router/util' import {context2array} from '@/router/util'

@ -3,32 +3,22 @@ export default {
meta: {title: '组件', icon: 'el-icon-s-grid'}, meta: {title: '组件', icon: 'el-icon-s-grid'},
children: [ children: [
{ {
path: 'uploadExample', path: 'upload',
component: 'example/component/upload', component: 'example/component/upload',
meta: {title: '上传文件'} meta: {title: '上传文件'}
}, },
{ {
path: 'skeletonExample', path: 'skeleton',
component: 'example/component/skeleton', component: 'example/component/skeleton',
meta: {title: '骨架屏'} meta: {title: '骨架屏'}
}, },
{ {
path: 'rippleExample', path: 'regionSelector',
component: 'example/component/ripple',
meta: {title: '波纹'}
},
{
path: 'signatureExample',
component: 'example/component/signature',
meta: {title: '手写签名'}
},
{
path: 'regionSelectorExample',
component: 'example/component/regionSelector', component: 'example/component/regionSelector',
meta: {title: '行政区划选择'} meta: {title: '行政区划选择'}
}, },
{ {
path: 'treeSelectExample', path: 'treeSelect',
component: 'example/component/treeSelect', component: 'example/component/treeSelect',
meta: {title: '树选择'} meta: {title: '树选择'}
} }

@ -0,0 +1,16 @@
export default {
path: 'directive',
meta: {title: '全局指令', icon: 'el-icon-s-grid'},
children: [
{
path: 'dragDialog',
component: 'example/directive/dragDialog',
meta: {title: '可拖拽dialog'}
},
{
path: 'ripple',
component: 'example/directive/ripple',
meta: {title: '波纹'}
}
]
}

@ -0,0 +1,36 @@
export default {
path: 'global',
meta: {title: '全局方法', icon: 'el-icon-s-opportunity'},
children: [
{
path: 'message',
component: 'example/globalMethod/message',
meta: {title: '消息提示'}
},
{
path: 'bottomTip',
component: 'example/globalMethod/bottomTip',
meta: {title: '底部消息提示'}
},
{
path: 'guide',
component: 'example/globalMethod/guide',
meta: {title: '导航'}
},
{
path: 'imageViewer',
component: 'example/globalMethod/imageViewer',
meta: {title: '图片预览'}
},
{
path: 'signature',
component: 'example/globalMethod/signature',
meta: {title: '手写签名'}
},
{
path: 'verify',
component: 'example/globalMethod/verify',
meta: {title: '拼图验证'}
}
]
}

@ -7,6 +7,6 @@ const files = require.context('./child', false, /\.js$/)
export default { export default {
path: '/example', path: '/example',
component: 'Layout', component: 'Layout',
meta: {title: '演示用例', icon: 'svg-show', noAuth: true, noCache: true}, meta: {title: '演示用例', icon: 'svg-show', noAuth: true, noCache: true, sort: 1},
children: context2array(files) children: context2array(files)
} }

@ -1,6 +1,6 @@
import defaultRoot from './defaultRoot' import admin from './admin'
import exampleRoot from './exampleRoot' import example from './example'
import devRoot from './devRoot' import dev from './dev'
import docRoot from './docRoot' import doc from './doc'
export default [defaultRoot, exampleRoot, devRoot, docRoot] export default [admin, example, dev, doc]

@ -1,6 +1,6 @@
import Layout from '@/layout' import Layout from '@/layout'
import SkeletonPage from '@/view/app/common/SkeletonPage' import SkeletonPage from '@/view/_common/SkeletonPage'
import Page500 from '@/view/app/500' import Page500 from '@/view/_app/500'
import {isEmpty} from "@/util" import {isEmpty} from "@/util"
import {isExternal, isString} from "@/util/validate" import {isExternal, isString} from "@/util/validate"

@ -22,6 +22,8 @@ const state = {
const mutations = { const mutations = {
resource(state, {data, admin}) { resource(state, {data, admin}) {
data = deepClone(data)
state.resourceMap = generateResourceMap(data) state.resourceMap = generateResourceMap(data)
//如果不是admin用户,那么过滤admin类型的权限 //如果不是admin用户,那么过滤admin类型的权限
@ -48,9 +50,10 @@ const actions = {
.then(({data}) => { .then(({data}) => {
commit('resource', {data: data || [], admin}) commit('resource', {data: data || [], admin})
//动态添加路由,这里不需要进行权限过滤
const routes = transformOriginRouteData(data) const routes = transformOriginRouteData(data)
metaExtend(routes) metaExtend(routes)
//动态添加路由,这里不需要进行权限过滤
//可能存在多次调用的情况,所以仅在第一次调用时添加进vue-router //可能存在多次调用的情况,所以仅在第一次调用时添加进vue-router
!state.init && addDynamicRoutes(routes) !state.init && addDynamicRoutes(routes)

@ -13,13 +13,13 @@ export function isMobile() {
} }
/** /**
* 判断是否为dom元素 * 判断是否为dom元素是则返回true
* *
* @param obj * @param obj
* @return {boolean} * @return {boolean}
*/ */
export function isDom(obj) { export function isDom(obj) {
return !!obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string' return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string'
} }
/** /**

@ -1,23 +1,38 @@
import {deepClone} from "@/util" import {deepClone} from "@/util"
import {createWorker} from '@/util/worker' import {createWorker} from '@/util/worker'
const DEFAULT_PROPS = {id: 'id', pid: 'pid', children: 'children', leafHasChildren: true} const DEFAULT_PROPS = {
//节点的id属性名称
id: 'id',
//节点的父级id属性名称
pid: 'pid',
//节点的子级节点属性名称
children: 'children',
//根节点的判定方法,传入函数时参数为节点对象
rootPredicate: 0,
//叶子节点是否能有children属性
leafHasChildren: false
}
/** /**
* 列表转树形结构 * 列表转树形结构
* *
* @param list {array} * @param list {array}
* @param rootSign {number|String|Function} 根节点的判定方法 * @param props 树的配置项{id, pid, children, rootPredicate, leafHasChildren}
* @param props 树的配置项{id, pid, children, leafHasChildren}
* @return {array} * @return {array}
*/ */
export function createTree(list, rootSign = 0, props = {}) { export function createTree(list, props = {}) {
if (!list || list.length <= 0) return [] if (!list || list.length <= 0) return []
const { const {
id = DEFAULT_PROPS.id, id = DEFAULT_PROPS.id,
pid = DEFAULT_PROPS.pid, pid = DEFAULT_PROPS.pid,
children = DEFAULT_PROPS.children, children = DEFAULT_PROPS.children,
rootPredicate = DEFAULT_PROPS.rootPredicate,
leafHasChildren = DEFAULT_PROPS.leafHasChildren leafHasChildren = DEFAULT_PROPS.leafHasChildren
} = props } = props
@ -29,9 +44,9 @@ export function createTree(list, rootSign = 0, props = {}) {
}) })
const predicate = (() => { const predicate = (() => {
return typeof rootSign === 'function' return typeof rootPredicate === 'function'
? rootSign ? rootPredicate
: key => key === rootSign : key => key === rootPredicate
})() })()
return list.filter(node => { return list.filter(node => {
@ -105,7 +120,7 @@ export function createLimitTreeByMap(fullMap, limit) {
findParent(node) findParent(node)
} }
const result = createTree(Object.values(resultNodes), '0') const result = createTree(Object.values(resultNodes), {rootPredicate: '0'})
result.forEach(i => calc(i)) result.forEach(i => calc(i))

@ -1,5 +1,5 @@
<script type="text/jsx"> <script type="text/jsx">
import ExceptionPage from '@/view/app/common/ExceptionPage' import ExceptionPage from '@/view/_common/ExceptionPage'
export default { export default {
name: 'Page403', name: 'Page403',

@ -1,5 +1,5 @@
<script type="text/jsx"> <script type="text/jsx">
import ExceptionPage from '@/view/app/common/ExceptionPage' import ExceptionPage from '@/view/_common/ExceptionPage'
export default { export default {
name: 'Page404', name: 'Page404',

@ -1,5 +1,5 @@
<script type="text/jsx"> <script type="text/jsx">
import ExceptionPage from '@/view/app/common/ExceptionPage' import ExceptionPage from '@/view/_common/ExceptionPage'
export default { export default {
name: 'Page500', name: 'Page500',

@ -1,9 +1,9 @@
@import "~@/asset/style/variables.scss"; @import "~@/asset/style/variables.scss";
$bg: #283443; $bg: #283443;
$light_gray: #fff; $light_gray: #ffffff;
$dark_gray: #889aa4; $dark_gray: #889aa4;
$cursor: #fff; $cursor: #ffffff;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) { @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input { .login-container .el-input input {

@ -8,7 +8,7 @@
&-header { &-header {
margin: -#{$page-view-margin} -#{$page-view-margin} 0 -#{$page-view-margin}; margin: -#{$page-view-margin} -#{$page-view-margin} 0 -#{$page-view-margin};
padding: 16px 32px 0 32px; padding: 16px 32px 0 32px;
background: #fff; background: #ffffff;
border-bottom: 1px solid $border-color-light; border-bottom: 1px solid $border-color-light;
> .el-page-header { > .el-page-header {

@ -17,7 +17,7 @@ export default {
methods: { methods: {
//设置表格距离视窗底部的理想距离(分页高度 + el-card的1px边距 + el-card padding + 页面margin) //设置表格距离视窗底部的理想距离(分页高度 + el-card的1px边距 + el-card padding + 页面margin)
calcDesiredDistance() { calcDesiredDistance() {
const pageViewMargin = parseFloat(cssVariables['pageViewMargin']) const pageViewMargin = parseFloat(cssVariables.pageViewMargin)
const paginationHeight = this.$el.querySelector('.table-container > .el-pagination') ? 50 : 0 const paginationHeight = this.$el.querySelector('.table-container > .el-pagination') ? 50 : 0
this.desiredDistance = paginationHeight + 1 + 20 + pageViewMargin this.desiredDistance = paginationHeight + 1 + 20 + pageViewMargin
}, },

@ -40,7 +40,7 @@ export default {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
color: #666; color: #666;
background: #fff; background: #ffffff;
border-radius: 4px; border-radius: 4px;
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);

@ -44,7 +44,7 @@
<script> <script>
import tableMixin from '@/mixin/tablePageMixin' import tableMixin from '@/mixin/tablePageMixin'
import EditDialog from './EditDialog' import EditDialog from './EditDialog'
import ListPage from '@/view/app/common/ListPage' import ListPage from '@/view/_common/ListPage'
import {search, add, update, del} from "@/api/message/manage" import {search, add, update, del} from "@/api/message/manage"
import {isEmpty} from '@/util' import {isEmpty} from '@/util'
import {wic} from "@/util/auth" import {wic} from "@/util/auth"

@ -10,20 +10,20 @@
@close="close" @close="close"
> >
<abstract-form :model="form" :rules="rules"> <abstract-form :model="form" :rules="rules">
<form-collapse-card ref="progress" header="流程进度"> <collapse-card ref="progress" header="流程进度">
<doc-steps :status="form.status" :type="type"/> <doc-steps :status="form.status" :type="type"/>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="base" header="基础信息"> <collapse-card ref="base" header="基础信息">
<abstract-form-item label="采购订单" prop="pid"> <abstract-form-item label="采购订单" prop="pid">
<el-input v-if="canSave" :value="form.pid" readonly> <el-input v-if="canSave" :value="form.pid" readonly>
<el-button slot="append" @click="parentDialog=true">选择</el-button> <el-button slot="append" @click="parentDialog=true">选择</el-button>
</el-input> </el-input>
<template v-else>{{ form.pid }}</template> <template v-else>{{ form.pid }}</template>
</abstract-form-item> </abstract-form-item>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="goods" header="入库商品"> <collapse-card ref="goods" header="入库商品">
<abstract-table :data="form.data" :highlight-current-row="false"> <abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/> <el-table-column align="center" label="商 品" prop="cname"/>
@ -41,18 +41,18 @@
</template> </template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="attachment" header="附件"> <collapse-card ref="attachment" header="附件">
<upload-file <upload-file
:file-list="form.imageList" :file-list="form.imageList"
:disabled="!canSave" :disabled="!canSave"
@remove="removeUpload" @remove="removeUpload"
@success="uploadSuccess" @success="uploadSuccess"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="remark" header="备注"> <collapse-card ref="remark" header="备注">
<el-input <el-input
v-model="form.remark" v-model="form.remark"
:rows="4" :rows="4"
@ -61,11 +61,11 @@
show-word-limit show-word-limit
type="textarea" type="textarea"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="history" header="单据历史"> <collapse-card ref="history" header="单据历史">
<doc-history :id="form.id"/> <doc-history :id="form.id"/>
</form-collapse-card> </collapse-card>
</abstract-form> </abstract-form>
<order-selector v-model="parentDialog" @select="selectParent"/> <order-selector v-model="parentDialog" @select="selectParent"/>

@ -10,20 +10,20 @@
@close="close" @close="close"
> >
<abstract-form :model="form" :rules="rules"> <abstract-form :model="form" :rules="rules">
<form-collapse-card ref="progress" header="流程进度"> <collapse-card ref="progress" header="流程进度">
<doc-steps :status="form.status" :finish="form.finish" :type="type"/> <doc-steps :status="form.status" :finish="form.finish" :type="type"/>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="base" header="基础信息"> <collapse-card ref="base" header="基础信息">
<abstract-form-item label="供应商" prop="sname"> <abstract-form-item label="供应商" prop="sname">
<el-input v-if="canSave" :value="form.sname" readonly> <el-input v-if="canSave" :value="form.sname" readonly>
<el-button slot="append" @click="supplierDialog=true">选择</el-button> <el-button slot="append" @click="supplierDialog=true">选择</el-button>
</el-input> </el-input>
<template v-else>{{ form.sname }}</template> <template v-else>{{ form.sname }}</template>
</abstract-form-item> </abstract-form-item>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="goods" header="采购商品"> <collapse-card ref="goods" header="采购商品">
<abstract-table :data="form.data" :highlight-current-row="false"> <abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品"> <el-table-column align="center" label="商 品">
@ -87,18 +87,18 @@
</el-button> </el-button>
</div> </div>
</abstract-table> </abstract-table>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="attachment" header="附件"> <collapse-card ref="attachment" header="附件">
<upload-file <upload-file
:file-list="form.imageList" :file-list="form.imageList"
:disabled="!canSave" :disabled="!canSave"
@remove="removeUpload" @remove="removeUpload"
@success="uploadSuccess" @success="uploadSuccess"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="remark" header="备注"> <collapse-card ref="remark" header="备注">
<el-input <el-input
v-model="form.remark" v-model="form.remark"
:rows="4" :rows="4"
@ -107,11 +107,11 @@
show-word-limit show-word-limit
type="textarea" type="textarea"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="history" header="单据历史"> <collapse-card ref="history" header="单据历史">
<doc-history :id="form.id"/> <doc-history :id="form.id"/>
</form-collapse-card> </collapse-card>
</abstract-form> </abstract-form>
<supplier-selector v-model="supplierDialog" @select="selectSupplier"/> <supplier-selector v-model="supplierDialog" @select="selectSupplier"/>

@ -10,20 +10,20 @@
@close="close" @close="close"
> >
<abstract-form :model="form" :rules="rules"> <abstract-form :model="form" :rules="rules">
<form-collapse-card ref="progress" header="流程进度"> <collapse-card ref="progress" header="流程进度">
<doc-steps :status="form.status" :finish="form.finish" :type="type"/> <doc-steps :status="form.status" :finish="form.finish" :type="type"/>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="base" header="基础信息"> <collapse-card ref="base" header="基础信息">
<abstract-form-item label="客 户" prop="customerName"> <abstract-form-item label="客 户" prop="customerName">
<el-input v-if="canSave" :value="form.customerName" readonly> <el-input v-if="canSave" :value="form.customerName" readonly>
<el-button slot="append" @click="customerDialog=true">选择</el-button> <el-button slot="append" @click="customerDialog=true">选择</el-button>
</el-input> </el-input>
<template v-else>{{ form.customerName }}</template> <template v-else>{{ form.customerName }}</template>
</abstract-form-item> </abstract-form-item>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="goods" header="销售商品"> <collapse-card ref="goods" header="销售商品">
<abstract-table :data="form.data" :highlight-current-row="false"> <abstract-table :data="form.data" :highlight-current-row="false">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商品" prop="cname"/> <el-table-column align="center" label="商品" prop="cname"/>
@ -70,18 +70,18 @@
</el-button> </el-button>
</div> </div>
</abstract-table> </abstract-table>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="attachment" header="附件"> <collapse-card ref="attachment" header="附件">
<upload-file <upload-file
:file-list="form.imageList" :file-list="form.imageList"
:disabled="!canSave" :disabled="!canSave"
@remove="removeUpload" @remove="removeUpload"
@success="uploadSuccess" @success="uploadSuccess"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="remark" header="备注"> <collapse-card ref="remark" header="备注">
<el-input <el-input
v-model="form.remark" v-model="form.remark"
:rows="4" :rows="4"
@ -90,11 +90,11 @@
show-word-limit show-word-limit
type="textarea" type="textarea"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="history" header="单据历史"> <collapse-card ref="history" header="单据历史">
<doc-history :id="form.id"/> <doc-history :id="form.id"/>
</form-collapse-card> </collapse-card>
</abstract-form> </abstract-form>
<stock-selector v-model="stockDialog" @select="selectStock"/> <stock-selector v-model="stockDialog" @select="selectStock"/>

@ -10,20 +10,20 @@
@close="close" @close="close"
> >
<abstract-form :model="form" :rules="rules"> <abstract-form :model="form" :rules="rules">
<form-collapse-card ref="progress" header="流程进度"> <collapse-card ref="progress" header="流程进度">
<doc-steps :status="form.status" :type="type"/> <doc-steps :status="form.status" :type="type"/>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="base" header="基础信息"> <collapse-card ref="base" header="基础信息">
<abstract-form-item label="销售订单" prop="pid"> <abstract-form-item label="销售订单" prop="pid">
<el-input v-if="canSave" :value="form.pid" readonly> <el-input v-if="canSave" :value="form.pid" readonly>
<el-button slot="append" @click="parentDialog=true">选择</el-button> <el-button slot="append" @click="parentDialog=true">选择</el-button>
</el-input> </el-input>
<template v-else>{{ form.pid }}</template> <template v-else>{{ form.pid }}</template>
</abstract-form-item> </abstract-form-item>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="goods" header="出库商品"> <collapse-card ref="goods" header="出库商品">
<abstract-table :data="displayTableData" :highlight-current-row="false"> <abstract-table :data="displayTableData" :highlight-current-row="false">
<el-table-column align="center" type="expand"> <el-table-column align="center" type="expand">
<el-table slot-scope="{row}" :data="row.data" border show-summary <el-table slot-scope="{row}" :data="row.data" border show-summary
@ -56,18 +56,18 @@
<el-table-column align="center" label="出库数量" prop="num" width="150"/> <el-table-column align="center" label="出库数量" prop="num" width="150"/>
<el-table-column align="center" label="订单剩余未出库数量" prop="remainNum" width="250"/> <el-table-column align="center" label="订单剩余未出库数量" prop="remainNum" width="250"/>
</abstract-table> </abstract-table>
</form-collapse-card> </collapse-card>
<form-collapse-card ref="attachment" header="附件"> <collapse-card ref="attachment" header="附件">
<upload-file <upload-file
:file-list="form.imageList" :file-list="form.imageList"
:disabled="!canSave" :disabled="!canSave"
@remove="removeUpload" @remove="removeUpload"
@success="uploadSuccess" @success="uploadSuccess"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="remark" header="备注"> <collapse-card ref="remark" header="备注">
<el-input <el-input
v-model="form.remark" v-model="form.remark"
:rows="4" :rows="4"
@ -76,11 +76,11 @@
show-word-limit show-word-limit
type="textarea" type="textarea"
/> />
</form-collapse-card> </collapse-card>
<form-collapse-card ref="history" header="单据历史"> <collapse-card ref="history" header="单据历史">
<doc-history :id="form.id"/> <doc-history :id="form.id"/>
</form-collapse-card> </collapse-card>
</abstract-form> </abstract-form>
<order-selector v-model="parentDialog" @select="selectParent"/> <order-selector v-model="parentDialog" @select="selectParent"/>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save