单据样式修改

master
toesbieya 6 years ago
parent 2a53db1324
commit f82f538636
  1. 8
      vue/src/assets/styles/index.scss
  2. 3
      vue/src/bizComponents/CategoryTree/index.vue
  3. 3
      vue/src/bizComponents/DocumentHistory/index.vue
  4. 3
      vue/src/bizComponents/DocumentSteps/index.vue
  5. 4
      vue/src/bizComponents/UserSelector/SimpleMultipleUserSelector.vue
  6. 2
      vue/src/components/AbstractTable/index.vue
  7. 2
      vue/src/components/BottomTip/main.vue
  8. 3
      vue/src/components/Charts/PieChart.vue
  9. 2
      vue/src/components/ContextMenu/ContextMenuItem.vue
  10. 4
      vue/src/components/ContextMenu/index.vue
  11. 3
      vue/src/components/DialogForm/DialogFormItem.vue
  12. 4
      vue/src/components/DialogForm/index.vue
  13. 73
      vue/src/components/DropDownMenu/index.vue
  14. 66
      vue/src/components/DropDownMenu/style.scss
  15. 2
      vue/src/components/Empty/DefaultEmptyImage.vue
  16. 53
      vue/src/components/Empty/index.vue
  17. 47
      vue/src/components/Empty/style.scss
  18. 92
      vue/src/components/Guide/main.vue
  19. 69
      vue/src/components/Guide/style.scss
  20. 3
      vue/src/components/ImageViewer/main.vue
  21. 42
      vue/src/components/LinerProgress/index.vue
  22. 36
      vue/src/components/LinerProgress/style.scss
  23. 2
      vue/src/components/Link/index.vue
  24. 7
      vue/src/components/LoadingMask/index.vue
  25. 7
      vue/src/components/OrgTree/index.vue
  26. 10
      vue/src/components/PuzzleVerify/main.vue
  27. 5
      vue/src/components/RegionSelector/Tab/index.vue
  28. 3
      vue/src/components/SearchForm/SearchFormItem.vue
  29. 7
      vue/src/components/SearchForm/index.vue
  30. 6
      vue/src/components/SignautreBoard/main.vue
  31. 2
      vue/src/components/Skeleton/PageSkeleton.vue
  32. 3
      vue/src/components/Skeleton/index.vue
  33. 3
      vue/src/components/SvgIcon/index.vue
  34. 6
      vue/src/components/TinymceEditor/index.vue
  35. 7
      vue/src/components/ZoomControl/index.vue
  36. 13
      vue/src/layout/components/Header.vue
  37. 6
      vue/src/layout/components/Main.vue
  38. 4
      vue/src/layout/components/Navbar/components/Bell.vue
  39. 3
      vue/src/layout/components/Navbar/components/Breadcrumb.vue
  40. 85
      vue/src/layout/components/Navbar/components/Fullscreen.vue
  41. 7
      vue/src/layout/components/Navbar/components/Hamburger.vue
  42. 12
      vue/src/layout/components/Navbar/components/HeaderSearch.vue
  43. 4
      vue/src/layout/components/Navbar/components/SettingDrawer.vue
  44. 64
      vue/src/layout/components/Navbar/index.vue
  45. 52
      vue/src/layout/components/Navbar/style.scss
  46. 4
      vue/src/layout/components/Sidebar/components/Logo.vue
  47. 2
      vue/src/layout/components/Sidebar/components/SidebarItem.vue
  48. 3
      vue/src/layout/components/Sidebar/components/SidebarItemContent.vue
  49. 15
      vue/src/layout/components/Sidebar/index.vue
  50. 6
      vue/src/layout/components/TagsView/ScrollPane.vue
  51. 9
      vue/src/layout/components/TagsView/index.vue
  52. 10
      vue/src/layout/index.vue
  53. 8
      vue/src/views/app/403.vue
  54. 8
      vue/src/views/app/404.vue
  55. 18
      vue/src/views/app/login/LoginForm.vue
  56. 12
      vue/src/views/app/login/RegisterForm.vue
  57. 4
      vue/src/views/app/login/SetAnimation.vue
  58. 10
      vue/src/views/app/login/index.vue
  59. 1
      vue/src/views/app/redirect.vue
  60. 5
      vue/src/views/index/components/DailyFinishOrderStat.vue
  61. 5
      vue/src/views/index/components/DailyProfitStat.vue
  62. 3
      vue/src/views/index/components/PanelGroup/PanelGroupItem.vue
  63. 5
      vue/src/views/index/components/PanelGroup/index.vue
  64. 6
      vue/src/views/index/components/TotalProfitGoods.vue
  65. 1
      vue/src/views/index/index.vue
  66. 7
      vue/src/views/message/manage/EditDialog.vue
  67. 15
      vue/src/views/message/manage/index.vue
  68. 25
      vue/src/views/purchase/inbound/components/EditDialog.vue
  69. 12
      vue/src/views/purchase/inbound/components/OrderSelector.vue
  70. 6
      vue/src/views/purchase/inbound/index.vue
  71. 61
      vue/src/views/purchase/order/components/EditDialog.vue
  72. 2
      vue/src/views/purchase/order/components/SupplierSelector.vue
  73. 15
      vue/src/views/sell/order/components/CustomerSelector.vue
  74. 63
      vue/src/views/sell/order/components/EditDialog.vue
  75. 12
      vue/src/views/sell/order/components/StockSelector.vue
  76. 16
      vue/src/views/sell/order/index.vue
  77. 34
      vue/src/views/sell/outbound/components/EditDialog.vue
  78. 12
      vue/src/views/sell/outbound/components/OrderSelector.vue
  79. 11
      vue/src/views/sell/outbound/components/StockSelector.vue
  80. 16
      vue/src/views/sell/outbound/index.vue
  81. 11
      vue/src/views/stock/current/DetailDialog.vue
  82. 18
      vue/src/views/stock/current/index.vue
  83. 11
      vue/src/views/system/category/components/Form.vue
  84. 13
      vue/src/views/system/category/components/List.vue
  85. 1
      vue/src/views/system/category/index.vue
  86. 14
      vue/src/views/system/customer/EditDialog.vue
  87. 18
      vue/src/views/system/customer/index.vue
  88. 12
      vue/src/views/system/department/components/EditDialog.vue
  89. 7
      vue/src/views/system/department/components/OrgTreeView.vue
  90. 17
      vue/src/views/system/department/index.vue
  91. 11
      vue/src/views/system/monitor/components/Cpu.vue
  92. 9
      vue/src/views/system/monitor/components/Jvm.vue
  93. 9
      vue/src/views/system/monitor/components/Memory.vue
  94. 10
      vue/src/views/system/monitor/index.vue
  95. 26
      vue/src/views/system/resource/EditDialog.vue
  96. 8
      vue/src/views/system/resource/index.vue
  97. 13
      vue/src/views/system/role/components/EditDialog.vue
  98. 3
      vue/src/views/system/role/components/RoleResource.vue
  99. 16
      vue/src/views/system/role/index.vue
  100. 14
      vue/src/views/system/supplier/EditDialog.vue
  101. Some files were not shown because too many files have changed in this diff Show More

@ -198,4 +198,12 @@ a:hover {
} }
} }
.table-add-btn {
margin: 8px 0;
.el-button {
width: 100%;
}
}

@ -16,12 +16,15 @@
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
} }
}, },
mounted() { mounted() {
getAllCategories() getAllCategories()
.then(data => this.$store.commit('dataCache/categories', data)) .then(data => this.$store.commit('dataCache/categories', data))

@ -1,11 +1,14 @@
<script type="text/jsx"> <script type="text/jsx">
export default { export default {
name: "DocumentHistory", name: "DocumentHistory",
functional: true, functional: true,
props: { props: {
type: String, type: String,
data: {type: Array, default: () => []} data: {type: Array, default: () => []}
}, },
render(h, context) { render(h, context) {
const {type, data = []} = context.props const {type, data = []} = context.props
if (type === 'add') return '' if (type === 'add') return ''

@ -1,11 +1,14 @@
<script type="text/jsx"> <script type="text/jsx">
export default { export default {
name: "DocumentSteps", name: "DocumentSteps",
functional: true, functional: true,
props: { props: {
status: Number, status: Number,
type: String type: String
}, },
render(h, context) { render(h, context) {
let {status, type} = context.props let {status, type} = context.props
let firstStatus = type === 'add' ? 'finish' : 'success' let firstStatus = type === 'add' ? 'finish' : 'success'

@ -14,20 +14,24 @@
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: { methods: {
emit(v) { emit(v) {
this.$emit('input', v) this.$emit('input', v)
} }
}, },
mounted() { mounted() {
getUsers({page: 1, pageSize: 9999}) getUsers({page: 1, pageSize: 9999})
.then(({list}) => this.data = list) .then(({list}) => this.data = list)

@ -3,7 +3,9 @@
export default { export default {
name: "AbstractTable", name: "AbstractTable",
functional: true, functional: true,
render(h, context) { render(h, context) {
const {data, children} = context const {data, children} = context
return ( return (

@ -10,12 +10,14 @@
<script> <script>
export default { export default {
name: "BottomTip", name: "BottomTip",
data() { data() {
return { return {
value: false, value: false,
message: null message: null
} }
}, },
methods: { methods: {
handleAfterLeave() { handleAfterLeave() {
this.$destroy(true) this.$destroy(true)

@ -7,10 +7,12 @@
export default { export default {
mixins: [resize, logic], mixins: [resize, logic],
props: { props: {
title: String, title: String,
data: Array data: Array
}, },
watch: { watch: {
data: { data: {
deep: true, deep: true,
@ -19,6 +21,7 @@
} }
} }
}, },
methods: { methods: {
init(data) { init(data) {
this.chart.setOption({ this.chart.setOption({

@ -1,7 +1,9 @@
<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 h('li', context.data, context.children) return h('li', context.data, context.children)
} }

@ -7,6 +7,7 @@
<script> <script>
export default { export default {
name: "ContextMenu", name: "ContextMenu",
props: { props: {
value: { value: {
type: Boolean, type: Boolean,
@ -19,12 +20,14 @@
type: Number type: Number
} }
}, },
data() { data() {
return { return {
realLeft: '0px', realLeft: '0px',
realTop: '0px' realTop: '0px'
} }
}, },
watch: { watch: {
value(v) { value(v) {
document.body[v ? 'addEventListener' : 'removeEventListener']('click', this.closeContextMenu) document.body[v ? 'addEventListener' : 'removeEventListener']('click', this.closeContextMenu)
@ -39,6 +42,7 @@
this.autoAdaptTop(v) this.autoAdaptTop(v)
} }
}, },
methods: { methods: {
closeContextMenu() { closeContextMenu() {
this.$emit('input', false) this.$emit('input', false)

@ -1,8 +1,11 @@
<script type="text/jsx"> <script type="text/jsx">
export default { export default {
name: "DialogFormItem", name: "DialogFormItem",
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) {
let {full, dense, label, prop} = context.props let {full, dense, label, prop} = context.props
let attrs = {xs: 24, sm: 12, lg: 8} let attrs = {xs: 24, sm: 12, lg: 8}

@ -7,6 +7,7 @@
v-on="$listeners" v-on="$listeners"
> >
<slot slot="title" name="title">{{title}}</slot> <slot slot="title" name="title">{{title}}</slot>
<div class="dialog-form-container"> <div class="dialog-form-container">
<loading-mask :show="loading"/> <loading-mask :show="loading"/>
<el-scrollbar> <el-scrollbar>
@ -16,6 +17,7 @@
<div style="margin-bottom: 17px"/> <div style="margin-bottom: 17px"/>
</el-scrollbar> </el-scrollbar>
</div> </div>
<slot slot="footer" name="footer"/> <slot slot="footer" name="footer"/>
</el-dialog> </el-dialog>
</template> </template>
@ -25,7 +27,9 @@
export default { export default {
name: "DialogForm", name: "DialogForm",
components: {LoadingMask}, components: {LoadingMask},
props: { props: {
value: Boolean, value: Boolean,
appendToBody: Boolean, appendToBody: Boolean,

@ -2,6 +2,7 @@
<div :class="{active:isActive}" class="share-dropdown-menu"> <div :class="{active:isActive}" class="share-dropdown-menu">
<div class="share-dropdown-menu-wrapper"> <div class="share-dropdown-menu-wrapper">
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span> <span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span>
<div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item"> <div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item">
<a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a> <a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a>
<span v-else>{{ item.title }}</span> <span v-else>{{ item.title }}</span>
@ -14,6 +15,7 @@
//drop.js //drop.js
export default { export default {
name: 'DropdownMenu', name: 'DropdownMenu',
props: { props: {
items: { items: {
type: Array, type: Array,
@ -26,11 +28,13 @@
default: 'vue' default: 'vue'
} }
}, },
data() { data() {
return { return {
isActive: false isActive: false
} }
}, },
methods: { methods: {
clickTitle() { clickTitle() {
this.isActive = !this.isActive this.isActive = !this.isActive
@ -39,71 +43,4 @@
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
$n: 9; //items.length
$t: .1s;
.share-dropdown-menu {
width: 250px;
position: relative;
z-index: 1;
&-title {
width: 100%;
display: block;
cursor: pointer;
background: black;
color: white;
height: 60px;
line-height: 60px;
font-size: 20px;
text-align: center;
z-index: 2;
transform: translate3d(0, 0, 0);
}
&-wrapper {
position: relative;
}
&-item {
text-align: center;
position: absolute;
width: 100%;
background: #e0e0e0;
line-height: 60px;
height: 60px;
cursor: pointer;
font-size: 20px;
opacity: 1;
transition: transform 0.28s ease;
&:hover {
background: black;
color: white;
}
@for $i from 1 through $n {
&:nth-of-type(#{$i}) {
z-index: -1;
transition-delay: $i*$t;
transform: translate3d(0, -60px, 0);
}
}
}
&.active {
.share-dropdown-menu-wrapper {
z-index: 1;
}
.share-dropdown-menu-item {
@for $i from 1 through $n {
&:nth-of-type(#{$i}) {
transition-delay: ($n - $i)*$t;
transform: translate3d(0, ($i - 1)*60px, 0);
}
}
}
}
}
</style>

@ -0,0 +1,66 @@
$n: 9; //和items.length 相同
$t: .1s;
.share-dropdown-menu {
width: 250px;
position: relative;
z-index: 1;
&-title {
width: 100%;
display: block;
cursor: pointer;
background: black;
color: white;
height: 60px;
line-height: 60px;
font-size: 20px;
text-align: center;
z-index: 2;
transform: translate3d(0, 0, 0);
}
&-wrapper {
position: relative;
}
&-item {
text-align: center;
position: absolute;
width: 100%;
background: #e0e0e0;
line-height: 60px;
height: 60px;
cursor: pointer;
font-size: 20px;
opacity: 1;
transition: transform 0.28s ease;
&:hover {
background: black;
color: white;
}
@for $i from 1 through $n {
&:nth-of-type(#{$i}) {
z-index: -1;
transition-delay: $i*$t;
transform: translate3d(0, -60px, 0);
}
}
}
&.active {
.share-dropdown-menu-wrapper {
z-index: 1;
}
.share-dropdown-menu-item {
@for $i from 1 through $n {
&:nth-of-type(#{$i}) {
transition-delay: ($n - $i)*$t;
transform: translate3d(0, ($i - 1)*60px, 0);
}
}
}
}
}

@ -1,7 +1,9 @@
<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">

@ -3,12 +3,15 @@
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'
@ -32,52 +35,4 @@
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
.ant-empty {
padding: 20px;
margin: 0 8px;
font-size: 14px;
line-height: 22px;
text-align: center;
&-image {
height: 100px;
margin-bottom: 8px;
img {
height: 100%;
}
svg {
height: 100%;
margin: auto;
}
}
&-description {
margin: 0;
}
&-footer {
margin-top: 16px;
}
&-normal {
margin: 32px 0;
color: rgba(0, 0, 0, .25);
.ant-empty-image {
height: 40px;
}
}
&-small {
margin: 8px 0;
color: rgba(0, 0, 0, .25);
.ant-empty-image {
height: 35px;
}
}
}
</style>

@ -0,0 +1,47 @@
.ant-empty {
padding: 20px;
margin: 0 8px;
font-size: 14px;
line-height: 22px;
text-align: center;
&-image {
height: 100px;
margin-bottom: 8px;
img {
height: 100%;
}
svg {
height: 100%;
margin: auto;
}
}
&-description {
margin: 0;
}
&-footer {
margin-top: 16px;
}
&-normal {
margin: 32px 0;
color: rgba(0, 0, 0, .25);
.ant-empty-image {
height: 40px;
}
}
&-small {
margin: 8px 0;
color: rgba(0, 0, 0, .25);
.ant-empty-image {
height: 35px;
}
}
}

@ -2,6 +2,7 @@
<div> <div>
<el-popover ref="popover" :value="showPopover" trigger="manual" width="300"> <el-popover ref="popover" :value="showPopover" trigger="manual" width="300">
<div v-html="step.content" style="padding: 10px"/> <div v-html="step.content" style="padding: 10px"/>
<div class="guide-popover-action"> <div class="guide-popover-action">
<div class="action-close"> <div class="action-close">
<el-button v-show="hasDone" size="small" @click="exit"> <el-button v-show="hasDone" size="small" @click="exit">
@ -11,6 +12,7 @@
{{step.closeBtnText}} {{step.closeBtnText}}
</el-button> </el-button>
</div> </div>
<div class="action-step"> <div class="action-step">
<el-button v-show="showPrevBtn" class="prev-btn" size="small" @click="previous"> <el-button v-show="showPrevBtn" class="prev-btn" size="small" @click="previous">
{{step.prevBtnText}} {{step.prevBtnText}}
@ -20,24 +22,27 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<div slot="reference" v-show="showStage" id="guide-stage" :style="stageStyle"/> <div slot="reference" v-show="showStage" id="guide-stage" :style="stageStyle"/>
</el-popover> </el-popover>
<div v-show="showStage" id="guide-highlight-element-cover" :style="stageStyle" @click.prevent.stop/> <div v-show="showStage" id="guide-highlight-element-cover" :style="stageStyle" @click.prevent.stop/>
<div v-show="showOverlay" id="guide-overlay"/> <div v-show="showOverlay" id="guide-overlay"/>
</div> </div>
</template> </template>
<script> <script>
/* /**
* 由driver.js改造而来 * 由driver.js改造而来
* vue里交互型的导航不太行太多东西做不到换成引导手册吧 * vue里交互型的导航不太行太多东西做不到换成引导手册吧
* */ */
import {debounce, isEmpty} from "@/utils" import {debounce, isEmpty} from "@/utils"
import {addHighlightClasses, getCalculatedPosition, inAppView, jump, removeHighlightClasses} from "./utils" import {addHighlightClasses, getCalculatedPosition, inAppView, jump, removeHighlightClasses} from "./utils"
export default { export default {
name: "Guide", name: "Guide",
data() { data() {
return { return {
steps: [], steps: [],
@ -59,6 +64,7 @@
lastHighlightedElement: null lastHighlightedElement: null
} }
}, },
computed: { computed: {
showPopover() { showPopover() {
return !this.moving && this.showStage return !this.moving && this.showStage
@ -83,11 +89,13 @@
} }
} }
}, },
watch: { watch: {
isActive(v) { isActive(v) {
v ? document.body.classList.add('overflow-hidden') : document.body.classList.remove('overflow-hidden') v ? document.body.classList.add('overflow-hidden') : document.body.classList.remove('overflow-hidden')
} }
}, },
methods: { methods: {
start(index = 0) { start(index = 0) {
if (!this.steps || this.steps.length === 0) throw new Error('请传入步骤') if (!this.steps || this.steps.length === 0) throw new Error('请传入步骤')
@ -207,84 +215,16 @@
`backgroundColor:${this.step.stageBackground}` `backgroundColor:${this.step.stageBackground}`
} }
}, },
mounted() { mounted() {
this.resize = debounce(this.resize) this.resize = debounce(this.resize)
window.addEventListener('resize', this.resize) window.addEventListener('resize', this.resize)
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener('resize', this.resize) window.removeEventListener('resize', this.resize)
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
.guide-highlighted-element {
z-index: 1002 !important;
}
.guide-position-relative {
position: relative !important;
}
.guide-fix-stacking {
z-index: auto !important;
opacity: 1.0 !important;
transform: none !important;
filter: none !important;
perspective: none !important;
transform-style: flat !important;
will-change: unset !important;
}
.guide-popover-action {
position: relative;
height: 100%;
width: 100%;
.action-close {
display: inline-block;
}
.action-step {
display: inline-block;
right: 0;
position: absolute;
.prev-btn {
position: absolute;
right: 90px;
}
.next-btn {
}
}
}
#guide-stage {
position: absolute;
background: white;
transition: all 0.3s;
z-index: 1001 !important;
border-radius: 2px;
/*background: transparent !important;
outline: 5000px solid rgba(0, 0, 0, 0.75);*/
}
#guide-overlay {
background: black;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
opacity: 0.75;
z-index: 1000 !important;
}
#guide-highlight-element-cover {
position: absolute;
background: transparent !important;
z-index: 1003 !important;
}
</style>

@ -0,0 +1,69 @@
.guide-highlighted-element {
z-index: 1002 !important;
}
.guide-position-relative {
position: relative !important;
}
.guide-fix-stacking {
z-index: auto !important;
opacity: 1.0 !important;
transform: none !important;
filter: none !important;
perspective: none !important;
transform-style: flat !important;
will-change: unset !important;
}
.guide-popover-action {
position: relative;
height: 100%;
width: 100%;
.action-close {
display: inline-block;
}
.action-step {
display: inline-block;
right: 0;
position: absolute;
.prev-btn {
position: absolute;
right: 90px;
}
.next-btn {
}
}
}
#guide-stage {
position: absolute;
background: white;
transition: all 0.3s;
z-index: 1001 !important;
border-radius: 2px;
/*background: transparent !important;
outline: 5000px solid rgba(0, 0, 0, 0.75);*/
}
#guide-overlay {
background: black;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
opacity: 0.75;
z-index: 1000 !important;
}
#guide-highlight-element-cover {
position: absolute;
background: transparent !important;
z-index: 1003 !important;
}

@ -7,7 +7,9 @@
export default { export default {
name: "ImageViewer", name: "ImageViewer",
components: {ElImageViewer: ImageViewer}, components: {ElImageViewer: ImageViewer},
data() { data() {
return { return {
value: false, value: false,
@ -15,6 +17,7 @@
urlList: [] urlList: []
} }
}, },
methods: { methods: {
close() { close() {
this.value = false this.value = false

@ -2,8 +2,11 @@
//muse-uihttps://muse-ui.org/#/zh-CN/progress //muse-uihttps://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 (
@ -17,41 +20,4 @@
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
.liner-progress {
position: relative;
height: 4px;
display: block;
width: 100%;
margin: 0;
overflow: hidden;
.liner-progress-background {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $--color-primary;
opacity: .3;
}
.linear-progress-indeterminate {
position: absolute;
top: 0;
bottom: 0;
width: 40%;
background-color: $--color-primary;
animation: linear-progress-animate .84s cubic-bezier(.445, .05, .55, .95) infinite;
}
@keyframes linear-progress-animate {
0% {
left: -40%;
}
100% {
left: 100%;
}
}
}
</style>

@ -0,0 +1,36 @@
.liner-progress {
position: relative;
height: 4px;
display: block;
width: 100%;
margin: 0;
overflow: hidden;
.liner-progress-background {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $--color-primary;
opacity: .3;
}
.linear-progress-indeterminate {
position: absolute;
top: 0;
bottom: 0;
width: 40%;
background-color: $--color-primary;
animation: linear-progress-animate .84s cubic-bezier(.445, .05, .55, .95) infinite;
}
@keyframes linear-progress-animate {
0% {
left: -40%;
}
100% {
left: 100%;
}
}
}

@ -3,7 +3,9 @@
export default { export default {
name: 'Link', name: 'Link',
functional: true, functional: true,
render(h, context) { render(h, context) {
let to = context.props.to let to = context.props.to
if (isExternal(to)) return ( if (isExternal(to)) return (

@ -1,10 +1,11 @@
<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 === false) return '' if (context.props.show === false) return ''
return ( return (

@ -24,12 +24,14 @@
export default { export default {
name: 'OrgTree', name: 'OrgTree',
components: { components: {
OrgTreeNode: { OrgTreeNode: {
render, render,
functional: true functional: true
} }
}, },
props: { props: {
data: { data: {
type: Object, type: Object,
@ -55,12 +57,14 @@
default: false default: false
} }
}, },
data() { data() {
return { return {
flatData: {}, flatData: {},
dataCloned: {} dataCloned: {}
} }
}, },
watch: { watch: {
data(newData) { data(newData) {
this._handleData(newData) this._handleData(newData)
@ -74,6 +78,7 @@
this._toggleExpand(this.dataCloned, status) this._toggleExpand(this.dataCloned, status)
} }
}, },
computed: { computed: {
prop_id() { prop_id() {
return this.props.id return this.props.id
@ -88,6 +93,7 @@
return this.props.children return this.props.children
} }
}, },
methods: { methods: {
_handleData(data) { _handleData(data) {
this._cloneData(data) this._cloneData(data)
@ -169,6 +175,7 @@
this._updateExpandStatus() this._updateExpandStatus()
} }
}, },
mounted() { mounted() {
this._handleData(this.data) this._handleData(this.data)
this._updateExpandStatus() this._updateExpandStatus()

@ -9,18 +9,22 @@
<div class="puzzle-view" :style="`width:${width}px;height:${height}px;`"> <div class="puzzle-view" :style="`width:${width}px;height:${height}px;`">
<div v-show="!image.loading" style="width: 100%;height: 100%"> <div v-show="!image.loading" style="width: 100%;height: 100%">
<img :src="image.src"/> <img :src="image.src"/>
<canvas ref="puzzleBox" :height="height" :width="width"/> <canvas ref="puzzleBox" :height="height" :width="width"/>
<div class="puzzle-lost-box" :style="`left:${leftNum}px`"> <div class="puzzle-lost-box" :style="`left:${leftNum}px`">
<canvas ref="puzzleShadow" :style="sliderStyle" :height="height" :width="width"/> <canvas ref="puzzleShadow" :style="sliderStyle" :height="height" :width="width"/>
<canvas ref="puzzleLost" :style="sliderStyle" :height="height" :width="width"/> <canvas ref="puzzleLost" :style="sliderStyle" :height="height" :width="width"/>
</div> </div>
</div> </div>
<transition name="fade"> <transition name="fade">
<div v-show="image.loading" class="puzzle-image-loading"> <div v-show="image.loading" class="puzzle-image-loading">
<div class="puzzle-image-loading__icon"/> <div class="puzzle-image-loading__icon"/>
<div class="puzzle-image-loading__text">加载中...</div> <div class="puzzle-image-loading__text">加载中...</div>
</div> </div>
</transition> </transition>
<div :class="resultTipClass"> <div :class="resultTipClass">
{{stat==='success'?'验证通过':'请正确拼合图像'}} {{stat==='success'?'验证通过':'请正确拼合图像'}}
</div> </div>
@ -38,6 +42,7 @@
<a class="puzzle-text-container puzzle-close" @click="close"> <a class="puzzle-text-container puzzle-close" @click="close">
<div class="puzzle-text-tip">关闭验证</div> <div class="puzzle-text-tip">关闭验证</div>
</a> </a>
<a class="puzzle-text-container puzzle-refresh" @click="refresh"> <a class="puzzle-text-container puzzle-refresh" @click="refresh">
<div class="puzzle-text-tip">刷新验证</div> <div class="puzzle-text-tip">刷新验证</div>
</a> </a>
@ -54,6 +59,7 @@
* */ * */
export default { export default {
name: "PuzzleVerify", name: "PuzzleVerify",
props: { props: {
//transition.scss //transition.scss
transition: { transition: {
@ -85,6 +91,7 @@
default: 80 default: 80
} }
}, },
data() { data() {
return { return {
visible: false, visible: false,
@ -107,6 +114,7 @@
} }
} }
}, },
computed: { computed: {
resultTipClass() { resultTipClass() {
const showResultTip = ['success', 'fail'].includes(this.stat) const showResultTip = ['success', 'fail'].includes(this.stat)
@ -119,6 +127,7 @@
} }
} }
}, },
methods: { methods: {
close() { close() {
this.visible = false this.visible = false
@ -295,6 +304,7 @@
this.$el.parentNode.removeChild(this.$el) this.$el.parentNode.removeChild(this.$el)
} }
}, },
mounted() { mounted() {
this.initImage().then(() => this.initCanvas()) this.initImage().then(() => this.initCanvas())
}, },

@ -12,13 +12,16 @@
<template slot="empty"> <template slot="empty">
<div class="rg-header"> <div class="rg-header">
<h3>行政区划选择</h3> <h3>行政区划选择</h3>
<button class="rg-removeall-button" type="button" title="清除已选" @click="removeAll"> <button class="rg-removeall-button" type="button" title="清除已选" @click="removeAll">
<i class="el-icon-delete"/> <i class="el-icon-delete"/>
</button> </button>
<button class="rg-done-button" type="button" title="完成" @click="done"> <button class="rg-done-button" type="button" title="完成" @click="done">
<i class="el-icon-check"/> <i class="el-icon-check"/>
</button> </button>
</div> </div>
<div class="rg-search"> <div class="rg-search">
<input <input
ref="searchInput" ref="searchInput"
@ -29,6 +32,7 @@
@input="search" @input="search"
> >
</div> </div>
<div class="rg-level-tabs"> <div class="rg-level-tabs">
<ul> <ul>
<li v-for="(tab,index) in selected" :key="tab.name" :class="{active:index+1 === currentLevel}"> <li v-for="(tab,index) in selected" :key="tab.name" :class="{active:index+1 === currentLevel}">
@ -36,6 +40,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<div v-loading="loading" class="rg-results-container"> <div v-loading="loading" class="rg-results-container">
<ul class="rg-results"> <ul class="rg-results">
<li <li

@ -1,12 +1,15 @@
<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 (

@ -3,11 +3,13 @@
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: 24},// <768px xs: {type: Number, default: 24},// <768px
@ -15,6 +17,7 @@
md: {type: Number, default: 8}, // >=998px md: {type: Number, default: 8}, // >=998px
lg: {type: Number, default: 6} // >=1200px lg: {type: Number, default: 6} // >=1200px
}, },
data() { data() {
return { return {
showCollapse: false, showCollapse: false,
@ -23,6 +26,7 @@
width: 'auto' width: 'auto'
} }
}, },
methods: { methods: {
handleCollapse() { handleCollapse() {
this.collapse = !this.collapse this.collapse = !this.collapse
@ -45,13 +49,16 @@
this.showCollapse = num < this.$slots.default.length this.showCollapse = num < this.$slots.default.length
} }
}, },
mounted() { mounted() {
this.resize() this.resize()
window.addEventListener('resize', this.resize) window.addEventListener('resize', this.resize)
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener('resize', this.resize) window.removeEventListener('resize', this.resize)
}, },
render() { render() {
const slots = this.$slots.default const slots = this.$slots.default
const collapseChildren = [] const collapseChildren = []

@ -9,6 +9,7 @@
@touchmove.prevent="drawMove" @touchmove.prevent="drawMove"
@touchend.prevent="drawEnd" @touchend.prevent="drawEnd"
/> />
<div class="signature-board__footer"> <div class="signature-board__footer">
<el-button plain size="small" @click="clear"> </el-button> <el-button plain size="small" @click="clear"> </el-button>
<el-button plain size="small" @click="close"> </el-button> <el-button plain size="small" @click="close"> </el-button>
@ -37,12 +38,14 @@
export default { export default {
name: 'SignatureBoard', name: 'SignatureBoard',
props: { props: {
image: String, image: String,
lineWidth: Number, lineWidth: Number,
lineColor: String, lineColor: String,
onConfirm: Function onConfirm: Function
}, },
data() { data() {
return { return {
visible: false, visible: false,
@ -52,6 +55,7 @@
startY: 0 startY: 0
} }
}, },
methods: { methods: {
drawStart(e) { drawStart(e) {
const {x, y} = getEventPoint(e) const {x, y} = getEventPoint(e)
@ -125,9 +129,11 @@
this.visible = false this.visible = false
} }
}, },
mounted() { mounted() {
window.addEventListener('resize', this.resize) window.addEventListener('resize', this.resize)
}, },
beforeDestroy() { beforeDestroy() {
this.clear() this.clear()
window.removeEventListener('resize', this.resize) window.removeEventListener('resize', this.resize)

@ -4,7 +4,9 @@
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">

@ -4,7 +4,9 @@
export default { export default {
name: 'QSkeleton', name: 'QSkeleton',
functional: true, functional: true,
props: { props: {
type: { type: {
type: String, type: String,
@ -25,6 +27,7 @@
width: String, width: String,
height: 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}

@ -3,7 +3,9 @@
export default { export default {
name: 'SvgIcon', name: 'SvgIcon',
functional: true, functional: true,
props: { props: {
icon: { icon: {
type: String, type: String,
@ -14,6 +16,7 @@
default: '' default: ''
} }
}, },
render(h, context) { render(h, context) {
const {listeners} = context const {listeners} = context
const {icon, className} = context.props const {icon, className} = context.props

@ -21,6 +21,7 @@
export default { export default {
name: "TinymceEditor", name: "TinymceEditor",
props: { props: {
value: String, value: String,
readonly: Boolean, readonly: Boolean,
@ -33,6 +34,7 @@
default: '100%' default: '100%'
} }
}, },
data() { data() {
return { return {
id: 'tinymce-' + Date.now(), id: 'tinymce-' + Date.now(),
@ -41,6 +43,7 @@
manualChange: false, manualChange: false,
} }
}, },
watch: { watch: {
value(value) { value(value) {
if (!this.hasInit) return if (!this.hasInit) return
@ -51,6 +54,7 @@
this.hasInit && this.getInstance().mode.set(value ? 'readonly' : 'design') this.hasInit && this.getInstance().mode.set(value ? 'readonly' : 'design')
} }
}, },
methods: { methods: {
getInstance() { getInstance() {
return window.tinymce.get(this.id) return window.tinymce.get(this.id)
@ -95,9 +99,11 @@
tinymce.destroy() tinymce.destroy()
} }
}, },
mounted() { mounted() {
!this.readonly && this.init() !this.readonly && this.init()
}, },
beforeDestroy() { beforeDestroy() {
this.destroy() this.destroy()
}, },

@ -1,7 +1,9 @@
<template> <template>
<div class="zoom-wrapper"> <div class="zoom-wrapper">
<el-button circle icon="el-icon-minus" size="small" title="缩小" type="info" @click="zoomOut"/> <el-button circle icon="el-icon-minus" size="small" title="缩小" type="info" @click="zoomOut"/>
<span class="zoom-number">{{ value }}%</span> <span class="zoom-number">{{ value }}%</span>
<el-button circle icon="el-icon-plus" size="small" title="放大" type="info" @click="zoomIn"/> <el-button circle icon="el-icon-plus" size="small" title="放大" type="info" @click="zoomIn"/>
</div> </div>
</template> </template>
@ -9,6 +11,7 @@
<script> <script>
export default { export default {
name: "ZoomControl", name: "ZoomControl",
props: { props: {
value: { value: {
type: Number, type: Number,
@ -27,16 +30,18 @@
default: 200 default: 200
} }
}, },
methods: { methods: {
zoomIn() { zoomIn() {
const zoom = this.value + this.step const zoom = this.value + this.step
if (zoom <= this.max) this.$emit('input', zoom) if (zoom <= this.max) this.$emit('input', zoom)
}, },
zoomOut() { zoomOut() {
const zoom = this.value - this.step const zoom = this.value - this.step
if (zoom >= this.min) this.$emit('input', zoom) if (zoom >= this.min) this.$emit('input', zoom)
} }
}, }
} }
</script> </script>

@ -6,6 +6,7 @@
@mouseleave="mouseOutside=true" @mouseleave="mouseOutside=true"
> >
<v-navbar @menu-show="navbarMenuShow=$event"/> <v-navbar @menu-show="navbarMenuShow=$event"/>
<tags-view v-if="useTagsView" @menu-show="tagsViewMenuShow=$event"/> <tags-view v-if="useTagsView" @menu-show="tagsViewMenuShow=$event"/>
</header> </header>
</template> </template>
@ -17,7 +18,9 @@
export default { export default {
name: "Header", name: "Header",
components: {VNavbar, TagsView}, components: {VNavbar, TagsView},
data() { data() {
return { return {
mouseOutside: true, mouseOutside: true,
@ -26,11 +29,13 @@
appMain: null appMain: null
} }
}, },
computed: { computed: {
...mapState('setting', { ...mapState('setting', {
useTagsView: state => state.useTagsView, useTagsView: state => state.useTagsView,
headerAutoHidden: state => state.headerAutoHidden headerAutoHidden: state => state.headerAutoHidden
}), }),
hideHeader() { hideHeader() {
return this.mouseOutside return this.mouseOutside
&& this.headerAutoHidden && this.headerAutoHidden
@ -38,35 +43,43 @@
&& !this.navbarMenuShow && !this.navbarMenuShow
}, },
}, },
watch: { watch: {
useTagsView(v) { useTagsView(v) {
!v && this.$store.dispatch('tagsView/delAllViews') !v && this.$store.dispatch('tagsView/delAllViews')
}, },
hideHeader(v) { hideHeader(v) {
this.$store.commit('app/hasHeader', !v) this.$store.commit('app/hasHeader', !v)
v ? this.addEvent() : this.removeEvent() v ? this.addEvent() : this.removeEvent()
} }
}, },
methods: { methods: {
moveEvent(e) { moveEvent(e) {
if (e.clientY <= 15) this.mouseOutside = false if (e.clientY <= 15) this.mouseOutside = false
}, },
addEvent() { addEvent() {
this.appMain.addEventListener('mousemove', this.moveEvent) this.appMain.addEventListener('mousemove', this.moveEvent)
}, },
removeEvent() { removeEvent() {
this.appMain.removeEventListener('mousemove', this.moveEvent) this.appMain.removeEventListener('mousemove', this.moveEvent)
} }
}, },
mounted() { mounted() {
this.appMain = document.querySelector('.app-main') this.appMain = document.querySelector('.app-main')
if (this.headerAutoHidden) this.addEvent() if (this.headerAutoHidden) this.addEvent()
}, },
beforeDestroy() { beforeDestroy() {
this.removeEvent() this.removeEvent()
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.has-tags-view .header-container { .has-tags-view .header-container {
height: calc(#{$nav-height} + #{$tags-view-height}); height: calc(#{$nav-height} + #{$tags-view-height});

@ -33,28 +33,34 @@
export default { export default {
name: 'AppMain', name: 'AppMain',
computed: { computed: {
...mapState('app', { ...mapState('app', {
scrollTop: state => state.scrollTop, scrollTop: state => state.scrollTop,
}), }),
...mapState('setting', { ...mapState('setting', {
showBackToTop: state => state.showBackToTop showBackToTop: state => state.showBackToTop
}), }),
...mapState('tagsView', { ...mapState('tagsView', {
cachedViews: state => state.cachedViews, cachedViews: state => state.cachedViews,
transitionName: state => state.transitionName transitionName: state => state.transitionName
}), }),
...mapState('iframe', { ...mapState('iframe', {
showIframe: state => state.show, showIframe: state => state.show,
currentIframe: state => state.current, currentIframe: state => state.current,
iframeList: state => state.list iframeList: state => state.list
}) })
}, },
watch: { watch: {
scrollTop(v) { scrollTop(v) {
if (v >= 0) this.$refs.scrollbar.$refs.wrap.scrollTop = v if (v >= 0) this.$refs.scrollbar.$refs.wrap.scrollTop = v
} }
}, },
mounted() { mounted() {
//footer //footer
const FooterConstructor = Vue.extend(Footer) const FooterConstructor = Vue.extend(Footer)

@ -7,11 +7,13 @@
<script> <script>
export default { export default {
name: "Bell", name: "Bell",
computed: { computed: {
hidden() { hidden() {
return this.$store.state.message.unreadCount < 1 return this.$store.state.message.unreadCount < 1
} }
}, },
methods: { methods: {
jump() { jump() {
let target = '/message/user' let target = '/message/user'
@ -19,11 +21,13 @@
this.$router.replace(target) this.$router.replace(target)
} }
}, },
mounted() { mounted() {
this.$store.dispatch('message/refresh') this.$store.dispatch('message/refresh')
} }
} }
</script> </script>
<style> <style>
.bell-badge .el-badge__content { .bell-badge .el-badge__content {
top: 15px !important; top: 15px !important;

@ -15,18 +15,21 @@
data: null data: null
} }
}, },
watch: { watch: {
$route(route) { $route(route) {
if (route.path.startsWith('/redirect')) return if (route.path.startsWith('/redirect')) return
this.getBreadcrumb() this.getBreadcrumb()
} }
}, },
methods: { methods: {
getBreadcrumb() { getBreadcrumb() {
// only show routes with meta.title // only show routes with meta.title
this.data = this.$route.matched.filter(item => item.meta.title) this.data = this.$route.matched.filter(item => item.meta.title)
} }
}, },
mounted() { mounted() {
this.getBreadcrumb() this.getBreadcrumb()
} }

@ -1,85 +0,0 @@
<template>
<div @click="change">
<i :class="icon" class="navbar-icon"/>
</div>
</template>
<script>
//iview-admin https://admin.iviewui.com
export default {
name: "Fullscreen",
props: {
value: {
type: Boolean,
default: false
},
events: {
type: Array,
default: () => ['fullscreenchange', 'mozfullscreenchange', 'webkitfullscreenchange', 'msfullscreenchange']
}
},
computed: {
icon() {
return this.value ? 'el-icon-aim' : 'el-icon-full-screen'
}
},
methods: {
change() {
let main = document.body
if (this.value) {
if (document.exitFullscreen) {
document.exitFullscreen()
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen()
}
else if (document.msExitFullscreen) {
document.msExitFullscreen()
}
}
else {
if (main.requestFullscreen) {
main.requestFullscreen()
}
else if (main.mozRequestFullScreen) {
main.mozRequestFullScreen()
}
else if (main.webkitRequestFullScreen) {
main.webkitRequestFullScreen()
}
else if (main.msRequestFullscreen) {
main.msRequestFullscreen()
}
}
},
emit() {
this.$emit('input', !this.value)
this.$emit('on-change', !this.value)
},
bindEvent() {
this.events.forEach(e => document.addEventListener(e, this.emit))
},
removeEvent() {
this.events.forEach(e => document.removeEventListener(e, this.emit))
}
},
mounted() {
let isFullscreen =
document.fullscreenElement
|| document.mozFullScreenElement
|| document.webkitFullscreenElement
|| document.fullScreen
|| document.mozFullScreen
|| document.webkitIsFullScreen
isFullscreen = !!isFullscreen
this.bindEvent()
this.$emit('input', isFullscreen)
},
beforeDestroy() {
this.removeEvent()
}
}
</script>

@ -1,10 +1,11 @@
<script type="text/jsx"> <script type="text/jsx">
export default { export default {
name: 'Hamburger', name: 'Hamburger',
functional: true, functional: true,
props: {
isActive: Boolean props: {isActive: Boolean},
},
render(h, context) { render(h, context) {
const {isActive} = context.props const {isActive} = context.props
return ( return (

@ -1,6 +1,7 @@
<template> <template>
<div :class="{'show':show}" class="header-search"> <div :class="{'show':show}" class="header-search">
<i class="el-icon-search navbar-icon" title="快捷搜索" @click.stop="click"/> <i class="el-icon-search navbar-icon" title="快捷搜索" @click.stop="click"/>
<el-select <el-select
ref="headerSearchSelect" ref="headerSearchSelect"
v-model="search" v-model="search"
@ -27,6 +28,7 @@
export default { export default {
name: 'HeaderSearch', name: 'HeaderSearch',
data() { data() {
return { return {
search: '', search: '',
@ -36,36 +38,43 @@
fuse: null fuse: null
} }
}, },
computed: { computed: {
routes() { routes() {
return this.$store.state.resource.routes return this.$store.state.resource.routes
} }
}, },
watch: { watch: {
routes() { routes() {
this.searchPool = this.generateRoutes(this.routes) this.searchPool = this.generateRoutes(this.routes)
this.initFuse(this.searchPool) this.initFuse(this.searchPool)
}, },
show(value) { show(value) {
if (value) document.body.addEventListener('click', this.close) if (value) document.body.addEventListener('click', this.close)
else document.body.removeEventListener('click', this.close) else document.body.removeEventListener('click', this.close)
} }
}, },
methods: { methods: {
click() { click() {
this.show = !this.show this.show = !this.show
if (this.show) this.$refs.headerSearchSelect.focus() if (this.show) this.$refs.headerSearchSelect.focus()
}, },
close() { close() {
this.$refs.headerSearchSelect.blur() this.$refs.headerSearchSelect.blur()
this.search = '' this.search = ''
this.options = [] this.options = []
this.show = false this.show = false
}, },
change(val) { change(val) {
this.close() this.close()
this.$router.push(val).catch(() => ({})) this.$router.push(val).catch(() => ({}))
}, },
initFuse(list) { initFuse(list) {
this.fuse = new Fuse(list, { this.fuse = new Fuse(list, {
shouldSort: true, shouldSort: true,
@ -77,6 +86,7 @@
keys: ['title'] keys: ['title']
}) })
}, },
generateRoutes(routes, prefixTitle = []) { generateRoutes(routes, prefixTitle = []) {
let res = [] let res = []
for (const route of routes) { for (const route of routes) {
@ -94,10 +104,12 @@
} }
return res return res
}, },
querySearch(query) { querySearch(query) {
this.options = query ? this.fuse.search(query) : [] this.options = query ? this.fuse.search(query) : []
} }
}, },
mounted() { mounted() {
this.searchPool = this.generateRoutes(this.routes) this.searchPool = this.generateRoutes(this.routes)
this.initFuse(this.searchPool) this.initFuse(this.searchPool)

@ -25,14 +25,18 @@
export default { export default {
name: "SettingDrawer", name: "SettingDrawer",
props: { props: {
value: Boolean value: Boolean
}, },
data: () => ({settings}), data: () => ({settings}),
methods: { methods: {
getValue(key) { getValue(key) {
return this.$store.state.setting[key] return this.$store.state.setting[key]
}, },
setValue(value, key) { setValue(value, key) {
this.$store.commit(`setting/${key}`, value) this.$store.commit(`setting/${key}`, value)
} }

@ -59,35 +59,44 @@
export default { export default {
name: 'navbar', name: 'navbar',
mixins: [GuideMixin.navbar], mixins: [GuideMixin.navbar],
components: {Hamburger, Breadcrumb, Search, Bell, SettingDrawer}, components: {Hamburger, Breadcrumb, Search, Bell, SettingDrawer},
data() { data() {
return { return {
fullscreen: false, fullscreen: false,
settingDrawer: false settingDrawer: false
} }
}, },
computed: { computed: {
...mapState('user', { ...mapState('user', {
avatar: state => state.avatar, avatar: state => state.avatar,
name: state => state.name, name: state => state.name,
prepare_logout: state => state.prepare_logout prepare_logout: state => state.prepare_logout
}), }),
...mapState('setting', { ...mapState('setting', {
sidebarCollapse: state => state.sidebarCollapse, sidebarCollapse: state => state.sidebarCollapse,
showBreadcrumb: state => state.showBreadcrumb showBreadcrumb: state => state.showBreadcrumb
}), }),
showSystemMonitor() { showSystemMonitor() {
return auth('/system/monitor') return auth('/system/monitor')
}, },
showSystemResource() { showSystemResource() {
return auth('/system/resource') return auth('/system/resource')
} }
}, },
methods: { methods: {
clickHamburger() { clickHamburger() {
this.$store.commit('setting/sidebarCollapse', !this.sidebarCollapse) this.$store.commit('setting/sidebarCollapse', !this.sidebarCollapse)
}, },
logout() { logout() {
if (this.prepare_logout) return if (this.prepare_logout) return
elConfirm('确认退出?') elConfirm('确认退出?')
@ -97,57 +106,4 @@
} }
</script> </script>
<style lang="scss"> <style lang="scss" src="./style.scss"></style>
.navbar {
height: $nav-height;
overflow: hidden;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
.navbar-icon {
font-size: 18px;
cursor: pointer;
vertical-align: middle;
}
.right-menu {
float: right;
height: 100%;
line-height: $nav-height;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
position: relative;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
transition: background .3s;
cursor: pointer;
&:hover:not(#header-search) {
background: rgba(0, 0, 0, .025)
}
}
.avatar-container {
.avatar-wrapper {
margin-top: 5px;
position: relative;
.el-avatar {
position: relative;
top: 5px;
margin-right: 5px;
}
}
}
}
}
</style>

@ -0,0 +1,52 @@
.navbar {
height: $nav-height;
overflow: hidden;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, .08);
.navbar-icon {
font-size: 18px;
cursor: pointer;
vertical-align: middle;
}
.right-menu {
float: right;
height: 100%;
line-height: $nav-height;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
position: relative;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
transition: background .3s;
cursor: pointer;
&:hover:not(#header-search) {
background: rgba(0, 0, 0, .025)
}
}
.avatar-container {
.avatar-wrapper {
margin-top: 5px;
position: relative;
.el-avatar {
position: relative;
top: 5px;
margin-right: 5px;
}
}
}
}
}

@ -2,7 +2,7 @@
<div :class="{'collapse':collapse}" class="sidebar-logo-container"> <div :class="{'collapse':collapse}" class="sidebar-logo-container">
<router-link class="sidebar-logo-link" key="expand" to="/"> <router-link class="sidebar-logo-link" key="expand" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo"> <img v-if="logo" :src="logo" class="sidebar-logo">
<h1 v-if="!collapse" class="sidebar-title">{{ title }} </h1> <h1 v-if="!collapse" class="sidebar-title">{{ title }}</h1>
</router-link> </router-link>
</div> </div>
</template> </template>
@ -12,7 +12,9 @@
export default { export default {
name: 'SidebarLogo', name: 'SidebarLogo',
props: {collapse: Boolean}, props: {collapse: Boolean},
data() { data() {
return { return {
title, title,

@ -61,12 +61,14 @@
export default { export default {
functional: true, functional: true,
props: { props: {
item: Object, item: Object,
isNest: Boolean, isNest: Boolean,
showParent: Boolean, showParent: Boolean,
collapse: Boolean collapse: Boolean
}, },
render(h, context) { render(h, context) {
return renderNode(h, context.props) return renderNode(h, context.props)
} }

@ -1,11 +1,14 @@
<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 = []

@ -6,19 +6,24 @@
export default { export default {
name: 'sidebar', name: 'sidebar',
components: {SidebarItem, Logo}, components: {SidebarItem, Logo},
data() { data() {
return { return {
mouseOutside: true mouseOutside: true
} }
}, },
computed: { computed: {
...mapState('app', { ...mapState('app', {
device: state => state.device device: state => state.device
}), }),
...mapState('resource', { ...mapState('resource', {
routes: state => state.sidebarMenus routes: state => state.sidebarMenus
}), }),
...mapState('setting', { ...mapState('setting', {
showLogo: state => state.showLogo, showLogo: state => state.showLogo,
sidebarCollapse: state => state.sidebarCollapse, sidebarCollapse: state => state.sidebarCollapse,
@ -26,14 +31,17 @@
sidebarShowParent: state => state.sidebarShowParent, sidebarShowParent: state => state.sidebarShowParent,
sidebarAutoHidden: state => state.sidebarAutoHidden sidebarAutoHidden: state => state.sidebarAutoHidden
}), }),
//pc //pc
collapse() { collapse() {
return this.sidebarCollapse && this.device === 'pc' return this.sidebarCollapse && this.device === 'pc'
}, },
hideSidebar() { hideSidebar() {
return this.sidebarAutoHidden && this.mouseOutside return this.sidebarAutoHidden && this.mouseOutside
|| this.sidebarCollapse && this.device === 'mobile' || this.sidebarCollapse && this.device === 'mobile'
}, },
sidebarClass() { sidebarClass() {
return { return {
'sidebar-container': true, 'sidebar-container': true,
@ -43,6 +51,7 @@
} }
} }
}, },
watch: { watch: {
//elMenuinitOpenedMenu()select //elMenuinitOpenedMenu()select
'$route.path'(nv, ov) { '$route.path'(nv, ov) {
@ -55,15 +64,18 @@
if (!item) menu.openedMenus = [] if (!item) menu.openedMenus = []
else this.select(item.index, item.indexPath, item, false) else this.select(item.index, item.indexPath, item, false)
}, },
hideSidebar(v) { hideSidebar(v) {
if (v) document.addEventListener('mousemove', this.moveEvent) if (v) document.addEventListener('mousemove', this.moveEvent)
else document.removeEventListener('mousemove', this.moveEvent) else document.removeEventListener('mousemove', this.moveEvent)
} }
}, },
methods: { methods: {
moveEvent(e) { moveEvent(e) {
if (e.clientX <= 15) this.mouseOutside = false if (e.clientX <= 15) this.mouseOutside = false
}, },
select(index, indexPath, item, jump = true) { select(index, indexPath, item, jump = true) {
// //
if (this.sidebarUniqueOpen && indexPath.length === 1) { if (this.sidebarUniqueOpen && indexPath.length === 1) {
@ -84,14 +96,17 @@
else this.$router.push(index) else this.$router.push(index)
} }
}, },
mounted() { mounted() {
if (this.sidebarAutoHidden) { if (this.sidebarAutoHidden) {
document.addEventListener('mousemove', this.moveEvent) document.addEventListener('mousemove', this.moveEvent)
} }
}, },
beforeDestroy() { beforeDestroy() {
document.removeEventListener('mousemove', this.moveEvent) document.removeEventListener('mousemove', this.moveEvent)
}, },
render() { render() {
const menu = ( const menu = (
<el-menu <el-menu

@ -9,12 +9,15 @@
export default { export default {
name: 'ScrollPane', name: 'ScrollPane',
data: () => ({rAF: null}), data: () => ({rAF: null}),
computed: { computed: {
scrollWrapper() { scrollWrapper() {
return this.$refs.scrollContainer.$refs.wrap return this.$refs.scrollContainer.$refs.wrap
}, },
}, },
methods: { methods: {
handleScroll(e) { handleScroll(e) {
const eventDelta = e.wheelDelta || -(e.detail || 0) * 40 const eventDelta = e.wheelDelta || -(e.detail || 0) * 40
@ -22,6 +25,7 @@
if (eventDelta < 0 && this.scrollWrapper.scrollWidth <= this.scrollWrapper.scrollLeft + this.scrollWrapper.clientWidth) return if (eventDelta < 0 && this.scrollWrapper.scrollWidth <= this.scrollWrapper.scrollLeft + this.scrollWrapper.clientWidth) return
this.smoothScroll(-eventDelta * 2) this.smoothScroll(-eventDelta * 2)
}, },
moveToTarget(currentTag) { moveToTarget(currentTag) {
const $container = this.$refs.scrollContainer.$el const $container = this.$refs.scrollContainer.$el
const $containerWidth = $container.offsetWidth const $containerWidth = $container.offsetWidth
@ -63,12 +67,14 @@
} }
} }
}, },
scrollLeft(val) { scrollLeft(val) {
this.scrollWrapper.scrollTo({ this.scrollWrapper.scrollTo({
left: val, left: val,
behavior: 'smooth' behavior: 'smooth'
}) })
}, },
smoothScroll(val) { smoothScroll(val) {
if (this.rAF) window.cancelAnimationFrame(this.rAF) if (this.rAF) window.cancelAnimationFrame(this.rAF)
let cost = 300, times = cost / 16, gap = val / times + 1 let cost = 300, times = cost / 16, gap = val / times + 1

@ -16,6 +16,7 @@
<i v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)"/> <i v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)"/>
</router-link> </router-link>
</scroll-pane> </scroll-pane>
<context-menu v-model="contextmenu.show" :left="contextmenu.left" :top="contextmenu.top"> <context-menu v-model="contextmenu.show" :left="contextmenu.left" :top="contextmenu.top">
<context-menu-item @click="refreshSelectedTag(selectedTag)">刷新</context-menu-item> <context-menu-item @click="refreshSelectedTag(selectedTag)">刷新</context-menu-item>
<context-menu-item v-show="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"> <context-menu-item v-show="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">
@ -36,7 +37,9 @@
export default { export default {
mixins: [shortcutsMixin, decideRouterTransitionMixin], mixins: [shortcutsMixin, decideRouterTransitionMixin],
components: {ContextMenu, ContextMenuItem, ScrollPane}, components: {ContextMenu, ContextMenuItem, ScrollPane},
data() { data() {
return { return {
contextmenu: { contextmenu: {
@ -49,24 +52,29 @@
scroller: null scroller: null
} }
}, },
computed: { computed: {
visitedViews() { visitedViews() {
return this.$store.state.tagsView.visitedViews return this.$store.state.tagsView.visitedViews
}, },
routes() { routes() {
return this.$store.state.resource.routes return this.$store.state.resource.routes
} }
}, },
watch: { watch: {
$route(to, from) { $route(to, from) {
this.decideRouteTransition && this.decideRouteTransition(to, from) this.decideRouteTransition && this.decideRouteTransition(to, from)
this.addTags(to) this.addTags(to)
this.moveToCurrentTag() this.moveToCurrentTag()
}, },
'contextmenu.show'(v) { 'contextmenu.show'(v) {
this.$emit('menu-show', v) this.$emit('menu-show', v)
} }
}, },
methods: { methods: {
isActive(route) { isActive(route) {
return route.path === this.$route.path return route.path === this.$route.path
@ -165,6 +173,7 @@
this.selectedTag = tag this.selectedTag = tag
} }
}, },
mounted() { mounted() {
this.initTags() this.initTags()
this.addTags() this.addTags()

@ -22,35 +22,45 @@
export default { export default {
name: 'Layout', name: 'Layout',
mixins: [ResizeHandler], mixins: [ResizeHandler],
components: {VMain, VSidebar, VHeader}, components: {VMain, VSidebar, VHeader},
computed: { computed: {
...mapState('app', { ...mapState('app', {
device: state => state.device, device: state => state.device,
hasHeader: state => state.hasHeader hasHeader: state => state.hasHeader
}), }),
...mapState('setting', { ...mapState('setting', {
useTagsView: state => state.useTagsView, useTagsView: state => state.useTagsView,
sidebarCollapse: state => state.sidebarCollapse sidebarCollapse: state => state.sidebarCollapse
}), }),
...mapState('socket', { ...mapState('socket', {
online: state => state.online online: state => state.online
}), }),
...mapState('user', { ...mapState('user', {
isLogin: state => !isEmpty(state.id) && !isEmpty(state.token) isLogin: state => !isEmpty(state.id) && !isEmpty(state.token)
}), }),
showOfflineTip() { showOfflineTip() {
return !this.online && this.isLogin return !this.online && this.isLogin
}, },
showSidebarMask() { showSidebarMask() {
return !this.sidebarCollapse && this.device === 'mobile' return !this.sidebarCollapse && this.device === 'mobile'
} }
}, },
watch: { watch: {
showOfflineTip(v) { showOfflineTip(v) {
v ? this.$bottomTip('与服务器失去连接') : this.$bottomTip.close() v ? this.$bottomTip('与服务器失去连接') : this.$bottomTip.close()
} }
}, },
methods: { methods: {
collapseSidebar() { collapseSidebar() {
this.$store.commit('setting/sidebarCollapse', true) this.$store.commit('setting/sidebarCollapse', true)

@ -4,12 +4,14 @@
<div class="pic"> <div class="pic">
<img alt="403" height="428" src="static/img/403.gif" width="313"> <img alt="403" height="428" src="static/img/403.gif" width="313">
</div> </div>
<div class="bullshit"> <div class="bullshit">
<div class="bullshit__oops">Oops!</div> <div class="bullshit__oops">Oops!</div>
<div class="bullshit__headline">没有访问权限</div> <div class="bullshit__headline">没有访问权限</div>
<div class="bullshit__info">
请联系管理员或者点击下方按钮返回 <div class="bullshit__info">请联系管理员或者点击下方按钮返回</div>
</div>
<router-link class="bullshit__return-home" to="/index">返回首页</router-link> <router-link class="bullshit__return-home" to="/index">返回首页</router-link>
</div> </div>
</div> </div>

@ -7,12 +7,14 @@
<img alt="404" class="pic__child mid" src="static/img/404_cloud.png"> <img alt="404" class="pic__child mid" src="static/img/404_cloud.png">
<img alt="404" class="pic__child right" src="static/img/404_cloud.png"> <img alt="404" class="pic__child right" src="static/img/404_cloud.png">
</div> </div>
<div class="bullshit"> <div class="bullshit">
<div class="bullshit__oops">Oops!</div> <div class="bullshit__oops">Oops!</div>
<div class="bullshit__headline">没有找到该页面...</div> <div class="bullshit__headline">没有找到该页面...</div>
<div class="bullshit__info">
请检查链接地址是否正确或者点击下方按钮返回 <div class="bullshit__info">请检查链接地址是否正确或者点击下方按钮返回</div>
</div>
<router-link class="bullshit__return-home" to="/index">返回首页</router-link> <router-link class="bullshit__return-home" to="/index">返回首页</router-link>
</div> </div>
</div> </div>

@ -4,6 +4,7 @@
<span class="svg-container"> <span class="svg-container">
<svg-icon icon="user"/> <svg-icon icon="user"/>
</span> </span>
<el-input <el-input
ref="username" ref="username"
v-model="form.username" v-model="form.username"
@ -13,12 +14,14 @@
type="text" type="text"
/> />
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-tooltip v-model="capsTooltip" :tabindex="-1" content="大写锁定已打开" manual placement="left"> <el-tooltip v-model="capsTooltip" :tabindex="-1" content="大写锁定已打开" manual placement="left">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon="password"/> <svg-icon icon="password"/>
</span> </span>
</el-tooltip> </el-tooltip>
<el-input <el-input
ref="password" ref="password"
v-model="form.password" v-model="form.password"
@ -29,10 +32,12 @@
placeholder="请输入密码" placeholder="请输入密码"
@keyup.enter.native="login" @keyup.enter.native="login"
/> />
<span @click="showPwd" class="show-pwd"> <span @click="showPwd" class="show-pwd">
<svg-icon :icon="passwordType === 'password' ? 'eye' : 'eye-open'"/> <svg-icon :icon="passwordType === 'password' ? 'eye' : 'eye-open'"/>
</span> </span>
</el-form-item> </el-form-item>
<el-button <el-button
:loading="loading" :loading="loading"
class="submit-btn" class="submit-btn"
@ -41,11 +46,13 @@
> >
{{loading ? '登 录 中...' : '登 录'}} {{loading ? '登 录 中...' : '登 录'}}
</el-button> </el-button>
<div class="flex" style="margin-top: 20px"> <div class="flex" style="margin-top: 20px">
<p class="other-ways"> <p class="other-ways">
其他方式登录 其他方式登录
<svg-icon v-for="i in otherWays" :key="i" :icon="i" @click="thirdPartyLogin(i)"/> <svg-icon v-for="i in otherWays" :key="i" :icon="i" @click="thirdPartyLogin(i)"/>
</p> </p>
<el-button type="text" @click="register">注册账户</el-button> <el-button type="text" @click="register">注册账户</el-button>
</div> </div>
</el-form> </el-form>
@ -58,6 +65,7 @@
export default { export default {
name: "LoginForm", name: "LoginForm",
data() { data() {
return { return {
loading: false, loading: false,
@ -77,11 +85,13 @@
otherWays: ['qq'] otherWays: ['qq']
} }
}, },
methods: { methods: {
showPwd() { showPwd() {
this.passwordType = this.passwordType === 'password' ? '' : 'password' this.passwordType = this.passwordType === 'password' ? '' : 'password'
this.$nextTick(() => this.$refs.password.focus()) this.$nextTick(() => this.$refs.password.focus())
}, },
login() { login() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(valid => { this.$refs.form.validate(valid => {
@ -96,33 +106,41 @@
.catch(() => this.loading = false) .catch(() => this.loading = false)
}) })
}, },
register() { register() {
!this.loading && this.$router.push('/register') !this.loading && this.$router.push('/register')
}, },
success() { success() {
elSuccess('登陆成功') elSuccess('登陆成功')
const redirect = this.$route.query.redirect || '/' const redirect = this.$route.query.redirect || '/'
//0.2s //0.2s
setTimeout(() => this.$router.push(redirect), 200) setTimeout(() => this.$router.push(redirect), 200)
}, },
thirdPartyLogin(channel) { thirdPartyLogin(channel) {
this.$message.info('假装可以第三方登录') this.$message.info('假装可以第三方登录')
}, },
capsLockTip({keyCode}) { capsLockTip({keyCode}) {
if (keyCode === 20) this.capsTooltip = !this.capsTooltip if (keyCode === 20) this.capsTooltip = !this.capsTooltip
}, },
addCapsLockEvent() { addCapsLockEvent() {
document.addEventListener('keyup', this.capsLockTip) document.addEventListener('keyup', this.capsLockTip)
}, },
removeEvent() { removeEvent() {
document.removeEventListener('keyup', this.addCapsLockEvent) document.removeEventListener('keyup', this.addCapsLockEvent)
} }
}, },
mounted() { mounted() {
this.addCapsLockEvent() this.addCapsLockEvent()
if (isEmpty(this.form.username)) this.$refs.username.focus() if (isEmpty(this.form.username)) this.$refs.username.focus()
else this.$refs.password.focus() else this.$refs.password.focus()
}, },
beforeDestroy() { beforeDestroy() {
this.removeEvent() this.removeEvent()
} }

@ -6,6 +6,7 @@
</span> </span>
<el-input ref="username" v-model="form.username" :maxlength="20" placeholder="请输入用户名"/> <el-input ref="username" v-model="form.username" :maxlength="20" placeholder="请输入用户名"/>
</el-form-item> </el-form-item>
<el-form-item prop="pwd"> <el-form-item prop="pwd">
<el-tooltip v-model="capsTooltip" :tabindex="-1" content="大写锁定已打开" manual placement="left"> <el-tooltip v-model="capsTooltip" :tabindex="-1" content="大写锁定已打开" manual placement="left">
<span class="svg-container"> <span class="svg-container">
@ -14,6 +15,7 @@
</el-tooltip> </el-tooltip>
<el-input v-model="form.pwd" placeholder="请输入密码" type="password" :maxlength="20"/> <el-input v-model="form.pwd" placeholder="请输入密码" type="password" :maxlength="20"/>
</el-form-item> </el-form-item>
<el-form-item prop="repwd"> <el-form-item prop="repwd">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon="password"/> <svg-icon icon="password"/>
@ -26,6 +28,7 @@
@keyup.enter.native="register" @keyup.enter.native="register"
/> />
</el-form-item> </el-form-item>
<el-button <el-button
:loading="loading" :loading="loading"
class="submit-btn" class="submit-btn"
@ -34,6 +37,7 @@
> >
{{loading ? '注 册 中...' : '注 册'}} {{loading ? '注 册 中...' : '注 册'}}
</el-button> </el-button>
<div class="flex" style="margin-top: 20px"> <div class="flex" style="margin-top: 20px">
<p/> <p/>
<el-button type="text" @click="login">已有账户登陆</el-button> <el-button type="text" @click="login">已有账户登陆</el-button>
@ -49,6 +53,7 @@
export default { export default {
name: "RegisterForm", name: "RegisterForm",
data() { data() {
const validateName = (r, v, c) => { const validateName = (r, v, c) => {
checkName(this.form.username) checkName(this.form.username)
@ -82,6 +87,7 @@
loading: false loading: false
} }
}, },
methods: { methods: {
register() { register() {
if (this.loading) return if (this.loading) return
@ -96,23 +102,29 @@
.catch(() => this.loading = false) .catch(() => this.loading = false)
}) })
}, },
login() { login() {
!this.loading && this.$router.push('/login') !this.loading && this.$router.push('/login')
}, },
capsLockTip({keyCode}) { capsLockTip({keyCode}) {
if (keyCode === 20) this.capsTooltip = !this.capsTooltip if (keyCode === 20) this.capsTooltip = !this.capsTooltip
}, },
addEvent() { addEvent() {
document.addEventListener('keyup', this.capsLockTip) document.addEventListener('keyup', this.capsLockTip)
}, },
removeEvent() { removeEvent() {
document.removeEventListener('keyup', this.addCapsLockEvent) document.removeEventListener('keyup', this.addCapsLockEvent)
} }
}, },
mounted() { mounted() {
this.addEvent() this.addEvent()
this.$nextTick(() => this.$refs.username.focus()) this.$nextTick(() => this.$refs.username.focus())
}, },
beforeDestroy() { beforeDestroy() {
this.removeEvent() this.removeEvent()
} }

@ -11,13 +11,17 @@
{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 (

@ -1,11 +1,13 @@
<template> <template>
<div class="login-page"> <div class="login-page">
<canvas id="login-background"/> <canvas id="login-background"/>
<div class="login-container" @click.stop> <div class="login-container" @click.stop>
<div class="title"> <div class="title">
{{title}} {{title}}
<set-animation :value="animation" custom-class="set-animation" @select="setAnimation"/> <set-animation :value="animation" custom-class="set-animation" @select="setAnimation"/>
</div> </div>
<component :is="component"/> <component :is="component"/>
</div> </div>
</div> </div>
@ -21,23 +23,28 @@
export default { export default {
name: 'login', name: 'login',
components: {LoginForm, RegisterForm, SetAnimation}, components: {LoginForm, RegisterForm, SetAnimation},
data() { data() {
return { return {
title, title,
animationInstance: null animationInstance: null
} }
}, },
computed: { computed: {
...mapState('app', { ...mapState('app', {
device: state => state.device, device: state => state.device,
animation: state => state.loginBackgroundAnimation animation: state => state.loginBackgroundAnimation
}), }),
component() { component() {
const formType = this.$route.path.substring(1) const formType = this.$route.path.substring(1)
return `${[...formType].join('')}-form` return `${[...formType].join('')}-form`
} }
}, },
methods: { methods: {
clearAnimation() { clearAnimation() {
if (this.animationInstance) { if (this.animationInstance) {
@ -45,6 +52,7 @@
this.animationInstance = null this.animationInstance = null
} }
}, },
setAnimation(value) { setAnimation(value) {
this.clearAnimation() this.clearAnimation()
this.$store.commit('app/loginBackgroundAnimation', value) this.$store.commit('app/loginBackgroundAnimation', value)
@ -53,10 +61,12 @@
.then(_ => this.animationInstance = new _.default(document.getElementById('login-background'))) .then(_ => this.animationInstance = new _.default(document.getElementById('login-background')))
} }
}, },
mounted() { mounted() {
// //
this.device !== 'mobile' && this.setAnimation(this.animation) this.device !== 'mobile' && this.setAnimation(this.animation)
}, },
beforeDestroy() { beforeDestroy() {
this.clearAnimation() this.clearAnimation()
this.$message.closeAll() this.$message.closeAll()

@ -8,6 +8,7 @@
} }
else this.$router.replace({path: '/' + params.path, query}) else this.$router.replace({path: '/' + params.path, query})
}, },
render: h => h() render: h => h()
} }
</script> </script>

@ -4,12 +4,14 @@
<script> <script>
import {logic, resize} from "@/mixins/chart" import {logic, resize} from "@/mixins/chart"
import {getDailyFinishOrder} from '@/api/statistic/index' import {getDailyFinishOrder} from '@/api/statistic'
import {timeFormat} from "@/utils" import {timeFormat} from "@/utils"
export default { export default {
name: "DailyFinishOrderStat", name: "DailyFinishOrderStat",
mixins: [resize, logic], mixins: [resize, logic],
methods: { methods: {
init() { init() {
if (this.loading) return if (this.loading) return
@ -28,6 +30,7 @@
}) })
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
setOptions({time, purchase, sell}) { setOptions({time, purchase, sell}) {
this.chart.setOption({ this.chart.setOption({
title: { title: {

@ -4,12 +4,14 @@
<script> <script>
import {logic, resize} from "@/mixins/chart" import {logic, resize} from "@/mixins/chart"
import {getDailyProfitStat} from '@/api/statistic/index' import {getDailyProfitStat} from '@/api/statistic'
import {timeFormat} from "@/utils" import {timeFormat} from "@/utils"
export default { export default {
name: "DailyProfitStat", name: "DailyProfitStat",
mixins: [resize, logic], mixins: [resize, logic],
methods: { methods: {
init() { init() {
if (this.loading) return if (this.loading) return
@ -30,6 +32,7 @@
}) })
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
setOptions({time, purchase, sell, profit}) { setOptions({time, purchase, sell, profit}) {
this.chart.setOption({ this.chart.setOption({
title: { title: {

@ -3,13 +3,16 @@
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 (

@ -15,7 +15,9 @@
export default { export default {
name: 'panelGroup', name: 'panelGroup',
components: {PanelGroupItem}, components: {PanelGroupItem},
data() { data() {
return { return {
loading: false, loading: false,
@ -34,6 +36,7 @@
] ]
} }
}, },
methods: { methods: {
init() { init() {
if (this.loading) return if (this.loading) return
@ -46,10 +49,12 @@
}) })
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
jump({path}) { jump({path}) {
if (!isEmpty(path) && auth(path)) this.$router.push(path) if (!isEmpty(path) && auth(path)) this.$router.push(path)
} }
}, },
mounted() { mounted() {
this.init() this.init()
} }

@ -14,7 +14,9 @@
export default { export default {
name: "TotalProfitGoods", name: "TotalProfitGoods",
components: {PieChart}, components: {PieChart},
data() { data() {
return { return {
loading: false, loading: false,
@ -32,13 +34,16 @@
} }
} }
}, },
methods: { methods: {
getTitle(type) { getTitle(type) {
return this[type].title return this[type].title
}, },
getData(type) { getData(type) {
return this[type].data return this[type].data
}, },
init() { init() {
if (this.loading) return if (this.loading) return
this.loading = true this.loading = true
@ -59,6 +64,7 @@
.finally(() => this.loading = false) .finally(() => this.loading = false)
} }
}, },
mounted() { mounted() {
this.init() this.init()
} }

@ -22,6 +22,7 @@
export default { export default {
name: 'index', name: 'index',
components: {PanelGroup, DailyProfitStat, DailyFinishOrderStat, TotalProfitGoods} components: {PanelGroup, DailyProfitStat, DailyFinishOrderStat, TotalProfitGoods}
} }
</script> </script>

@ -51,6 +51,7 @@
</dialog-form-item> </dialog-form-item>
</el-row> </el-row>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button> <el-button v-if="canSave" size="small" type="primary" @click="save"> </el-button>
@ -73,8 +74,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm, DialogFormItem, TinymceEditor, UserSelector}, components: {DialogForm, DialogFormItem, TinymceEditor, UserSelector},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
type: {type: String, default: 'see'}, type: {type: String, default: 'see'},
@ -84,6 +88,7 @@
}, },
baseUrl: String baseUrl: String
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -111,6 +116,7 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
if (isEmpty(this.type)) return '' if (isEmpty(this.type)) return ''
@ -142,6 +148,7 @@
&& this.form.status === 1 && this.form.status === 1
}, },
}, },
methods: { methods: {
open() { open() {
if (this.type === 'add') return if (this.type === 'add') return

@ -18,6 +18,7 @@
</el-select> </el-select>
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
@ -25,6 +26,7 @@
<el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button>
<el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button> <el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @row-click="row=$event"> <abstract-table :data="tableData" @row-click="row=$event">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
@ -43,6 +45,7 @@
<template v-slot="{row}">{{row.ptime | timestamp2Date}}</template> <template v-slot="{row}">{{row.ptime | timestamp2Date}}</template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -75,8 +78,11 @@
export default { export default {
name: "messageManagement", name: "messageManagement",
mixins: [tableMixin], mixins: [tableMixin],
components: {SearchForm, SearchFormItem, EditDialog}, components: {SearchForm, SearchFormItem, EditDialog},
data() { data() {
return { return {
baseUrl: '/message/manage', baseUrl: '/message/manage',
@ -90,17 +96,21 @@
regionDialog: false regionDialog: false
} }
}, },
computed: { computed: {
canAdd() { canAdd() {
return auth(this.baseUrl + '/add') return auth(this.baseUrl + '/add')
}, },
canUpdate() { canUpdate() {
return auth(this.baseUrl + '/update') return auth(this.baseUrl + '/update')
}, },
canDel() { canDel() {
return auth(this.baseUrl + '/del') return auth(this.baseUrl + '/del')
} }
}, },
methods: { methods: {
transformStatus(status) { transformStatus(status) {
switch (status) { switch (status) {
@ -112,6 +122,7 @@
return '已撤回' return '已撤回'
} }
}, },
search() { search() {
if (this.config.loading) return if (this.config.loading) return
this.config.loading = true this.config.loading = true
@ -124,20 +135,24 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
add() { add() {
this.type = 'add' this.type = 'add'
this.editDialog = true this.editDialog = true
}, },
see() { see() {
if (isEmpty(this.row)) return elError('请选择要查看的消息') if (isEmpty(this.row)) return elError('请选择要查看的消息')
this.type = 'see' this.type = 'see'
this.editDialog = true this.editDialog = true
}, },
edit() { edit() {
if (isEmpty(this.row)) return elError('请选择要编辑的消息') if (isEmpty(this.row)) return elError('请选择要编辑的消息')
this.type = 'edit' this.type = 'edit'
this.editDialog = true this.editDialog = true
}, },
del() { del() {
if (isEmpty(this.row)) return elError('请选择要删除的消息') if (isEmpty(this.row)) return elError('请选择要删除的消息')
if (this.row.status !== 0) return elError('只有状态为【拟定】时才能删除') if (this.row.status !== 0) return elError('只有状态为【拟定】时才能删除')

@ -4,6 +4,7 @@
{{title}} {{title}}
<document-history :data="history" :type="type" @show="getHistory"/> <document-history :data="history" :type="type" @show="getHistory"/>
</template> </template>
<el-form <el-form
ref="form" ref="form"
:model="form" :model="form"
@ -14,7 +15,7 @@
status-icon status-icon
> >
<el-row :gutter="20"> <el-row :gutter="20">
<dialog-form-item label="单 号:" prop="id"> <dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/> <el-input :value="form.id" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="采购订单:" prop="pid"> <dialog-form-item label="采购订单:" prop="pid">
@ -22,16 +23,16 @@
<el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button> <el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button>
</el-input> </el-input>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建人:" prop="cname"> <dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/> <el-input :value="form.cname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建时间:" prop="ctime"> <dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核人:" prop="vname"> <dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/> <el-input :value="form.vname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核时间:" prop="vtime"> <dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="附 件:" full> <dialog-form-item label="附 件:" full>
@ -54,6 +55,7 @@
</dialog-form-item> </dialog-form-item>
</el-row> </el-row>
</el-form> </el-form>
<el-table :data="form.data"> <el-table :data="form.data">
<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"/>
@ -62,6 +64,7 @@
<el-input-number <el-input-number
v-if="canSave" v-if="canSave"
v-model="row.num" v-model="row.num"
controls-position="right"
:min="0" :min="0"
size="small" size="small"
@change="(nv,ov)=>changeInboundNum(nv,ov,row)" @change="(nv,ov)=>changeInboundNum(nv,ov,row)"
@ -70,8 +73,9 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<document-steps :status="form.status" :type="type"/> <document-steps :status="form.status" :type="type"/>
<order-selector v-model="parentDialog" @select="selectParent"/>
<template v-slot:footer> <template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span> <span v-if="form.status===2" class="seal">已审核</span>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
@ -81,6 +85,8 @@
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button> <el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button> <el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template> </template>
<order-selector v-model="parentDialog" @select="selectParent"/>
</dialog-form> </dialog-form>
</template> </template>
@ -95,8 +101,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [bizDocumentDialogMixin], mixins: [bizDocumentDialogMixin],
components: {OrderSelector}, components: {OrderSelector},
data() { data() {
return { return {
documentName: '采购入库单', documentName: '采购入库单',
@ -113,11 +122,13 @@
parentSubList: [] parentSubList: []
} }
}, },
methods: { methods: {
afterInit() { afterInit() {
if (this.type !== 'edit') return if (this.type !== 'edit') return
return getParentSubById(this.form.pid).then(data => this.parentSubList = data) return getParentSubById(this.form.pid).then(data => this.parentSubList = data)
}, },
selectParent(id, sub) { selectParent(id, sub) {
this.parentSubList = sub this.parentSubList = sub
this.form.pid = id this.form.pid = id
@ -128,12 +139,14 @@
num: i.remain_num num: i.remain_num
})) }))
}, },
changeInboundNum(nv, ov, row) { changeInboundNum(nv, ov, row) {
let parentSub = this.parentSubList.find(i => i.cid === row.cid) let parentSub = this.parentSubList.find(i => i.cid === row.cid)
if (!parentSub || nv > parentSub.remain_num) { if (!parentSub || nv > parentSub.remain_num) {
return elAlert(`${row.cname}的入库数量超出采购数量`, () => row.num = ov) return elAlert(`${row.cname}的入库数量超出采购数量`, () => row.num = ov)
} }
}, },
validate() { validate() {
if (this.type === 'edit' && isEmpty(this.form.id)) { if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试' return '属性缺失,请关闭弹窗刷新重试'

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择采购订单" title="选择采购订单"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"
@ -14,6 +14,7 @@
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @expand-change="getSubList"> <abstract-table :data="tableData" @expand-change="getSubList">
<el-table-column align="center" type="expand"> <el-table-column align="center" type="expand">
@ -73,9 +74,13 @@
export default { export default {
name: "OrderSelector", name: "OrderSelector",
mixins: [dialogMixin, tableMixin], mixins: [dialogMixin, tableMixin],
components: {LinerProgress}, components: {LinerProgress},
props: {value: Boolean}, props: {value: Boolean},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -84,6 +89,7 @@
} }
} }
}, },
methods: { methods: {
search() { search() {
if (!this.value || this.config.loading) return if (!this.value || this.config.loading) return
@ -101,6 +107,7 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
getSubList(row) { getSubList(row) {
if (row._loaded || row._loading) return if (row._loaded || row._loading) return
row._loading = true row._loading = true
@ -111,11 +118,13 @@
}) })
.finally(() => row._loading = false) .finally(() => row._loading = false)
}, },
confirm(row) { confirm(row) {
if (row._selection.length <= 0) return elError('请选择要入库的商品') if (row._selection.length <= 0) return elError('请选择要入库的商品')
this.$emit('select', row.id, row._selection) this.$emit('select', row.id, row._selection)
this.cancel() this.cancel()
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.tableData = [] this.tableData = []
@ -123,6 +132,7 @@
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.el-table { .el-table {
.nets-table-btn { .nets-table-btn {

@ -39,6 +39,7 @@
</el-select> </el-select>
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
@ -48,6 +49,7 @@
<el-button v-if="canExport" icon="el-icon-download" size="small" type="info" @click="downloadExcel"> <el-button v-if="canExport" icon="el-icon-download" size="small" type="info" @click="downloadExcel">
</el-button> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table <abstract-table
:data="tableData" :data="tableData"
@ -110,8 +112,11 @@
export default { export default {
name: "purchaseInbound", name: "purchaseInbound",
mixins: [documentTableMixin], mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem}, components: {EditDialog, SearchForm, SearchFormItem},
data() { data() {
return { return {
baseUrl: '/purchase/inbound', baseUrl: '/purchase/inbound',
@ -133,6 +138,7 @@
}, },
} }
}, },
methods: { methods: {
mergeSearchForm() { mergeSearchForm() {
return { return {

@ -4,6 +4,7 @@
{{title}} {{title}}
<document-history :data="history" :type="type" @show="getHistory"/> <document-history :data="history" :type="type" @show="getHistory"/>
</template> </template>
<el-form <el-form
ref="form" ref="form"
:model="form" :model="form"
@ -14,7 +15,7 @@
status-icon status-icon
> >
<el-row :gutter="20"> <el-row :gutter="20">
<dialog-form-item label="单 号:" prop="id"> <dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/> <el-input :value="form.id" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="供应商:" prop="sname"> <dialog-form-item label="供应商:" prop="sname">
@ -22,19 +23,19 @@
<el-button slot="append" :disabled="!canSave" @click="supplierDialog=true">选择</el-button> <el-button slot="append" :disabled="!canSave" @click="supplierDialog=true">选择</el-button>
</el-input> </el-input>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建人:" prop="cname"> <dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/> <el-input :value="form.cname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建时间:" prop="ctime"> <dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核人:" prop="vname"> <dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/> <el-input :value="form.vname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核时间:" prop="vtime"> <dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="完成时间:" prop="ftime"> <dialog-form-item v-if="form.finish===2" label="完成时间:" prop="ftime">
<el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="附 件:" full> <dialog-form-item label="附 件:" full>
@ -57,12 +58,13 @@
</dialog-form-item> </dialog-form-item>
</el-row> </el-row>
</el-form> </el-form>
<el-table ref="table" :data="form.data"> <el-table ref="table" :data="form.data">
<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="商 品">
<template v-slot="{row}"> <template v-slot="{row}">
<category-selector <category-selector
v-if="canSave" v-if="row._editable"
v-model="row.cid" v-model="row.cid"
:selected="selectedCategories" :selected="selectedCategories"
@get-name="row.cname=$event" @get-name="row.cname=$event"
@ -72,34 +74,49 @@
</el-table-column> </el-table-column>
<el-table-column align="center" label="采购数量"> <el-table-column align="center" label="采购数量">
<template v-slot="{row}"> <template v-slot="{row}">
<el-input-number v-if="canSave" v-model="row.num" :min="0" size="small"/> <el-input-number
v-if="row._editable"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span> <span v-else>{{row.num}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="采购单价"> <el-table-column align="center" label="采购单价">
<template v-slot="{row}"> <template v-slot="{row}">
<el-input-number v-if="canSave" v-model="row.price" :min="0" size="small"/> <el-input-number
v-if="row._editable"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span> <span v-else>{{row.price}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="剩余未入库" prop="remain_num"/> <el-table-column v-if="form.id" align="center" label="剩余未入库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="入库情况" width="120"> <el-table-column v-if="form.id" align="center" label="入库情况" width="120">
<template slot-scope="{row}"> <template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/> <span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部入库':'未全部入库'}} {{row.remain_num===0?'已全部入库':'未全部入库'}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column v-if="canSave" align="center" width="80"> <el-table-column v-if="canSave" align="center" label="操作" width="140">
<el-button slot="header" icon="el-icon-plus" size="small" type="text" @click="addSub"/> <template v-if="canSave" v-slot="{row,$index}">
<el-button <el-button v-if="!row._editable" type="text" @click="()=>row._editable=true">编辑</el-button>
slot-scope="d" <el-button v-else type="text" @click="()=>row._editable=false">保存</el-button>
icon="el-icon-delete" <el-button type="text" @click="()=>delSub(row,$index)">删除</el-button>
size="small" type="text" </template>
@click="delSub(d.row,d.$index)"
/>
</el-table-column> </el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button plain type="dashed" size="small" icon="el-icon-plus" @click="addSub">添加采购商品</el-button>
</div>
</el-table> </el-table>
<document-steps :status="form.status" :type="type"/> <document-steps :status="form.status" :type="type"/>
<template v-slot:footer> <template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span> <span v-if="form.status===2" class="seal">已审核</span>
<span v-if="form.finish===2" class="seal">已完成</span> <span v-if="form.finish===2" class="seal">已完成</span>
@ -162,7 +179,8 @@
cid: null, cid: null,
cname: null, cname: null,
num: 0, num: 0,
price: 0 price: 0,
_editable: true
}) })
}, },
delSub(row, index) { delSub(row, index) {
@ -184,6 +202,9 @@
index++ index++
} }
return null return null
},
afterInit() {
this.form.data.forEach(item => item.__editable = false)
} }
} }
} }

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择供应商" title="选择供应商"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择客户" title="选择客户"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"
@ -23,9 +23,11 @@
添加客户 添加客户
</el-button> </el-button>
</el-row> </el-row>
<el-scrollbar> <el-scrollbar>
<el-row class="table-container"> <el-row class="table-container">
<liner-progress :show="config.loading"/> <liner-progress :show="config.loading"/>
<abstract-table :data="tableData" @row-click="row=$event" @row-dblclick="dbclick"> <abstract-table :data="tableData" @row-click="row=$event" @row-dblclick="dbclick">
<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="name" show-overflow-tooltip/> <el-table-column align="center" label="客 户" prop="name" show-overflow-tooltip/>
@ -43,6 +45,7 @@
</template> </template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -66,9 +69,13 @@
export default { export default {
name: "CustomerSelector", name: "CustomerSelector",
mixins: [dialogMixin, tableMixin], mixins: [dialogMixin, tableMixin],
components: {LinerProgress}, components: {LinerProgress},
props: {value: Boolean}, props: {value: Boolean},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -76,11 +83,13 @@
} }
} }
}, },
computed: { computed: {
canGoToSysCustomerPage() { canGoToSysCustomerPage() {
return auth('/system/customer') return auth('/system/customer')
} }
}, },
methods: { methods: {
search() { search() {
if (!this.value || this.config.loading) return if (!this.value || this.config.loading) return
@ -93,18 +102,22 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
dbclick(row) { dbclick(row) {
this.row = row this.row = row
this.confirm() this.confirm()
}, },
confirm() { confirm() {
if (!this.row) return elError('请选择一个客户') if (!this.row) return elError('请选择一个客户')
this.$emit('select', this.row) this.$emit('select', this.row)
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.tableData = [] this.tableData = []
}, },
goToSysCustomerPage() { goToSysCustomerPage() {
this.closeDialog() this.closeDialog()
this.$emit('jump') this.$emit('jump')

@ -4,6 +4,7 @@
{{title}} {{title}}
<document-history :data="history" :type="type" @show="getHistory"/> <document-history :data="history" :type="type" @show="getHistory"/>
</template> </template>
<el-form <el-form
ref="form" ref="form"
:model="form" :model="form"
@ -14,7 +15,7 @@
status-icon status-icon
> >
<el-row :gutter="20"> <el-row :gutter="20">
<dialog-form-item label="单 号:" prop="id"> <dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/> <el-input :value="form.id" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="客 户:" prop="customer_name"> <dialog-form-item label="客 户:" prop="customer_name">
@ -22,19 +23,19 @@
<el-button slot="append" :disabled="!canSave" @click="customerDialog=true">选择</el-button> <el-button slot="append" :disabled="!canSave" @click="customerDialog=true">选择</el-button>
</el-input> </el-input>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建人:" prop="cname"> <dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/> <el-input :value="form.cname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建时间:" prop="ctime"> <dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核人:" prop="vname"> <dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/> <el-input :value="form.vname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核时间:" prop="vtime"> <dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="完成时间:" prop="ftime"> <dialog-form-item v-if="form.finish===2" label="完成时间:" prop="ftime">
<el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ftime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="附 件:" full> <dialog-form-item label="附 件:" full>
@ -57,36 +58,56 @@
</dialog-form-item> </dialog-form-item>
</el-row> </el-row>
</el-form> </el-form>
<el-table ref="table" :data="form.data"> <el-table ref="table" :data="form.data">
<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"> <el-table-column align="center" label="商品" prop="cname"/>
<template slot="header">
商品
<el-button v-if="canSave" size="small" type="text" icon="el-icon-plus" @click="stockDialog=true"/>
</template>
<template v-slot="{row}">{{row.cname}}</template>
</el-table-column>
<el-table-column align="center" label="销售数量"> <el-table-column align="center" label="销售数量">
<template v-slot="{row}"> <template v-slot="{row}">
<el-input-number v-if="canSave" v-model="row.num" :min="0" size="small"/> <el-input-number
v-if="canSave"
v-model="row.num"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.num}}</span> <span v-else>{{row.num}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="销售单价"> <el-table-column align="center" label="销售单价">
<template v-slot="{row}"> <template v-slot="{row}">
<el-input-number v-if="canSave" v-model="row.price" :min="0" size="small"/> <el-input-number
v-if="canSave"
v-model="row.price"
controls-position="right"
:min="0"
size="small"
/>
<span v-else>{{row.price}}</span> <span v-else>{{row.price}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="剩余未出库" prop="remain_num"/> <el-table-column align="center" label="剩余未出库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="出库情况" width="120"> <el-table-column v-if="form.id" align="center" label="出库情况" width="120">
<template slot-scope="{row}"> <template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/> <span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部出库':'未全部出库'}} {{row.remain_num===0?'已全部出库':'未全部出库'}}
</template> </template>
</el-table-column> </el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
<el-button
plain
type="dashed"
size="small"
icon="el-icon-plus"
@click="stockDialog=true"
>
添加销售商品
</el-button>
</div>
</el-table> </el-table>
<document-steps :status="form.status" :type="type"/> <document-steps :status="form.status" :type="type"/>
<template v-slot:footer> <template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span> <span v-if="form.status===2" class="seal">已审核</span>
<span v-if="form.finish===2" class="seal">已完成</span> <span v-if="form.finish===2" class="seal">已完成</span>
@ -99,6 +120,7 @@
</template> </template>
<stock-selector v-model="stockDialog" @select="selectStock"/> <stock-selector v-model="stockDialog" @select="selectStock"/>
<customer-selector v-model="customerDialog" @select="selectCustomer" @jump="closeDialog"/> <customer-selector v-model="customerDialog" @select="selectCustomer" @jump="closeDialog"/>
</dialog-form> </dialog-form>
</template> </template>
@ -114,8 +136,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [bizDocumentDialogMixin], mixins: [bizDocumentDialogMixin],
components: {StockSelector, CustomerSelector}, components: {StockSelector, CustomerSelector},
data() { data() {
return { return {
documentName: '销售订单', documentName: '销售订单',
@ -136,21 +161,25 @@
stockDialog: false stockDialog: false
} }
}, },
computed: { computed: {
selectedCategories() { selectedCategories() {
return this.form.data.map(i => i.cid) return this.form.data.map(i => i.cid)
} }
}, },
methods: { methods: {
selectCustomer(row) { selectCustomer(row) {
this.form.customer_id = row.id this.form.customer_id = row.id
this.form.customer_name = row.name this.form.customer_name = row.name
this.customerDialog = false this.customerDialog = false
}, },
selectStock(stocks) { selectStock(stocks) {
this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.total_num, price: 0})) this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.total_num, price: 0}))
this.stockDialog = false this.stockDialog = false
}, },
addSub() { addSub() {
this.form.data.push({ this.form.data.push({
cid: null, cid: null,
@ -160,9 +189,11 @@
remain_num: 0 remain_num: 0
}) })
}, },
delSub(row, index) { delSub(row, index) {
this.form.data.splice(index, 1) this.form.data.splice(index, 1)
}, },
validate() { validate() {
if (this.form.data.length <= 0) return '销售商品不能为空' if (this.form.data.length <= 0) return '销售商品不能为空'
if (this.type === 'edit' && isEmpty(this.form.id)) { if (this.type === 'edit' && isEmpty(this.form.id)) {

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择库存商品" title="选择库存商品"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"
@ -15,8 +15,10 @@
<el-button size="small" type="primary" @click="confirm"> </el-button> <el-button size="small" type="primary" @click="confirm"> </el-button>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
</el-row> </el-row>
<el-row class="table-container"> <el-row class="table-container">
<liner-progress :show="config.loading"/> <liner-progress :show="config.loading"/>
<el-table <el-table
ref="table" ref="table"
:data="tableData" :data="tableData"
@ -28,6 +30,7 @@
<el-table-column align="center" label="商品分类" prop="cname" show-overflow-tooltip/> <el-table-column align="center" label="商品分类" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="库存数量" prop="total_num" show-overflow-tooltip/> <el-table-column align="center" label="库存数量" prop="total_num" show-overflow-tooltip/>
</el-table> </el-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -50,14 +53,19 @@
export default { export default {
name: "StockSelector", name: "StockSelector",
mixins: [dialogMixin, tableMixin], mixins: [dialogMixin, tableMixin],
components: {LinerProgress}, components: {LinerProgress},
props: {value: Boolean}, props: {value: Boolean},
data() { data() {
return { return {
selection: [] selection: []
} }
}, },
methods: { methods: {
search() { search() {
if (!this.value || this.config.loading) return if (!this.value || this.config.loading) return
@ -70,10 +78,12 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
confirm() { confirm() {
if (this.selection.length <= 0) return elError('请选择商品') if (this.selection.length <= 0) return elError('请选择商品')
this.$emit('select', this.selection) this.$emit('select', this.selection)
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.$refs.table.clearSelection() this.$refs.table.clearSelection()

@ -55,15 +55,24 @@
/> />
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
<el-button icon="el-icon-view" size="small" type="primary" @click="see"> </el-button> <el-button icon="el-icon-view" size="small" type="primary" @click="see"> </el-button>
<el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button>
<el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button> <el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button>
<el-button v-if="canExport" icon="el-icon-download" size="small" type="info" @click="downloadExcel"> <el-button
v-if="canExport"
icon="el-icon-download"
size="small"
type="info"
@click="downloadExcel"
>
</el-button> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @row-click="row=$event" @expand-change="getSubList"> <abstract-table :data="tableData" @row-click="row=$event" @expand-change="getSubList">
<el-table-column align="center" type="expand"> <el-table-column align="center" type="expand">
@ -105,6 +114,7 @@
<template v-slot="{row}">{{row.ftime | timestamp2Date}}</template> <template v-slot="{row}">{{row.ftime | timestamp2Date}}</template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -134,8 +144,11 @@
export default { export default {
name: "sellOrder", name: "sellOrder",
mixins: [documentTableMixin], mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem}, components: {EditDialog, SearchForm, SearchFormItem},
data() { data() {
return { return {
baseUrl: '/sell/order', baseUrl: '/sell/order',
@ -163,6 +176,7 @@
} }
} }
}, },
methods: { methods: {
mergeSearchForm() { mergeSearchForm() {
return { return {

@ -4,6 +4,7 @@
{{title}} {{title}}
<document-history :data="history" :type="type" @show="getHistory"/> <document-history :data="history" :type="type" @show="getHistory"/>
</template> </template>
<el-form <el-form
ref="form" ref="form"
:model="form" :model="form"
@ -14,7 +15,7 @@
status-icon status-icon
> >
<el-row :gutter="20"> <el-row :gutter="20">
<dialog-form-item label="单 号:" prop="id"> <dialog-form-item v-if="form.id" label="单 号:" prop="id">
<el-input :value="form.id" readonly/> <el-input :value="form.id" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="销售订单:" prop="pid"> <dialog-form-item label="销售订单:" prop="pid">
@ -22,16 +23,16 @@
<el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button> <el-button slot="append" :disabled="!canSave" @click="parentDialog=true">选择</el-button>
</el-input> </el-input>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建人:" prop="cname"> <dialog-form-item v-if="form.id" label="创建人:" prop="cname">
<el-input :value="form.cname" readonly/> <el-input :value="form.cname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="创建时间:" prop="ctime"> <dialog-form-item v-if="form.id" label="创建时间:" prop="ctime">
<el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.ctime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核人:" prop="vname"> <dialog-form-item v-if="form.status===2" label="审核人:" prop="vname">
<el-input :value="form.vname" readonly/> <el-input :value="form.vname" readonly/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="审核时间:" prop="vtime"> <dialog-form-item v-if="form.status===2" label="审核时间:" prop="vtime">
<el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/> <el-date-picker :value="form.vtime" format="yyyy-MM-dd HH:mm:ss" readonly type="date"/>
</dialog-form-item> </dialog-form-item>
<dialog-form-item label="附 件:" full> <dialog-form-item label="附 件:" full>
@ -54,6 +55,7 @@
</dialog-form-item> </dialog-form-item>
</el-row> </el-row>
</el-form> </el-form>
<el-table :data="displayTableData"> <el-table :data="displayTableData">
<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 :summary-method="summaryStock(row)"> <el-table slot-scope="{row}" :data="row.data" border show-summary :summary-method="summaryStock(row)">
@ -63,10 +65,11 @@
出库数量 出库数量
<el-button v-if="canSave" type="text" size="small" @click="openStock(row)">选择库存</el-button> <el-button v-if="canSave" type="text" size="small" @click="openStock(row)">选择库存</el-button>
</template> </template>
<template slot-scope="d"> <template v-slot="d">
<el-input-number <el-input-number
v-if="canSave" v-if="canSave"
v-model="d.row.num" v-model="d.row.num"
controls-position="right"
:min="0" :min="0"
size="small" size="small"
@change="(nv,ov)=>changeOutboundNum(nv,ov,d.row,row)" @change="(nv,ov)=>changeOutboundNum(nv,ov,d.row,row)"
@ -83,9 +86,9 @@
<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="remain_num" width="250"/> <el-table-column align="center" label="订单剩余未出库数量" prop="remain_num" width="250"/>
</el-table> </el-table>
<document-steps :status="form.status" :type="type"/> <document-steps :status="form.status" :type="type"/>
<order-selector v-model="parentDialog" @select="selectParent"/>
<stock-selector v-model="stockDialog" :cid="row?row.cid:null" @select="selectStock"/>
<template v-slot:footer> <template v-slot:footer>
<span v-if="form.status===2" class="seal">已审核</span> <span v-if="form.status===2" class="seal">已审核</span>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
@ -95,6 +98,10 @@
<el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button> <el-button v-if="canPass" size="small" type="success" @click="pass"> </el-button>
<el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button> <el-button v-if="canReject" size="small" type="danger" @click="reject"> </el-button>
</template> </template>
<order-selector v-model="parentDialog" @select="selectParent"/>
<stock-selector v-model="stockDialog" :cid="row?row.cid:null" @select="selectStock"/>
</dialog-form> </dialog-form>
</template> </template>
@ -112,8 +119,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [bizDocumentDialogMixin], mixins: [bizDocumentDialogMixin],
components: {OrderSelector, StockSelector}, components: {OrderSelector, StockSelector},
data() { data() {
return { return {
documentName: '销售出库单', documentName: '销售出库单',
@ -132,6 +142,7 @@
displayTableData: [] displayTableData: []
} }
}, },
methods: { methods: {
afterInit() { afterInit() {
if (this.type === 'add') return if (this.type === 'add') return
@ -142,6 +153,7 @@
]) ])
.then(([r1, r2]) => this.buildDisplayTableData(r1, r2)) .then(([r1, r2]) => this.buildDisplayTableData(r1, r2))
}, },
// //
buildDisplayTableData(orderSubList, stockList) { buildDisplayTableData(orderSubList, stockList) {
this.displayTableData = [] this.displayTableData = []
@ -170,14 +182,17 @@
}) })
} }
}, },
selectParent(id, sub) { selectParent(id, sub) {
this.form.pid = id this.form.pid = id
this.displayTableData = sub.map(i => ({...i, num: 0, data: []})) this.displayTableData = sub.map(i => ({...i, num: 0, data: []}))
}, },
openStock(row) { openStock(row) {
this.row = row this.row = row
this.stockDialog = true this.stockDialog = true
}, },
selectStock(stocks) { selectStock(stocks) {
let res = [] let res = []
let outboundNum = 0 let outboundNum = 0
@ -199,6 +214,7 @@
this.row.data = res this.row.data = res
this.stockDialog = false this.stockDialog = false
}, },
summaryStock(row) { summaryStock(row) {
return ({data}) => { return ({data}) => {
let sum = ['合计', 0, '', ''] let sum = ['合计', 0, '', '']
@ -209,6 +225,7 @@
return sum return sum
} }
}, },
changeOutboundNum(nv, ov, row, displayTableRow) { changeOutboundNum(nv, ov, row, displayTableRow) {
if (nv > row.max_num) { if (nv > row.max_num) {
return elAlert(`${row.cname}的出库数量超出库存数量`, () => row.num = ov) return elAlert(`${row.cname}的出库数量超出库存数量`, () => row.num = ov)
@ -226,6 +243,7 @@
return elAlert(`${displayTableRow.cname}的出库数量超出销售数量`, () => row.num = ov) return elAlert(`${displayTableRow.cname}的出库数量超出销售数量`, () => row.num = ov)
} }
}, },
validate() { validate() {
if (this.type === 'edit' && isEmpty(this.form.id)) { if (this.type === 'edit' && isEmpty(this.form.id)) {
return '属性缺失,请关闭弹窗刷新重试' return '属性缺失,请关闭弹窗刷新重试'

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择销售订单" title="选择销售订单"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"
@ -14,6 +14,7 @@
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @expand-change="getSubList"> <abstract-table :data="tableData" @expand-change="getSubList">
<el-table-column align="center" type="expand"> <el-table-column align="center" type="expand">
@ -73,9 +74,13 @@
export default { export default {
name: "OrderSelector", name: "OrderSelector",
mixins: [dialogMixin, tableMixin], mixins: [dialogMixin, tableMixin],
components: {LinerProgress}, components: {LinerProgress},
props: {value: Boolean}, props: {value: Boolean},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -84,6 +89,7 @@
} }
} }
}, },
methods: { methods: {
search() { search() {
if (!this.value || this.config.loading) return if (!this.value || this.config.loading) return
@ -101,6 +107,7 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
getSubList(row) { getSubList(row) {
if (row._loaded || row._loading) return if (row._loaded || row._loading) return
row._loading = true row._loading = true
@ -111,11 +118,13 @@
}) })
.finally(() => row._loading = false) .finally(() => row._loading = false)
}, },
confirm(row) { confirm(row) {
if (row._selection.length <= 0) return elError('请选择要出库的商品') if (row._selection.length <= 0) return elError('请选择要出库的商品')
this.$emit('select', row.id, row._selection) this.$emit('select', row.id, row._selection)
this.cancel() this.cancel()
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.tableData = [] this.tableData = []
@ -123,6 +132,7 @@
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.el-table { .el-table {
.nets-table-btn { .nets-table-btn {

@ -4,7 +4,7 @@
:visible="value" :visible="value"
append-to-body append-to-body
title="选择库存商品" title="选择库存商品"
width="50%" width="70%"
top="50px" top="50px"
@close="cancel" @close="cancel"
@open="search" @open="search"
@ -15,8 +15,10 @@
<el-button size="small" type="primary" @click="confirm"> </el-button> <el-button size="small" type="primary" @click="confirm"> </el-button>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
</el-row> </el-row>
<el-row class="table-container"> <el-row class="table-container">
<liner-progress :show="loading"/> <liner-progress :show="loading"/>
<el-table <el-table
ref="table" ref="table"
:data="tableData" :data="tableData"
@ -43,13 +45,17 @@
export default { export default {
name: "StockSelector", name: "StockSelector",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {LinerProgress}, components: {LinerProgress},
props: { props: {
value: Boolean, value: Boolean,
cid: Number, cid: Number,
row: Object row: Object
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -57,6 +63,7 @@
selection: [] selection: []
} }
}, },
methods: { methods: {
search() { search() {
if (!this.value || this.loading) return if (!this.value || this.loading) return
@ -66,10 +73,12 @@
.then(data => this.tableData = data) .then(data => this.tableData = data)
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
confirm() { confirm() {
if (this.selection.length <= 0) return elError('请选择商品') if (this.selection.length <= 0) return elError('请选择商品')
this.$emit('select', this.selection) this.$emit('select', this.selection)
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.$refs.table.clearSelection() this.$refs.table.clearSelection()

@ -39,15 +39,24 @@
</el-select> </el-select>
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
<el-button icon="el-icon-view" size="small" type="primary" @click="see"> </el-button> <el-button icon="el-icon-view" size="small" type="primary" @click="see"> </el-button>
<el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button>
<el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button> <el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button>
<el-button v-if="canExport" icon="el-icon-download" size="small" type="info" @click="downloadExcel"> <el-button
v-if="canExport"
icon="el-icon-download"
size="small"
type="info"
@click="downloadExcel"
>
</el-button> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @row-click="row=$event" @expand-change="getSubList"> <abstract-table :data="tableData" @row-click="row=$event" @expand-change="getSubList">
<el-table-column align="center" type="expand"> <el-table-column align="center" type="expand">
@ -77,6 +86,7 @@
</template> </template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -106,8 +116,11 @@
export default { export default {
name: "sellOutbound", name: "sellOutbound",
mixins: [documentTableMixin], mixins: [documentTableMixin],
components: {EditDialog, SearchForm, SearchFormItem}, components: {EditDialog, SearchForm, SearchFormItem},
data() { data() {
return { return {
baseUrl: '/sell/outbound', baseUrl: '/sell/outbound',
@ -129,6 +142,7 @@
} }
} }
}, },
methods: { methods: {
mergeSearchForm() { mergeSearchForm() {
return { return {

@ -1,6 +1,7 @@
<template> <template>
<dialog-form :value="value" :loading="false" :title="title" width="70%" @close="cancel" @open="search"> <dialog-form :value="value" :loading="false" :title="title" width="70%" @close="cancel" @open="search">
<liner-progress :show="loading"/> <liner-progress :show="loading"/>
<abstract-table :data="tableData" border show-summary :summary-method="summary" :span-method="span"> <abstract-table :data="tableData" border show-summary :summary-method="summary" :span-method="span">
<el-table-column align="center" label="采购订单" show-overflow-tooltip> <el-table-column align="center" label="采购订单" show-overflow-tooltip>
<router-link <router-link
@ -41,15 +42,20 @@
export default { export default {
name: "DetailDialog", name: "DetailDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {AbstractTable, LinerProgress, DialogForm}, components: {AbstractTable, LinerProgress, DialogForm},
props: {value: Boolean, title: String, cid: Number}, props: {value: Boolean, title: String, cid: Number},
data() { data() {
return { return {
loading: false, loading: false,
tableData: [] tableData: []
} }
}, },
methods: { methods: {
summary({data}) { summary({data}) {
let sum = ['合计', '', '', '', 0, 0] let sum = ['合计', '', '', '', 0, 0]
@ -59,11 +65,13 @@
}) })
return sum return sum
}, },
span({row, column, rowIndex, columnIndex}) { span({row, column, rowIndex, columnIndex}) {
if (columnIndex === 0 || columnIndex === 1) { if (columnIndex === 0 || columnIndex === 1) {
return row._span return row._span
} }
}, },
search() { search() {
this.tableData = [] this.tableData = []
if (!this.value || isEmpty(this.cid) || this.loading) return if (!this.value || isEmpty(this.cid) || this.loading) return
@ -75,6 +83,7 @@
}) })
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
prepareData(data) { prepareData(data) {
data.sort((a, b) => { data.sort((a, b) => {
if (a.cgddid > b.cgddid) return -1 if (a.cgddid > b.cgddid) return -1
@ -98,6 +107,7 @@
} }
} }
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.tableData = [] this.tableData = []
@ -105,6 +115,7 @@
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.el-table { .el-table {
a { a {

@ -33,10 +33,12 @@
/> />
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button icon="el-icon-download" size="small" type="info" @click="downloadExcel"> </el-button> <el-button icon="el-icon-download" size="small" type="info" @click="downloadExcel"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" show-summary :summary-method="summary"> <abstract-table :data="tableData" show-summary :summary-method="summary">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
@ -49,6 +51,7 @@
</template> </template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -80,8 +83,11 @@
export default { export default {
name: "currentStock", name: "currentStock",
mixins: [tableMixin], mixins: [tableMixin],
components: {SearchForm, SearchFormItem, CategoryTree, DetailDialog}, components: {SearchForm, SearchFormItem, CategoryTree, DetailDialog},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -113,14 +119,17 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
return this.row ? `库存详细(${this.row.cname})` : '' return this.row ? `库存详细(${this.row.cname})` : ''
}, },
cid() { cid() {
return this.row ? this.row.cid : null return this.row ? this.row.cid : null
} }
}, },
methods: { methods: {
summary({data}) { summary({data}) {
let sum = ['合计', '', '', 0] let sum = ['合计', '', '', 0]
@ -129,13 +138,16 @@
}) })
return sum return sum
}, },
filterNode(value, data) { filterNode(value, data) {
if (isEmpty(value)) return true if (isEmpty(value)) return true
return data.name.includes(value) return data.name.includes(value)
}, },
filter(v) { filter(v) {
this.$refs.tree.$refs.tree.filter(v) this.$refs.tree.$refs.tree.filter(v)
}, },
mergeSearchForm() { mergeSearchForm() {
return { return {
...this.searchForm, ...this.searchForm,
@ -143,6 +155,7 @@
endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null
} }
}, },
search() { search() {
if (this.config.loading) return if (this.config.loading) return
this.config.loading = true this.config.loading = true
@ -153,26 +166,31 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
downloadExcel() { downloadExcel() {
exportExcel(baseUrl + '/export', this.mergeSearchForm(), this.excel) exportExcel(baseUrl + '/export', this.mergeSearchForm(), this.excel)
}, },
nodeClick(obj) { nodeClick(obj) {
const ids = getNodeId(obj.children) const ids = getNodeId(obj.children)
ids.unshift(obj.id) ids.unshift(obj.id)
this.searchForm.cids = ids.join(',') this.searchForm.cids = ids.join(',')
this.temp.cname = obj.name this.temp.cname = obj.name
}, },
clearCidSearch() { clearCidSearch() {
this.searchForm.cids = null this.searchForm.cids = null
this.temp.cname = null this.temp.cname = null
let tree = this.$refs.tree.$refs.tree let tree = this.$refs.tree.$refs.tree
tree.setCurrentKey() tree.setCurrentKey()
}, },
more(row) { more(row) {
this.row = row this.row = row
this.detailDialog = true this.detailDialog = true
} }
}, },
created() { created() {
this.filter = debounce(this.filter, 500) this.filter = debounce(this.filter, 500)
} }

@ -43,6 +43,7 @@
export default { export default {
props: ['list'], props: ['list'],
data() { data() {
let typeValidate = (r, v, c) => { let typeValidate = (r, v, c) => {
if (v === 1 && this.hasChildren) c('该分类下已有子节点') if (v === 1 && this.hasChildren) c('该分类下已有子节点')
@ -69,10 +70,12 @@
} }
} }
}, },
computed: { computed: {
show() { show() {
return this.list() && (this.type === 'add' || ['see', 'edit'].includes(this.type) && this.list().currentCategory) return this.list() && (this.type === 'add' || ['see', 'edit'].includes(this.type) && this.list().currentCategory)
}, },
confirmMessage() { confirmMessage() {
switch (this.type) { switch (this.type) {
case 'add': case 'add':
@ -84,6 +87,7 @@
} }
} }
}, },
methods: { methods: {
add(parent) { add(parent) {
this.title = '添加新分类' this.title = '添加新分类'
@ -94,12 +98,14 @@
this.form.type = 0 this.form.type = 0
this.hasChildren = false this.hasChildren = false
}, },
see(current, parent) { see(current, parent) {
this.title = `分类信息(${current.name})` this.title = `分类信息(${current.name})`
this.parentObj = parent this.parentObj = parent
this.type = 'see' this.type = 'see'
mergeObj(this.form, current) mergeObj(this.form, current)
}, },
edit(current, parent) { edit(current, parent) {
this.title = `编辑分类(${current.name})` this.title = `编辑分类(${current.name})`
this.parentObj = parent this.parentObj = parent
@ -107,6 +113,7 @@
mergeObj(this.form, current) mergeObj(this.form, current)
this.hasChildren = current.children.length > 0 this.hasChildren = current.children.length > 0
}, },
confirm() { confirm() {
this.$refs.form.validate(v => { this.$refs.form.validate(v => {
if (!v) return if (!v) return
@ -118,11 +125,13 @@
}) })
}) })
}, },
cancel() { cancel() {
this.type = 'none' this.type = 'none'
this.clearForm() this.clearForm()
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
clearForm() { clearForm() {
this.form.id = null this.form.id = null
this.form.pid = 0 this.form.pid = 0
@ -132,6 +141,7 @@
this.hasChildren = false this.hasChildren = false
} }
}, },
mounted() { mounted() {
waitUntilSuccess( waitUntilSuccess(
() => !isEmpty(this.list()), () => !isEmpty(this.list()),
@ -140,6 +150,7 @@
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.edit-form { .edit-form {
width: 85%; width: 85%;

@ -22,7 +22,9 @@
export default { export default {
components: {ContextMenuItem, ContextMenu, CategoryTree}, components: {ContextMenuItem, ContextMenu, CategoryTree},
props: ['form'], props: ['form'],
data() { data() {
return { return {
loading: false, loading: false,
@ -35,12 +37,14 @@
} }
} }
}, },
computed: { computed: {
canAdd() { canAdd() {
return !this.currentCategory return !this.currentCategory
|| this.currentCategory.type === 0 && this.currentCategory.level < this.maxLevel || this.currentCategory.type === 0 && this.currentCategory.level < this.maxLevel
} }
}, },
methods: { methods: {
get() { get() {
this.loading = true this.loading = true
@ -50,16 +54,20 @@
.then(data => this.$store.commit('dataCache/categories', data)) .then(data => this.$store.commit('dataCache/categories', data))
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
add() { add() {
this.$emit('add', this.currentCategory) this.$emit('add', this.currentCategory)
}, },
see(obj, node) { see(obj, node) {
this.currentCategory = {...obj, level: node.level} this.currentCategory = {...obj, level: node.level}
this.$emit('see', this.currentCategory, node.parent ? node.parent.data : null) this.$emit('see', this.currentCategory, node.parent ? node.parent.data : null)
}, },
edit() { edit() {
this.$emit('edit', this.currentCategory, this.currentCategory.parent) this.$emit('edit', this.currentCategory, this.currentCategory.parent)
}, },
del() { del() {
if (isEmpty(this.currentCategory)) return elError('请选择要删除的分类') if (isEmpty(this.currentCategory)) return elError('请选择要删除的分类')
if (this.currentCategory.children.length > 0) { if (this.currentCategory.children.length > 0) {
@ -73,10 +81,12 @@
}) })
.then(() => this.commitSuccess('删除成功')) .then(() => this.commitSuccess('删除成功'))
}, },
commitSuccess(msg) { commitSuccess(msg) {
elSuccess(msg) elSuccess(msg)
this.get() this.get()
}, },
openContextMenu(e, obj, node) { openContextMenu(e, obj, node) {
e.preventDefault() e.preventDefault()
this.currentCategory = obj ? { this.currentCategory = obj ? {
@ -91,6 +101,7 @@
this.contextmenu.show = true this.contextmenu.show = true
} }
}, },
mounted() { mounted() {
this.$el.querySelector(".el-card__body").addEventListener('contextmenu', this.openContextMenu) this.$el.querySelector(".el-card__body").addEventListener('contextmenu', this.openContextMenu)
waitUntilSuccess( waitUntilSuccess(
@ -98,11 +109,13 @@
() => this.form().$on('commit-success', this.commitSuccess) () => this.form().$on('commit-success', this.commitSuccess)
) )
}, },
beforeDestroy() { beforeDestroy() {
this.$el.querySelector(".el-card__body").removeEventListener('contextmenu', this.openContextMenu) this.$el.querySelector(".el-card__body").removeEventListener('contextmenu', this.openContextMenu)
} }
} }
</script> </script>
<style scoped> <style scoped>
.card-container { .card-container {
min-width: 250px; min-width: 250px;

@ -17,6 +17,7 @@
export default { export default {
name: "categorySetting", name: "categorySetting",
components: {CategoryList, EditForm} components: {CategoryList, EditForm}
} }
</script> </script>

@ -45,6 +45,7 @@
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button> <el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button>
@ -62,8 +63,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm, RegionSelector}, components: {DialogForm, RegionSelector},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
type: {type: String, default: 'see'}, type: {type: String, default: 'see'},
@ -72,6 +76,7 @@
default: () => ({}) default: () => ({})
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -96,6 +101,7 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
if (isEmpty(this.type)) return '' if (isEmpty(this.type)) return ''
@ -108,6 +114,7 @@
return '编辑客户' return '编辑客户'
} }
}, },
confirmMessage() { confirmMessage() {
switch (this.type) { switch (this.type) {
case 'add': case 'add':
@ -118,31 +125,38 @@
return '' return ''
} }
}, },
canEdit() { canEdit() {
return ['add', 'edit'].includes(this.type) return ['add', 'edit'].includes(this.type)
} }
}, },
methods: { methods: {
clearRegion() { clearRegion() {
this.form.region = null this.form.region = null
this.form.region_name = null this.form.region_name = null
}, },
selectRegion(obj) { selectRegion(obj) {
this.form.region = obj.id this.form.region = obj.id
this.form.region_name = obj.fullname this.form.region_name = obj.fullname
}, },
open() { open() {
if (this.type !== 'add') mergeObj(this.form, this.data) if (this.type !== 'add') mergeObj(this.form, this.data)
}, },
clearForm() { clearForm() {
resetObj(this.form) resetObj(this.form)
this.form.status = 1 this.form.status = 1
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.clearForm() this.clearForm()
}, },
confirm() { confirm() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(v => { this.$refs.form.validate(v => {

@ -39,12 +39,14 @@
/> />
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button size="small" type="success" @click="search"> </el-button> <el-button size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" size="small" type="primary" @click="add"> </el-button>
<el-button v-if="canUpdate" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" size="small" type="primary" @click="edit"> </el-button>
<el-button v-if="canDel" size="small" type="danger" @click="del"> </el-button> <el-button v-if="canDel" size="small" type="danger" @click="del"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @row-click="row=$event"> <abstract-table :data="tableData" @row-click="row=$event">
<el-table-column align="center" label="#" type="index" width="80"/> <el-table-column align="center" label="#" type="index" width="80"/>
@ -72,6 +74,7 @@
@current-change="pageChange" @current-change="pageChange"
/> />
</el-row> </el-row>
<edit-dialog v-model="editDialog" :data="row" :type="type" @success="success"/> <edit-dialog v-model="editDialog" :data="row" :type="type" @success="success"/>
</el-card> </el-card>
</template> </template>
@ -91,8 +94,11 @@
export default { export default {
name: "customerManagement", name: "customerManagement",
mixins: [tableMixin], mixins: [tableMixin],
components: {SearchForm, SearchFormItem, EditDialog, RegionSelector}, components: {SearchForm, SearchFormItem, EditDialog, RegionSelector},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -110,29 +116,36 @@
editDialog: false editDialog: false
} }
}, },
computed: { computed: {
canAdd() { canAdd() {
return auth(baseUrl + '/add') return auth(baseUrl + '/add')
}, },
canUpdate() { canUpdate() {
return auth(baseUrl + '/update') return auth(baseUrl + '/update')
}, },
canDel() { canDel() {
return auth(baseUrl + '/del') return auth(baseUrl + '/del')
} }
}, },
methods: { methods: {
getLimitRegion() { getLimitRegion() {
return getLimitRegion() return getLimitRegion()
}, },
clearSidSearch() { clearSidSearch() {
this.searchForm.region = null this.searchForm.region = null
this.temp.region_name = null this.temp.region_name = null
}, },
selectRegion(obj, ids) { selectRegion(obj, ids) {
this.searchForm.region = ids.join(',') this.searchForm.region = ids.join(',')
this.temp.region_name = obj.fullname this.temp.region_name = obj.fullname
}, },
mergeSearchForm() { mergeSearchForm() {
return { return {
...this.searchForm, ...this.searchForm,
@ -140,6 +153,7 @@
endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null
} }
}, },
search() { search() {
if (this.config.loading) return if (this.config.loading) return
this.config.loading = true this.config.loading = true
@ -152,15 +166,18 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
add() { add() {
this.type = 'add' this.type = 'add'
this.editDialog = true this.editDialog = true
}, },
edit() { edit() {
if (isEmpty(this.row)) return elError('请选择要编辑的客户') if (isEmpty(this.row)) return elError('请选择要编辑的客户')
this.type = 'edit' this.type = 'edit'
this.editDialog = true this.editDialog = true
}, },
del() { del() {
if (isEmpty(this.row)) return elError('请选择要删除的客户') if (isEmpty(this.row)) return elError('请选择要删除的客户')
if (this.config.operating) return if (this.config.operating) return
@ -172,6 +189,7 @@
.then(() => this.success('删除成功')) .then(() => this.success('删除成功'))
.finally(() => this.config.operating = false) .finally(() => this.config.operating = false)
}, },
success(msg) { success(msg) {
elSuccess(msg) elSuccess(msg)
this.editDialog = false this.editDialog = false

@ -21,6 +21,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button> <el-button size="small" type="primary" @click="confirm"> </el-button>
@ -37,13 +38,17 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm}, components: {DialogForm},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
type: {type: String, default: 'add'}, type: {type: String, default: 'add'},
data: {type: Object, default: () => ({})}, data: {type: Object, default: () => ({})},
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -59,6 +64,7 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
if (!this.data || isEmpty(this.type)) return '' if (!this.data || isEmpty(this.type)) return ''
@ -69,6 +75,7 @@
return `编辑部门【${this.data.name}` return `编辑部门【${this.data.name}`
} }
}, },
confirmMessage() { confirmMessage() {
if (!this.data || isEmpty(this.type)) return '' if (!this.data || isEmpty(this.type)) return ''
switch (this.type) { switch (this.type) {
@ -80,12 +87,14 @@
return '' return ''
} }
}, },
parentName() { parentName() {
if (!this.data) return '' if (!this.data) return ''
if (this.type === 'add') return this.data.fullname if (this.type === 'add') return this.data.fullname
else return this.data.parentName else return this.data.parentName
} }
}, },
methods: { methods: {
open() { open() {
this.$nextTick(() => { this.$nextTick(() => {
@ -97,6 +106,7 @@
else this.form.pid = this.data.id else this.form.pid = this.data.id
}) })
}, },
clearForm() { clearForm() {
this.form.id = null this.form.id = null
this.form.pid = null this.form.pid = null
@ -104,10 +114,12 @@
this.form.status = 1 this.form.status = 1
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.clearForm() this.clearForm()
}, },
confirm() { confirm() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(v => { this.$refs.form.validate(v => {

@ -18,13 +18,16 @@
export default { export default {
name: "OrgTreeView", name: "OrgTreeView",
components: {OrgTree}, components: {OrgTree},
props: { props: {
data: {type: Object, default: () => ({})}, data: {type: Object, default: () => ({})},
horizontal: Boolean, horizontal: Boolean,
collapsable: Boolean, collapsable: Boolean,
zoom: {type: Number, default: 1}, zoom: {type: Number, default: 1},
}, },
data() { data() {
return { return {
orgTreeOffsetLeft: 0, orgTreeOffsetLeft: 0,
@ -37,6 +40,7 @@
expandAll: true expandAll: true
} }
}, },
computed: { computed: {
orgTreeStyle() { orgTreeStyle() {
return { return {
@ -46,6 +50,7 @@
} }
} }
}, },
methods: { methods: {
mousedownView(event) { mousedownView(event) {
this.canMove = true this.canMove = true
@ -56,12 +61,14 @@
document.addEventListener('mousemove', this.mousemoveView) document.addEventListener('mousemove', this.mousemoveView)
document.addEventListener('mouseup', this.mouseupView) document.addEventListener('mouseup', this.mouseupView)
}, },
mousemoveView(event) { mousemoveView(event) {
if (!this.canMove) return if (!this.canMove) return
const {pageX, pageY} = event const {pageX, pageY} = event
this.orgTreeOffsetLeft = this.oldMarginLeft + pageX - this.initPageX this.orgTreeOffsetLeft = this.oldMarginLeft + pageX - this.initPageX
this.orgTreeOffsetTop = this.oldMarginTop + pageY - this.initPageY this.orgTreeOffsetTop = this.oldMarginTop + pageY - this.initPageY
}, },
mouseupView() { mouseupView() {
this.canMove = false this.canMove = false
document.removeEventListener('mousemove', this.mousemoveView) document.removeEventListener('mousemove', this.mousemoveView)

@ -5,6 +5,7 @@
组织结构树演示详情见iview-admin 组织结构树演示详情见iview-admin
</a> </a>
</div> </div>
<div class="department-outer"> <div class="department-outer">
<div class="view-box"> <div class="view-box">
<org-tree-view <org-tree-view
@ -16,11 +17,13 @@
@wheel.native.prevent="wheel" @wheel.native.prevent="wheel"
/> />
</div> </div>
<div class="tooltip-box"> <div class="tooltip-box">
<el-radio-group v-model="horizontal" fill="#909399" size="small" style="margin-right: 20px"> <el-radio-group v-model="horizontal" fill="#909399" size="small" style="margin-right: 20px">
<el-radio-button :label="true"> </el-radio-button> <el-radio-button :label="true"> </el-radio-button>
<el-radio-button :label="false"> </el-radio-button> <el-radio-button :label="false"> </el-radio-button>
</el-radio-group> </el-radio-group>
<el-button <el-button
circle circle
icon="el-icon-refresh" icon="el-icon-refresh"
@ -30,9 +33,11 @@
type="info" type="info"
@click="search" @click="search"
/> />
<zoom-control v-model="zoom" :max="200" :min="20"/> <zoom-control v-model="zoom" :max="200" :min="20"/>
</div> </div>
</div> </div>
<context-menu <context-menu
v-if="canAdd||canUpdate||canDel" v-if="canAdd||canUpdate||canDel"
v-model="contextmenu.show" v-model="contextmenu.show"
@ -43,6 +48,7 @@
<context-menu-item v-show="canUpdate" @click="update">编辑部门</context-menu-item> <context-menu-item v-show="canUpdate" @click="update">编辑部门</context-menu-item>
<context-menu-item v-show="canDel" @click="del">删除部门</context-menu-item> <context-menu-item v-show="canDel" @click="del">删除部门</context-menu-item>
</context-menu> </context-menu>
<edit-dialog v-model="editDialog" :data="currentNode" :type="type" @success="search"/> <edit-dialog v-model="editDialog" :data="currentNode" :type="type" @success="search"/>
</el-card> </el-card>
</template> </template>
@ -63,7 +69,9 @@
export default { export default {
name: "departmentManagement", name: "departmentManagement",
components: {OrgTreeView, ZoomControl, ContextMenu, ContextMenuItem, EditDialog}, components: {OrgTreeView, ZoomControl, ContextMenu, ContextMenuItem, EditDialog},
data() { data() {
return { return {
loading: false, loading: false,
@ -80,20 +88,25 @@
} }
} }
}, },
computed: { computed: {
realZoom() { realZoom() {
return this.zoom / 100 return this.zoom / 100
}, },
canAdd() { canAdd() {
return auth(baseUrl + '/add') return auth(baseUrl + '/add')
}, },
canUpdate() { canUpdate() {
return auth(baseUrl + '/update') return auth(baseUrl + '/update')
}, },
canDel() { canDel() {
return auth(baseUrl + '/del') return auth(baseUrl + '/del')
}, },
}, },
methods: { methods: {
openMenu(e, obj) { openMenu(e, obj) {
e.preventDefault() e.preventDefault()
@ -103,6 +116,7 @@
this.contextmenu.top = e.clientY - top this.contextmenu.top = e.clientY - top
this.contextmenu.show = true this.contextmenu.show = true
}, },
wheel(e) { wheel(e) {
const eventDelta = e.wheelDelta || -(e.detail || 0) const eventDelta = e.wheelDelta || -(e.detail || 0)
const zoom = this.zoom + eventDelta / 12 * 2 const zoom = this.zoom + eventDelta / 12 * 2
@ -115,10 +129,12 @@
this.type = 'add' this.type = 'add'
this.editDialog = true this.editDialog = true
}, },
update() { update() {
this.type = 'edit' this.type = 'edit'
this.editDialog = true this.editDialog = true
}, },
del() { del() {
if (this.loading || !this.currentNode) return if (this.loading || !this.currentNode) return
if (this.currentNode.id === 1) return elError('根节点不能删除') if (this.currentNode.id === 1) return elError('根节点不能删除')
@ -149,6 +165,7 @@
.finally(() => this.loading = false) .finally(() => this.loading = false)
} }
}, },
mounted() { mounted() {
this.search() this.search()
} }

@ -2,6 +2,7 @@
<el-card class="chart-card"> <el-card class="chart-card">
<div slot="header"> <div slot="header">
<span><b>cpu监控</b></span> <span><b>cpu监控</b></span>
<span class="title-span"> <span class="title-span">
当前使用率 当前使用率
<count-to <count-to
@ -11,6 +12,7 @@
suffix="%" suffix="%"
/> />
</span> </span>
<span class="title-span"> <span class="title-span">
峰值 峰值
<count-to <count-to
@ -21,6 +23,7 @@
/> />
</span> </span>
</div> </div>
<div class="line-chart"/> <div class="line-chart"/>
</el-card> </el-card>
</template> </template>
@ -31,11 +34,15 @@
export default { export default {
name: "Cpu", name: "Cpu",
mixins: [resize, logic], mixins: [resize, logic],
components: {CountTo}, components: {CountTo},
props: { props: {
data: Object data: Object
}, },
data() { data() {
return { return {
options: { options: {
@ -91,6 +98,7 @@
} }
} }
}, },
watch: { watch: {
data: { data: {
deep: true, deep: true,
@ -100,13 +108,16 @@
} }
} }
}, },
methods: { methods: {
init() { init() {
this.chart.setOption(this.options) this.chart.setOption(this.options)
}, },
$_getChartDom() { $_getChartDom() {
return this.$el.querySelector('.line-chart') return this.$el.querySelector('.line-chart')
}, },
setOptions({xData, vData} = {}) { setOptions({xData, vData} = {}) {
this.chart.setOption({ this.chart.setOption({
xAxis: {data: xData}, xAxis: {data: xData},

@ -22,6 +22,7 @@
/> />
</span> </span>
</div> </div>
<div class="line-chart"/> <div class="line-chart"/>
</el-card> </el-card>
</template> </template>
@ -32,11 +33,15 @@
export default { export default {
name: "Jvm", name: "Jvm",
mixins: [resize, logic], mixins: [resize, logic],
components: {CountTo}, components: {CountTo},
props: { props: {
data: Object data: Object
}, },
data() { data() {
return { return {
options: { options: {
@ -92,6 +97,7 @@
} }
} }
}, },
watch: { watch: {
data: { data: {
deep: true, deep: true,
@ -101,13 +107,16 @@
} }
} }
}, },
methods: { methods: {
init() { init() {
this.chart.setOption(this.options) this.chart.setOption(this.options)
}, },
$_getChartDom() { $_getChartDom() {
return this.$el.querySelector('.line-chart') return this.$el.querySelector('.line-chart')
}, },
setOptions({xData, vData} = {}) { setOptions({xData, vData} = {}) {
this.chart.setOption({ this.chart.setOption({
xAxis: {data: xData}, xAxis: {data: xData},

@ -22,6 +22,7 @@
/> />
</span> </span>
</div> </div>
<div class="line-chart"/> <div class="line-chart"/>
</el-card> </el-card>
</template> </template>
@ -32,11 +33,15 @@
export default { export default {
name: "Memory", name: "Memory",
mixins: [resize, logic], mixins: [resize, logic],
components: {CountTo}, components: {CountTo},
props: { props: {
data: Object data: Object
}, },
data() { data() {
return { return {
options: { options: {
@ -92,6 +97,7 @@
} }
} }
}, },
watch: { watch: {
data: { data: {
deep: true, deep: true,
@ -101,13 +107,16 @@
} }
} }
}, },
methods: { methods: {
init() { init() {
this.chart.setOption(this.options) this.chart.setOption(this.options)
}, },
$_getChartDom() { $_getChartDom() {
return this.$el.querySelector('.line-chart') return this.$el.querySelector('.line-chart')
}, },
setOptions({xData, vData} = {}) { setOptions({xData, vData} = {}) {
this.chart.setOption({ this.chart.setOption({
xAxis: {data: xData}, xAxis: {data: xData},

@ -4,7 +4,9 @@
<span>启动时间{{operatingInfo.bootedTime}}</span> <span>启动时间{{operatingInfo.bootedTime}}</span>
<span style="margin-left: 20px">运行时间{{operatingInfo.upTime|timePass}}</span> <span style="margin-left: 20px">运行时间{{operatingInfo.upTime|timePass}}</span>
</div> </div>
<cpu-info :data="cpuInfo"/> <cpu-info :data="cpuInfo"/>
<el-row :gutter="40" style="margin-top: 32px"> <el-row :gutter="40" style="margin-top: 32px">
<el-col :span="12"> <el-col :span="12">
<memory-info :data="memoryInfo"/> <memory-info :data="memoryInfo"/>
@ -26,7 +28,9 @@
export default { export default {
name: "systemMonitor", name: "systemMonitor",
components: {CpuInfo, MemoryInfo, JvmInfo}, components: {CpuInfo, MemoryInfo, JvmInfo},
data() { data() {
return { return {
loading: false, loading: false,
@ -79,6 +83,7 @@
} }
} }
}, },
methods: { methods: {
getData() { getData() {
if (this.loading) return if (this.loading) return
@ -94,10 +99,12 @@
}) })
.finally(() => this.loading = false) .finally(() => this.loading = false)
}, },
handleOperatingInfo(info) { handleOperatingInfo(info) {
this.operatingInfo.bootedTime = timeFormat(null, new Date(info.bootedTime * 1000)) this.operatingInfo.bootedTime = timeFormat(null, new Date(info.bootedTime * 1000))
this.operatingInfo.upTime = info.upTime this.operatingInfo.upTime = info.upTime
}, },
handleCpuInfo(info) { handleCpuInfo(info) {
let used = (Number)(sub(100, info.idle).toFixed(2)) let used = (Number)(sub(100, info.idle).toFixed(2))
this.cpuInfo.name = info.name this.cpuInfo.name = info.name
@ -111,6 +118,7 @@
this.cpuInfo.xData.push(this.time) this.cpuInfo.xData.push(this.time)
this.cpuInfo.vData.push(used) this.cpuInfo.vData.push(used)
}, },
handleMemoryInfo(info) { handleMemoryInfo(info) {
info.utilizationRate = (Number)(info.utilizationRate.toFixed(2)) info.utilizationRate = (Number)(info.utilizationRate.toFixed(2))
this.memoryInfo.total = info.total this.memoryInfo.total = info.total
@ -125,6 +133,7 @@
this.memoryInfo.xData.push(this.time) this.memoryInfo.xData.push(this.time)
this.memoryInfo.vData.push(info.utilizationRate) this.memoryInfo.vData.push(info.utilizationRate)
}, },
handleJvmInfo(info) { handleJvmInfo(info) {
info.utilizationRate = (Number)(info.utilizationRate.toFixed(2)) info.utilizationRate = (Number)(info.utilizationRate.toFixed(2))
this.jvmInfo.total = info.total this.jvmInfo.total = info.total
@ -140,6 +149,7 @@
this.jvmInfo.vData.push(info.utilizationRate) this.jvmInfo.vData.push(info.utilizationRate)
}, },
}, },
mounted() { mounted() {
this.getData() this.getData()
this.refreshTimer = setInterval(() => this.getData(), 40000) this.refreshTimer = setInterval(() => this.getData(), 40000)

@ -15,12 +15,25 @@
<el-input :value="form.url" readonly/> <el-input :value="form.url" readonly/>
</el-form-item> </el-form-item>
<el-form-item label="总频率:" prop="total_rate"> <el-form-item label="总频率:" prop="total_rate">
<el-input-number v-model="form.total_rate" :min="1" :step="1" step-strictly size="small"/> <el-input-number
v-model="form.total_rate"
controls-position="right"
:min="1"
:step="1"
step-strictly size="small"
/>
</el-form-item> </el-form-item>
<el-form-item label="单个IP频率:" prop="ip_rate"> <el-form-item label="单个IP频率:" prop="ip_rate">
<el-input-number v-model="form.ip_rate" :min="1" :step="1" step-strictly size="small"/> <el-input-number
v-model="form.ip_rate"
controls-position="right"
:min="1"
:step="1"
step-strictly size="small"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button> <el-button size="small" type="primary" @click="confirm"> </el-button>
@ -36,12 +49,16 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm}, components: {DialogForm},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
data: {type: Object, default: () => ({})}, data: {type: Object, default: () => ({})},
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -58,15 +75,18 @@
} }
} }
}, },
methods: { methods: {
open() { open() {
this.$nextTick(() => mergeObj(this.form, this.data)) this.$nextTick(() => mergeObj(this.form, this.data))
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
resetObj(this.form) resetObj(this.form)
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
confirm() { confirm() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(v => { this.$refs.form.validate(v => {
@ -76,7 +96,7 @@
.then(({msg}) => this.$emit('success', msg)) .then(({msg}) => this.$emit('success', msg))
.finally(() => this.loading = false) .finally(() => this.loading = false)
}) })
}, }
} }
} }
</script> </script>

@ -4,6 +4,7 @@
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table :data="tableData" @row-click="row=$event"> <abstract-table :data="tableData" @row-click="row=$event">
<el-table-column label="名称" prop="fullName" show-overflow-tooltip/> <el-table-column label="名称" prop="fullName" show-overflow-tooltip/>
@ -31,18 +32,23 @@
export default { export default {
name: "resourceManagement", name: "resourceManagement",
mixins: [tableMixin], mixins: [tableMixin],
components: {SearchForm, SearchFormItem, EditDialog}, components: {SearchForm, SearchFormItem, EditDialog},
data() { data() {
return { return {
editDialog: false editDialog: false
} }
}, },
computed: { computed: {
canUpdate() { canUpdate() {
return auth(baseUrl + '/update') return auth(baseUrl + '/update')
} }
}, },
methods: { methods: {
search() { search() {
if (this.config.loading) return if (this.config.loading) return
@ -53,10 +59,12 @@
.then(data => this.tableData = data) .then(data => this.tableData = data)
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
edit() { edit() {
if (!this.row) return elError('请选择要编辑的资源') if (!this.row) return elError('请选择要编辑的资源')
this.editDialog = true this.editDialog = true
}, },
success(msg) { success(msg) {
elSuccess(msg) elSuccess(msg)
this.editDialog = false this.editDialog = false

@ -28,6 +28,7 @@
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-dropdown placement="top" style="float: left" @command="treeCommand"> <el-dropdown placement="top" style="float: left" @command="treeCommand">
<el-button plain size="small"> <el-button plain size="small">
@ -55,13 +56,17 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm}, components: {DialogForm},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
type: {type: String, default: 'add'}, type: {type: String, default: 'add'},
data: {type: Object, default: () => ({})}, data: {type: Object, default: () => ({})},
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -77,6 +82,7 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
if (isEmpty(this.type)) return '' if (isEmpty(this.type)) return ''
@ -87,6 +93,7 @@
return '编辑角色' return '编辑角色'
} }
}, },
confirmMessage() { confirmMessage() {
switch (this.type) { switch (this.type) {
case 'add': case 'add':
@ -97,14 +104,17 @@
return '' return ''
} }
}, },
resource() { resource() {
return this.$store.state.resource.tree return this.$store.state.resource.tree
} }
}, },
methods: { methods: {
treeCommand({action, level}) { treeCommand({action, level}) {
elTreeControl(this.$refs.tree, action, level) elTreeControl(this.$refs.tree, action, level)
}, },
open() { open() {
this.$nextTick(() => { this.$nextTick(() => {
if (this.type === 'edit') { if (this.type === 'edit') {
@ -113,6 +123,7 @@
} }
}) })
}, },
clearForm() { clearForm() {
this.form.id = null this.form.id = null
this.form.name = null this.form.name = null
@ -121,10 +132,12 @@
this.$refs.tree.setCheckedKeys([]) this.$refs.tree.setCheckedKeys([])
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.clearForm() this.clearForm()
}, },
confirm() { confirm() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(v => { this.$refs.form.validate(v => {

@ -3,11 +3,14 @@
export default { export default {
name: "RoleResource", name: "RoleResource",
functional: true, functional: true,
props: { props: {
ids: {type: Array, default: () => []}, ids: {type: Array, default: () => []},
map: {type: Object, default: () => ({})} map: {type: Object, default: () => ({})}
}, },
render(h, context) { render(h, context) {
const {ids, map} = context.props const {ids, map} = context.props
let tree = [] let tree = []

@ -23,12 +23,14 @@
/> />
</search-form-item> </search-form-item>
</search-form> </search-form>
<el-row class="button-group"> <el-row class="button-group">
<el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button> <el-button icon="el-icon-search" size="small" type="success" @click="search"> </el-button>
<el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button> <el-button v-if="canAdd" icon="el-icon-plus" size="small" type="primary" @click="add"> </el-button>
<el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button> <el-button v-if="canUpdate" icon="el-icon-edit" size="small" type="primary" @click="edit"> </el-button>
<el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button> <el-button v-if="canDel" icon="el-icon-delete" size="small" type="danger" @click="del"> </el-button>
</el-row> </el-row>
<el-row v-loading="config.loading" class="table-container"> <el-row v-loading="config.loading" class="table-container">
<abstract-table <abstract-table
:data="tableData" :data="tableData"
@ -50,6 +52,7 @@
</template> </template>
</el-table-column> </el-table-column>
</abstract-table> </abstract-table>
<el-pagination <el-pagination
background background
:current-page="searchForm.page" :current-page="searchForm.page"
@ -79,8 +82,11 @@
export default { export default {
name: "roleManagement", name: "roleManagement",
mixins: [tableMixin], mixins: [tableMixin],
components: {SearchForm, SearchFormItem, EditDialog, RoleResource}, components: {SearchForm, SearchFormItem, EditDialog, RoleResource},
data() { data() {
return { return {
searchForm: { searchForm: {
@ -94,16 +100,20 @@
editDialog: false editDialog: false
} }
}, },
computed: { computed: {
canAdd() { canAdd() {
return auth(baseUrl + '/add') return auth(baseUrl + '/add')
}, },
canUpdate() { canUpdate() {
return auth(baseUrl + '/update') return auth(baseUrl + '/update')
}, },
canDel() { canDel() {
return auth(baseUrl + '/del') return auth(baseUrl + '/del')
}, },
resourceMap() { resourceMap() {
const resource = this.$store.state.resource const resource = this.$store.state.resource
if (resource.data.length <= 0) return {} if (resource.data.length <= 0) return {}
@ -113,6 +123,7 @@
}, {}) }, {})
} }
}, },
methods: { methods: {
mergeSearchForm() { mergeSearchForm() {
return { return {
@ -121,6 +132,7 @@
endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null, endTime: this.temp.ctime ? this.temp.ctime[1] + 86400000 : null,
} }
}, },
search() { search() {
if (this.config.loading) return if (this.config.loading) return
this.config.loading = true this.config.loading = true
@ -136,16 +148,19 @@
}) })
.finally(() => this.config.loading = false) .finally(() => this.config.loading = false)
}, },
add() { add() {
this.row = null this.row = null
this.type = 'add' this.type = 'add'
this.editDialog = true this.editDialog = true
}, },
edit() { edit() {
if (!this.row) return elError('请选择要编辑的角色') if (!this.row) return elError('请选择要编辑的角色')
this.type = 'edit' this.type = 'edit'
this.editDialog = true this.editDialog = true
}, },
del() { del() {
if (!this.row) return elError('请选择要删除的角色') if (!this.row) return elError('请选择要删除的角色')
if (this.row.status === 1) return elError('不能删除已启用的角色') if (this.row.status === 1) return elError('不能删除已启用的角色')
@ -161,6 +176,7 @@
}) })
.finally(() => this.config.operating = false) .finally(() => this.config.operating = false)
}, },
success(msg) { success(msg) {
elSuccess(msg) elSuccess(msg)
this.editDialog = false this.editDialog = false

@ -45,6 +45,7 @@
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
<el-button plain size="small" @click="closeDialog"> </el-button> <el-button plain size="small" @click="closeDialog"> </el-button>
<el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button> <el-button v-if="canEdit" size="small" type="primary" @click="confirm"> </el-button>
@ -62,8 +63,11 @@
export default { export default {
name: "EditDialog", name: "EditDialog",
mixins: [dialogMixin], mixins: [dialogMixin],
components: {DialogForm, RegionSelector}, components: {DialogForm, RegionSelector},
props: { props: {
value: {type: Boolean, default: false}, value: {type: Boolean, default: false},
type: {type: String, default: 'see'}, type: {type: String, default: 'see'},
@ -72,6 +76,7 @@
default: () => ({}) default: () => ({})
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
@ -96,6 +101,7 @@
} }
} }
}, },
computed: { computed: {
title() { title() {
if (isEmpty(this.type)) return '' if (isEmpty(this.type)) return ''
@ -108,6 +114,7 @@
return '编辑供应商' return '编辑供应商'
} }
}, },
confirmMessage() { confirmMessage() {
switch (this.type) { switch (this.type) {
case 'add': case 'add':
@ -118,31 +125,38 @@
return '' return ''
} }
}, },
canEdit() { canEdit() {
return ['add', 'edit'].includes(this.type) return ['add', 'edit'].includes(this.type)
} }
}, },
methods: { methods: {
clearRegion() { clearRegion() {
this.form.region = null this.form.region = null
this.form.region_name = null this.form.region_name = null
}, },
selectRegion(obj) { selectRegion(obj) {
this.form.region = obj.id this.form.region = obj.id
this.form.region_name = obj.fullname this.form.region_name = obj.fullname
}, },
open() { open() {
if (this.type !== 'add') mergeObj(this.form, this.data) if (this.type !== 'add') mergeObj(this.form, this.data)
}, },
clearForm() { clearForm() {
resetObj(this.form) resetObj(this.form)
this.form.status = 1 this.form.status = 1
this.$nextTick(() => this.$refs.form.clearValidate()) this.$nextTick(() => this.$refs.form.clearValidate())
}, },
cancel() { cancel() {
this.closeDialog() this.closeDialog()
this.clearForm() this.clearForm()
}, },
confirm() { confirm() {
if (this.loading) return if (this.loading) return
this.$refs.form.validate(v => { this.$refs.form.validate(v => {

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

Loading…
Cancel
Save