update .gitignore

This commit is contained in:
2021-05-11 20:11:16 +08:00
parent df4159752e
commit 76a6f6ddc1
109 changed files with 34880 additions and 28299 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=localhost;Port=3306;Database=ewide;User ID=root;Password=root;pooling=true;sslmode=none;CharSet=utf8;"
}
}

View File

@@ -1,3 +1,3 @@
VUE_APP_NODE_ENV=development VUE_APP_NODE_ENV=development
VUE_APP_BASE_URL=http://localhost:5566 VUE_APP_BASE_URL=http://localhost:5566
VUE_APP_DEV_KEY=CJm9dFWx4IIGXHm^R1e@Y&mp*n8MQXfDKjDYP6ZVGqEAZQiC9LvX9jq8@uaMTT@T VUE_APP_DEV_KEY=CJm9dFWx4IIGXHm^R1e@Y&mp*n8MQXfDKjDYP6ZVGqEAZQiC9LvX9jq8@uaMTT@T

View File

@@ -1,3 +1,3 @@
VUE_APP_NODE_ENV=production VUE_APP_NODE_ENV=production
VUE_APP_BASE_URL=http://localhost:60161 VUE_APP_BASE_URL=http://localhost:60161
VUE_APP_DEV_KEY=%0!qF2BpcVorlNceu#kP4SVS1bPiMUqI71%rITatPIosNOCrot@mV7PJ&br$CVvF VUE_APP_DEV_KEY=%0!qF2BpcVorlNceu#kP4SVS1bPiMUqI71%rITatPIosNOCrot@mV7PJ&br$CVvF

View File

@@ -1,33 +1,33 @@
@import './extend.less'; @import './extend.less';
@import './lib/visibility.less'; @import './lib/visibility.less';
@import './lib/container.less'; @import './lib/container.less';
@import './lib/align.less'; @import './lib/align.less';
@import './lib/font-size.less'; @import './lib/font-size.less';
@import './lib/text-color.less'; @import './lib/text-color.less';
@import './lib/margin.less'; @import './lib/margin.less';
@import './lib/width-height.less'; @import './lib/width-height.less';
@import './lib/scrollbar.less'; @import './lib/scrollbar.less';
@import './main.less'; @import './main.less';
@import './frame/dark.less'; @import './frame/dark.less';
@import './frame/light.less'; @import './frame/light.less';
.yo-nav-theme--dark { .yo-nav-theme--dark {
.dark(); .dark();
} }
.yo-nav-theme--light { .yo-nav-theme--light {
.light(); .light();
} }
@import './lib/button.less'; @import './lib/button.less';
@import './lib/card.less'; @import './lib/card.less';
@import './lib/table.less'; @import './lib/table.less';
@import './lib/list.less'; @import './lib/list.less';
@import './lib/form.less'; @import './lib/form.less';
@import './lib/description.less'; @import './lib/description.less';
@import './lib/select.less'; @import './lib/select.less';
@import './lib/cascader.less'; @import './lib/cascader.less';
@import './lib/dropdown.less'; @import './lib/dropdown.less';
@import './lib/modal.less'; @import './lib/modal.less';
@import './lib/tree-layout.less'; @import './lib/tree-layout.less';
@import './lib/authority-view.less'; @import './lib/authority-view.less';
@import './lib/icon-selector.less'; @import './lib/icon-selector.less';
@import './theme/primary.less'; @import './theme/primary.less';
// @import './lib/font-weight.less'; // @import './lib/font-weight.less';

View File

@@ -1,3 +1,3 @@
@import '~ant-design-vue/dist/antd.less'; @import '~ant-design-vue/dist/antd.less';
@padding-xxs: 4px; @padding-xxs: 4px;
@padding-xl: 32px; @padding-xl: 32px;

View File

@@ -1,18 +1,18 @@
@import (reference) '~@/assets/style/main.less'; @import (reference) '~@/assets/style/main.less';
@layout-header-background: #1c2127; @layout-header-background: #1c2127;
.dark { .dark {
.main(@nav-background: @layout-header-background; .main(@nav-background: @layout-header-background;
@nav-box-shadow-color: fade(@black, 25%); @nav-box-shadow-color: fade(@black, 25%);
@nav-scrollbar-background: fade(@white, 50%); @nav-scrollbar-background: fade(@white, 50%);
@nav-app-color: fade(@white, 35%); @nav-app-color: fade(@white, 35%);
@logo-color: @white; @logo-color: @white;
@logo-box-shadow: none; @logo-box-shadow: none;
@header-action-color: fade(@white, 60%); @header-action-color: fade(@white, 60%);
@header-action-hover-color: @white; @header-action-hover-color: @white;
@header-action-hover-background: fade(@white, 20%); @header-action-hover-background: fade(@white, 20%);
@header-search-color: @white; @header-search-color: @white;
@header-search-background: fade(@white, 15%); @header-search-background: fade(@white, 15%);
@header-search-focus-background: fade(@white, 30%); @header-search-focus-background: fade(@white, 30%);
@header-search-icon-color: fade(@white, 60%); @header-search-icon-color: fade(@white, 60%);
@header-search-icon-hover-color: @white); @header-search-icon-hover-color: @white);
} }

View File

@@ -1,17 +1,17 @@
@import (reference) '~@/assets/style/main.less'; @import (reference) '~@/assets/style/main.less';
.light { .light {
.main(@nav-background: @white; .main(@nav-background: @white;
@nav-box-shadow-color: fade(@black, 5%); @nav-box-shadow-color: fade(@black, 5%);
@nav-scrollbar-background: fade(@black, 30%); @nav-scrollbar-background: fade(@black, 30%);
@nav-app-color: fade(@black, 35%); @nav-app-color: fade(@black, 35%);
@logo-color: @black; @logo-color: @black;
@logo-box-shadow: inset -1px -1px 1px @border-color-split; @logo-box-shadow: inset -1px -1px 1px @border-color-split;
@header-action-color: fade(@black, 35%); @header-action-color: fade(@black, 35%);
@header-action-hover-color: @icon-color-hover; @header-action-hover-color: @icon-color-hover;
@header-action-hover-background: fade(@black, 5%); @header-action-hover-background: fade(@black, 5%);
@header-search-color: @black; @header-search-color: @black;
@header-search-background: @white; @header-search-background: @white;
@header-search-focus-background: fade(@black, 5%); @header-search-focus-background: fade(@black, 5%);
@header-search-icon-color: fade(@black, 45%); @header-search-icon-color: fade(@black, 45%);
@header-search-icon-hover-color: fade(@black, 80%)); @header-search-icon-hover-color: fade(@black, 80%));
} }

View File

@@ -1,9 +1,9 @@
.text-left { .text-left {
text-align: left !important; text-align: left !important;
} }
.text-center { .text-center {
text-align: center !important; text-align: center !important;
} }
.text-right { .text-right {
text-align: right !important; text-align: right !important;
} }

View File

@@ -1,24 +1,24 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.yo-authority-view { .yo-authority-view {
.ant-descriptions-item-label { .ant-descriptions-item-label {
width: 150px; width: 150px;
} }
.ant-descriptions { .ant-descriptions {
margin-bottom: @padding-sm; margin-bottom: @padding-sm;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
} }
.ant-descriptions-item-content { .ant-descriptions-item-content {
padding: @padding-sm @padding-md; padding: @padding-sm @padding-md;
>.yo-authority-view--checkbox { >.yo-authority-view--checkbox {
display: inline-block; display: inline-block;
width: 150px; width: 150px;
margin: @padding-xxs 0; margin: @padding-xxs 0;
.ant-checkbox-wrapper { .ant-checkbox-wrapper {
margin: 0; margin: 0;
} }
} }
} }
} }

View File

@@ -1,4 +1,4 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.ant-card { .ant-card {
margin-bottom: @padding-md; margin-bottom: @padding-md;
} }

View File

@@ -1,39 +1,39 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
@container-width: 1400px; @container-width: 1400px;
.container-base { .container-base {
margin: 0 auto; margin: 0 auto;
padding: 0 @padding-md; padding: 0 @padding-md;
} }
.container { .container {
width: @container-width; width: @container-width;
.container-base(); .container-base();
} }
@media (max-width: 1400px) { @media (max-width: 1400px) {
.container { .container {
width: auto; width: auto;
} }
} }
.container-md { .container-md {
width: @container-width - 200px; width: @container-width - 200px;
.container-base(); .container-base();
} }
.container-sm { .container-sm {
width: @container-width - 400px; width: @container-width - 400px;
.container-base(); .container-base();
} }
.container-xs { .container-xs {
width: @container-width - 600px; width: @container-width - 600px;
.container-base(); .container-base();
} }
.container-xxs { .container-xxs {
width: @container-width - 700px; width: @container-width - 700px;
.container-base(); .container-base();
} }
.container-fluid { .container-fluid {
.container-base(); .container-base();
} }

View File

@@ -1,6 +1,6 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.ant-dropdown-trigger { .ant-dropdown-trigger {
.anticon-down { .anticon-down {
transform: scaleY(.75); transform: scaleY(.75);
} }
} }

View File

@@ -1,25 +1,25 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
h1, h1,
.h1 { .h1 {
font-size: 36px; font-size: 36px;
} }
h2, h2,
.h2 { .h2 {
font-size: 32px; font-size: 32px;
} }
h3, h3,
.h3 { .h3 {
font-size: 24px; font-size: 24px;
} }
h4, h4,
.h4 { .h4 {
font-size: 18px; font-size: 18px;
} }
h5, h5,
.h5 { .h5 {
font-size: 14px; font-size: 14px;
} }
h6, h6,
.h6 { .h6 {
font-size: 12px; font-size: 12px;
} }

View File

@@ -1,24 +1,24 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
body { body {
font-weight: 100; font-weight: 100;
} }
h1, h1,
h2, h2,
h3, h3,
h4, h4,
h5, h5,
h6 { h6 {
font-weight: 300; font-weight: 300;
} }
@btn-font-weight: 100; @btn-font-weight: 100;
.ant-card-meta-title { .ant-card-meta-title {
font-weight: inherit; font-weight: inherit;
} }
.ant-table-thead { .ant-table-thead {
>tr { >tr {
>th { >th {
font-weight: 500; font-weight: 500;
} }
} }
} }

View File

@@ -1,284 +1,284 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.yo-form { .yo-form {
&--fixed { &--fixed {
width: 660px; width: 660px;
margin: 0 auto; margin: 0 auto;
} }
.h1, .h1,
.h2, .h2,
.h3, .h3,
.h4, .h4,
.h5, .h5,
.h6 { .h6 {
color: darken(@white, 40%); color: darken(@white, 40%);
} }
.h3 { .h3 {
font-size: 16px; font-size: 16px;
} }
.h4 { .h4 {
font-size: 15px; font-size: 15px;
} }
.yo-form-group { .yo-form-group {
margin-bottom: @padding-md; margin-bottom: @padding-md;
} }
.ant-form-item { .ant-form-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: -1px; margin-bottom: -1px;
padding: @padding-xs @padding-md; padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split; border: @border-width-base @border-style-base @border-color-split;
background-color: @white; background-color: @white;
@box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%); @box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%);
@control-background: lighten(@black, 95%) !important; @control-background: lighten(@black, 95%) !important;
&::before, &::before,
&::after { &::after {
content: none; content: none;
} }
.ant-form-item-control { .ant-form-item-control {
text-align: right; text-align: right;
} }
.ant-input, .ant-input,
.ant-input-number, .ant-input-number,
.ant-mentions, .ant-mentions,
.ant-select-selection, .ant-select-selection,
.ant-input-group-addon, .ant-input-group-addon,
.ant-cascader-picker, .ant-cascader-picker,
.ant-cascader-input.ant-input { .ant-cascader-input.ant-input {
z-index: 1; z-index: 1;
text-align: left; text-align: left;
color: lighten(@black, 10%); color: lighten(@black, 10%);
border: 0; border: 0;
background-color: @control-background; background-color: @control-background;
} }
.ant-mentions { .ant-mentions {
textarea { textarea {
background-color: lighten(@black, 95%); background-color: lighten(@black, 95%);
} }
} }
.focus { .focus {
z-index: 2 !important; z-index: 2 !important;
box-shadow: @box-shadow-focused; box-shadow: @box-shadow-focused;
} }
.ant-input { .ant-input {
&:focus { &:focus {
.focus(); .focus();
} }
} }
.ant-input-number-focused, .ant-input-number-focused,
.ant-mentions-focused { .ant-mentions-focused {
.focus(); .focus();
} }
.ant-select-focused, .ant-select-focused,
.ant-select-open { .ant-select-open {
z-index: 2; z-index: 2;
.ant-select-selection { .ant-select-selection {
.focus(); .focus();
} }
} }
.ant-cascader-picker:focus { .ant-cascader-picker:focus {
.ant-cascader-input { .ant-cascader-input {
.focus(); .focus();
} }
} }
.ant-input-group { .ant-input-group {
.ant-row-flex { .ant-row-flex {
.ant-select { .ant-select {
width: 100%; width: 100%;
} }
} }
.ant-input-group-addon { .ant-input-group-addon {
z-index: 0; z-index: 0;
} }
} }
.ant-cascader-picker-clear { .ant-cascader-picker-clear {
background-color: @control-background; background-color: @control-background;
} }
} }
.ant-form-item-label { .ant-form-item-label {
overflow: hidden; overflow: hidden;
flex: 1 1 auto; flex: 1 1 auto;
margin-right: @padding-md; margin-right: @padding-md;
text-align: left; text-align: left;
text-overflow: ellipsis; text-overflow: ellipsis;
>label { >label {
color: lighten(@black, 10%); color: lighten(@black, 10%);
&::after { &::after {
content: none; content: none;
} }
} }
} }
.ant-form-item-control-wrapper { .ant-form-item-control-wrapper {
flex: 0 0 61.8%; flex: 0 0 61.8%;
width: 61.8%; width: 61.8%;
min-width: 220px; min-width: 220px;
} }
.yo-form--fluid { .yo-form--fluid {
.ant-form-item-control-wrapper { .ant-form-item-control-wrapper {
flex: 0 0 100%; flex: 0 0 100%;
width: 100%; width: 100%;
} }
} }
.yo-form--short { .yo-form--short {
.ant-form-item-control-wrapper { .ant-form-item-control-wrapper {
flex: 0 0 38.2%; flex: 0 0 38.2%;
width: 38.2%; width: 38.2%;
} }
} }
.ant-form-explain { .ant-form-explain {
font-size: @font-size-base - 1px; font-size: @font-size-base - 1px;
margin-top: @padding-xs; margin-top: @padding-xs;
margin-bottom: @padding-xxs; margin-bottom: @padding-xxs;
margin-left: -61.8%; margin-left: -61.8%;
transition: none; transition: none;
animation: none; animation: none;
text-align: left; text-align: left;
opacity: 1; opacity: 1;
color: fade(darken(@primary-color, 38.2%), 61.8%); color: fade(darken(@primary-color, 38.2%), 61.8%);
} }
.has-error { .has-error {
.ant-form-explain { .ant-form-explain {
color: @error-color; color: @error-color;
} }
} }
// 上下布局 // 上下布局
.yo-form--vertical { .yo-form--vertical {
display: block; display: block;
.ant-form-item-control { .ant-form-item-control {
text-align: left; text-align: left;
} }
&-radio { &-radio {
.ant-radio-wrapper { .ant-radio-wrapper {
line-height: @padding-lg; line-height: @padding-lg;
display: block; display: block;
margin-right: 0; margin-right: 0;
+.ant-radio-wrapper { +.ant-radio-wrapper {
margin-top: @padding-sm; margin-top: @padding-sm;
} }
} }
} }
.ant-form-item-control-wrapper { .ant-form-item-control-wrapper {
margin-left: @padding-lg; margin-left: @padding-lg;
} }
.ant-form-explain { .ant-form-explain {
margin-left: 0; margin-left: 0;
} }
} }
.yo-form-link { .yo-form-link {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: -1px; margin-bottom: -1px;
padding: @padding-md; padding: @padding-md;
cursor: pointer; cursor: pointer;
border: @border-width-base @border-style-base @border-color-split; border: @border-width-base @border-style-base @border-color-split;
background-color: @white; background-color: @white;
&:hover { &:hover {
background-color: darken(@white, 1%); background-color: darken(@white, 1%);
} }
&:active { &:active {
background-color: darken(@white, 3%); background-color: darken(@white, 3%);
} }
&--title { &--title {
font-size: @font-size-base + 1px; font-size: @font-size-base + 1px;
flex: 1; flex: 1;
} }
&--content { &--content {
flex: 1; flex: 1;
text-align: right; text-align: right;
color: fade(@black, 35%); color: fade(@black, 35%);
} }
&--right-icon { &--right-icon {
margin-left: @padding-xs; margin-left: @padding-xs;
color: fade(@black, 50%); color: fade(@black, 50%);
} }
} }
} }
.yo-modal-form { .yo-modal-form {
.ant-modal-body { .ant-modal-body {
padding: 0; padding: 0;
} }
.yo-form { .yo-form {
h1, h1,
h2, h2,
h3, h3,
h4, h4,
h5 { h5 {
margin-top: @padding-sm; margin-top: @padding-sm;
padding: 0 @padding-md; padding: 0 @padding-md;
} }
.yo-form-group { .yo-form-group {
margin-bottom: 0; margin-bottom: 0;
} }
.ant-form-item { .ant-form-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
&:first-child { &:first-child {
margin-top: -1px; margin-top: -1px;
} }
} }
} }
} }
.yo-drawer-form { .yo-drawer-form {
.ant-drawer-wrapper-body { .ant-drawer-wrapper-body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.ant-drawer-header { .ant-drawer-header {
flex: 0 0 auto; flex: 0 0 auto;
} }
.ant-drawer-body { .ant-drawer-body {
position: relative; position: relative;
flex: 1 1 100%; flex: 1 1 100%;
padding: 0; padding: 0;
} }
.yo-drawer-form--body { .yo-drawer-form--body {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: @border-width-base + 20px + @padding-md * 2; bottom: @border-width-base + 20px + @padding-md * 2;
overflow: auto; overflow: auto;
width: 100%; width: 100%;
padding: @padding-lg; padding: @padding-lg;
} }
.ant-drawer-footer { .ant-drawer-footer {
position: absolute; position: absolute;
left: 0; left: 0;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
padding: 10px @padding-md; padding: 10px @padding-md;
text-align: right; text-align: right;
border-top: @border-width-base @border-style-base @border-color-split; border-top: @border-width-base @border-style-base @border-color-split;
background: @white; background: @white;
button+button { button+button {
margin-left: @padding-xs; margin-left: @padding-xs;
} }
} }
} }

View File

@@ -1,28 +1,28 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.ant-list-bordered { .ant-list-bordered {
border-color: @border-color-split; border-color: @border-color-split;
background-color: @white; background-color: @white;
} }
.yo-list { .yo-list {
&-content--h { &-content--h {
display: flex; display: flex;
align-items: center; align-items: center;
&--item { &--item {
min-width: 120px; min-width: 120px;
margin-left: @padding-xl; margin-left: @padding-xl;
>span { >span {
line-height: 20px; line-height: 20px;
color: lighten(@black, 70%); color: lighten(@black, 70%);
} }
>p { >p {
line-height: 22px; line-height: 22px;
margin-top: @padding-xxs; margin-top: @padding-xxs;
margin-bottom: 0; margin-bottom: 0;
color: lighten(@black, 30%); color: lighten(@black, 30%);
} }
} }
} }
} }

View File

@@ -1,68 +1,68 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
@margin-padding-position: ~'', ~'-top', ~'-left', ~'-right', ~'-bottom'; @margin-padding-position: ~'', ~'-top', ~'-left', ~'-right', ~'-bottom';
@margin-padding-position-name: ~'', ~'t', ~'l', ~'r', ~'b'; @margin-padding-position-name: ~'', ~'t', ~'l', ~'r', ~'b';
.margin-padding (@i) when (@i <=length(@margin-padding-position)) { .margin-padding (@i) when (@i <=length(@margin-padding-position)) {
@position: extract(@margin-padding-position, @i); @position: extract(@margin-padding-position, @i);
@name: extract(@margin-padding-position-name, @i); @name: extract(@margin-padding-position-name, @i);
.m@{name}-xl { .m@{name}-xl {
margin@{position}: @padding-xl !important; margin@{position}: @padding-xl !important;
} }
.m@{name}-lg { .m@{name}-lg {
margin@{position}: @padding-lg !important; margin@{position}: @padding-lg !important;
} }
.m@{name}-md { .m@{name}-md {
margin@{position}: @padding-md !important; margin@{position}: @padding-md !important;
} }
.m@{name}-sm { .m@{name}-sm {
margin@{position}: @padding-sm !important; margin@{position}: @padding-sm !important;
} }
.m@{name}-xs { .m@{name}-xs {
margin@{position}: @padding-xs !important; margin@{position}: @padding-xs !important;
} }
.m@{name}-xxs { .m@{name}-xxs {
margin@{position}: @padding-xxs !important; margin@{position}: @padding-xxs !important;
} }
.p@{name}-xl { .p@{name}-xl {
padding@{position}: @padding-xl !important; padding@{position}: @padding-xl !important;
} }
.p@{name}-lg { .p@{name}-lg {
padding@{position}: @padding-lg !important; padding@{position}: @padding-lg !important;
} }
.p@{name}-md { .p@{name}-md {
padding@{position}: @padding-md !important; padding@{position}: @padding-md !important;
} }
.p@{name}-sm { .p@{name}-sm {
padding@{position}: @padding-sm !important; padding@{position}: @padding-sm !important;
} }
.p@{name}-xs { .p@{name}-xs {
padding@{position}: @padding-xs !important; padding@{position}: @padding-xs !important;
} }
.p@{name}-xxs { .p@{name}-xxs {
padding@{position}: @padding-xxs !important; padding@{position}: @padding-xxs !important;
} }
.m@{name}-none { .m@{name}-none {
margin@{position}: 0 !important; margin@{position}: 0 !important;
} }
.p@{name}-none { .p@{name}-none {
padding@{position}: 0 !important; padding@{position}: 0 !important;
} }
.margin-padding(@i + 1); .margin-padding(@i + 1);
} }
.margin-padding(1); .margin-padding(1);

View File

@@ -1,14 +1,14 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
::-webkit-scrollbar { ::-webkit-scrollbar {
width: 7px; width: 7px;
height: 7px; height: 7px;
background-color: lighten(@primary-color, 35%); background-color: lighten(@primary-color, 35%);
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
border-radius: @border-radius-base; border-radius: @border-radius-base;
background-color: fade(@primary-color, 70%); background-color: fade(@primary-color, 70%);
} }
::-webkit-scrollbar-thumb:active { ::-webkit-scrollbar-thumb:active {
background-color: @primary-color; background-color: @primary-color;
} }

View File

@@ -1,6 +1,6 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.ant-select-arrow { .ant-select-arrow {
.anticon-down { .anticon-down {
transform: scaleY(.75); transform: scaleY(.75);
} }
} }

View File

@@ -1,162 +1,162 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.yo-query-bar { .yo-query-bar {
margin-bottom: @padding-md; margin-bottom: @padding-md;
} }
.yo-action-bar { .yo-action-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: @padding-md; margin-bottom: @padding-md;
&--actions { &--actions {
>.ant-btn, >.ant-btn,
>.ant-btn-group { >.ant-btn-group {
+.ant-btn, +.ant-btn,
+.ant-btn-group { +.ant-btn-group {
margin-left: @padding-xs; margin-left: @padding-xs;
} }
} }
} }
} }
.ant-table { .ant-table {
background-color: @white; background-color: @white;
} }
.ant-table-small { .ant-table-small {
>.ant-table-content { >.ant-table-content {
>.ant-table-body { >.ant-table-body {
margin: 0; margin: 0;
>table { >table {
>.ant-table-thead { >.ant-table-thead {
>tr { >tr {
>th { >th {
background-color: @table-selected-row-bg; background-color: @table-selected-row-bg;
} }
} }
} }
} }
} }
} }
} }
.ant-table-thead { .ant-table-thead {
>tr { >tr {
>th { >th {
font-weight: bold; font-weight: bold;
} }
} }
} }
.yo-table { .yo-table {
.border-right-none() { .border-right-none() {
border-right-width: 0 !important; border-right-width: 0 !important;
&:last-child { &:last-child {
border-right-width: 1px !important; border-right-width: 1px !important;
} }
} }
.ant-table-content { .ant-table-content {
.ant-table-body { .ant-table-body {
overflow-x: auto !important; overflow-x: auto !important;
>table { >table {
>.ant-table-thead { >.ant-table-thead {
>tr { >tr {
>th { >th {
.border-right-none(); .border-right-none();
} }
} }
} }
>.ant-table-tbody { >.ant-table-tbody {
>tr { >tr {
>td { >td {
.border-right-none(); .border-right-none();
} }
} }
} }
} }
} }
.ant-table-fixed-left { .ant-table-fixed-left {
.ant-table-thead { .ant-table-thead {
>tr { >tr {
>th { >th {
border-right-width: 0 !important; border-right-width: 0 !important;
} }
} }
} }
.ant-table-tbody { .ant-table-tbody {
>tr { >tr {
>td { >td {
border-right-width: 0 !important; border-right-width: 0 !important;
} }
} }
} }
} }
.ant-table-fixed-right { .ant-table-fixed-right {
.ant-table-fixed { .ant-table-fixed {
border-left-width: 0 !important; border-left-width: 0 !important;
} }
.ant-table-thead { .ant-table-thead {
>tr { >tr {
>th { >th {
.border-right-none(); .border-right-none();
} }
} }
} }
.ant-table-tbody { .ant-table-tbody {
>tr { >tr {
>td { >td {
.border-right-none(); .border-right-none();
} }
} }
} }
} }
} }
} }
.yo-table-actions { .yo-table-actions {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
&--inner { &--inner {
display: flex; display: flex;
align-items: center; align-items: center;
height: 18px; height: 18px;
} }
} }
.yo-table--column-setting { .yo-table--column-setting {
width: 240px; width: 240px;
.ant-dropdown-menu-item { .ant-dropdown-menu-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
.anticon-pushpin { .anticon-pushpin {
color: darken(@white, 40%); color: darken(@white, 40%);
transition: @animation-duration-slow; transition: @animation-duration-slow;
transform: rotate(45deg); transform: rotate(45deg);
} }
.yo-table--fixed { .yo-table--fixed {
transform: rotate(-45deg); transform: rotate(-45deg);
} }
} }

View File

@@ -1,69 +1,69 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.yo-tree-layout { .yo-tree-layout {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
.ant-layout-sider { .ant-layout-sider {
background-color: @white; background-color: @white;
.ant-layout-header { .ant-layout-header {
height: @layout-header-height - 20px; height: @layout-header-height - 20px;
background-color: @white; background-color: @white;
.header-actions { .header-actions {
>.ant-input-search { >.ant-input-search {
.ant-input { .ant-input {
color: @black; color: @black;
background-color: @white; background-color: @white;
&:focus { &:focus {
background-color: fade(@black, 5%); background-color: fade(@black, 5%);
} }
} }
.anticon-search { .anticon-search {
color: fade(@black, 45%); color: fade(@black, 45%);
} }
} }
} }
} }
.swiper-container { .swiper-container {
position: absolute; position: absolute;
top: @layout-header-height; top: @layout-header-height;
left: 0; left: 0;
bottom: 0; bottom: 0;
width: 100%; width: 100%;
.swiper-slide { .swiper-slide {
height: auto; height: auto;
min-height: 100%; min-height: 100%;
} }
.swiper-scrollbar { .swiper-scrollbar {
transition: @animation-duration-slow opacity; transition: @animation-duration-slow opacity;
opacity: 0; opacity: 0;
} }
&:hover { &:hover {
.swiper-scrollbar { .swiper-scrollbar {
opacity: 1; opacity: 1;
} }
} }
} }
} }
&--bar { &--bar {
line-height: 20px; line-height: 20px;
height: 20px; height: 20px;
padding: 0 @padding-md; padding: 0 @padding-md;
text-align: right; text-align: right;
>.anticon { >.anticon {
cursor: pointer; cursor: pointer;
color: fade(@black, 50%); color: fade(@black, 50%);
&:hover { &:hover {
color: fade(@black, 80%); color: fade(@black, 80%);
} }
} }
} }
} }

View File

@@ -1,22 +1,22 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.hide { .hide {
visibility: hidden !important; visibility: hidden !important;
} }
.hidden { .hidden {
display: none !important; display: none !important;
} }
.block { .block {
display: block; display: block;
} }
.inline-block { .inline-block {
display: inline-block; display: inline-block;
} }
.inline { .inline {
display: inline; display: inline;
} }
.inline-flex { .inline-flex {
display: inline-flex; display: inline-flex;
} }
.flex { .flex {
display: flex; display: flex;
} }

View File

@@ -1,25 +1,25 @@
@import (reference) '~@/assets/style/extend.less'; @import (reference) '~@/assets/style/extend.less';
.w-100-p { .w-100-p {
width: 100%; width: 100%;
} }
.w-100 { .w-100 {
width: 100px; width: 100px;
} }
.w-200 { .w-200 {
width: 200px; width: 200px;
} }
.w-300 { .w-300 {
width: 300px; width: 300px;
} }
.h-100-p { .h-100-p {
height: 100%; height: 100%;
} }
.h-100 { .h-100 {
height: 100px; height: 100px;
} }
.h-200 { .h-200 {
height: 200px; height: 200px;
} }
.h-300 { .h-300 {
height: 300px; height: 300px;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
@import '~@/assets/style/app.less'; @import '~@/assets/style/app.less';
@primary-color: #007bff; @primary-color: #007bff;
@font-size-base: 13px; @font-size-base: 13px;
@border-radius-base: 0; @border-radius-base: 0;

View File

@@ -1,169 +1,169 @@
/** /**
* api * api
* v1.2 * v1.2
*/ */
import axios from 'axios' import axios from 'axios'
import { token } from '@/common/token' import { token } from '@/common/token'
import status from './status' import status from './status'
const STATUS = status const STATUS = status
import app from '@/main' import app from '@/main'
axios.defaults.baseURL = '/api' axios.defaults.baseURL = '/api'
/** /**
* 最终直接根据url名称调用接口方法 * 最终直接根据url名称调用接口方法
* 例如 * 例如
* import { api } from '@/api' * import { api } from '@/api'
* api.getItemGroupType(parmas).then(...) * api.getItemGroupType(parmas).then(...)
*/ */
import urls from './requests' import urls from './requests'
import { settings } from 'nprogress' import { settings } from 'nprogress'
const initInstance = (options) => { const initInstance = (options) => {
const instance = axios const instance = axios
.create({ .create({
headers: { headers: {
Authorization: 'Bearer ' + token.value Authorization: 'Bearer ' + token.value
}, },
...options ...options
}) })
instance.interceptors.response.use((res) => { instance.interceptors.response.use((res) => {
if (res.data.status === STATUS.Unauthorized) { if (res.data.status === STATUS.Unauthorized) {
handlerUnauthorized() handlerUnauthorized()
} }
return res return res
}, (err) => { }, (err) => {
return Promise.reject(err) return Promise.reject(err)
}) })
return instance return instance
} }
const errerCodes = [STATUS.BadRequest, STATUS.InternalServerError, STATUS.Forbidden] const errerCodes = [STATUS.BadRequest, STATUS.InternalServerError, STATUS.Forbidden]
const errorNotification = ({ code, message }) => { const errorNotification = ({ code, message }) => {
switch (message.constructor) { switch (message.constructor) {
case Array: case Array:
message.map(p => { message.map(p => {
setTimeout(() => { setTimeout(() => {
app.$notification.error({ app.$notification.error({
duration: 30, duration: 30,
message: p.field, message: p.field,
description: p.messages.join('/'), description: p.messages.join('/'),
}) })
}) })
}) })
break break
default: default:
app.$notification.error({ app.$notification.error({
duration: 30, duration: 30,
message: code || '错误', message: code || '错误',
description: message, description: message,
}) })
break break
} }
} }
const handlerUnauthorized = () => { const handlerUnauthorized = () => {
token.value = '' token.value = ''
app.$router.replace({ app.$router.replace({
path: '/login' path: '/login'
}).catch(() => { }) }).catch(() => { })
} }
const api = {} const api = {}
for (let key in urls) { for (let key in urls) {
const item = urls[key] const item = urls[key]
let url = '', let url = '',
method = 'post', method = 'post',
options = {} options = {}
if (item.constructor === String) { if (item.constructor === String) {
url = item url = item
} else if (item.constructor === Array) { } else if (item.constructor === Array) {
url = item[0] url = item[0]
if (item[1]) { if (item[1]) {
method = item[1].toLowerCase() method = item[1].toLowerCase()
} }
if (item[2]) { if (item[2]) {
options = item[2] options = item[2]
} }
} else if (item.constructor === Object) { } else if (item.constructor === Object) {
url = item.url url = item.url
if (item.method) { if (item.method) {
method = item.method.toLowerCase() method = item.method.toLowerCase()
} }
} }
api[`${key}Await`] = function (params = {}) { api[`${key}Await`] = function (params = {}) {
if (method === 'post') { if (method === 'post') {
return initInstance(options).post(url, params) return initInstance(options).post(url, params)
} else { } else {
return initInstance(options).get(url, { return initInstance(options).get(url, {
params params
}) })
} }
} }
api[key] = function (params = {}) { api[key] = function (params = {}) {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
api[`${key}Await`](params) api[`${key}Await`](params)
.then((res) => { .then((res) => {
const { data } = res const { data } = res
if (errerCodes.indexOf(data.code) >= 0) { if (errerCodes.indexOf(data.code) >= 0) {
errorNotification(data) errorNotification(data)
reject([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data) reject([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data)
} else if (data.code === STATUS.Unauthorized) { } else if (data.code === STATUS.Unauthorized) {
handlerUnauthorized() handlerUnauthorized()
} else { } else {
reslove([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data) reslove([ArrayBuffer, Blob].indexOf(data.constructor) > -1 ? res : data)
} }
}) })
.catch(({ response }) => { .catch(({ response }) => {
if (process.env.VUE_APP_NODE_ENV === 'development') { if (process.env.VUE_APP_NODE_ENV === 'development') {
const { data, status } = response const { data, status } = response
if (data.constructor === String) { if (data.constructor === String) {
errorNotification({ errorNotification({
message: data, message: data,
code: status code: status
}) })
} else { } else {
errorNotification(data) errorNotification(data)
} }
if (data.code === STATUS.Unauthorized) { if (data.code === STATUS.Unauthorized) {
handlerUnauthorized() handlerUnauthorized()
} }
reject(data) reject(data)
} else { } else {
errorNotification({ errorNotification({
message: '系统发生错误,请联系管理员' message: '系统发生错误,请联系管理员'
}) })
} }
}) })
}) })
} }
api[key].prototype.name = key api[key].prototype.name = key
} }
/** /**
* 并发请求,与axios.all方式相同 * 并发请求,与axios.all方式相同
* 但是使用的接口函数为this.$api.[接口名]E * 但是使用的接口函数为this.$api.[接口名]E
*/ */
api.$queue = function (queue) { api.$queue = function (queue) {
return new Promise((reslove) => { return new Promise((reslove) => {
axios.all(queue).then((results) => { axios.all(queue).then((results) => {
const res = results.map(p => p.data) const res = results.map(p => p.data)
reslove(res) reslove(res)
}) })
}) })
} }
export { export {
axios, axios,
urls, urls,
api, api,
STATUS STATUS
} }

View File

@@ -1,20 +1,20 @@
/** /**
* 接口的3种配置方式 * 接口的3种配置方式
* 1.string * 1.string
* 如login: '/login'\ * 如login: '/login'\
* 将会默认已POST方式请求接口/login * 将会默认已POST方式请求接口/login
* 2.array * 2.array
* 如login: ['/login', 'post'] * 如login: ['/login', 'post']
* 数组[0]必填,为接口地址,[1]选填,为请求方式(不区分大小写),默认为POST * 数组[0]必填,为接口地址,[1]选填,为请求方式(不区分大小写),默认为POST
* 3.object * 3.object
* 如login: { url: '/login', method: 'post' } * 如login: { url: '/login', method: 'post' }
* [url]必填,为接口地址,[method]选填,为请求方式(不区分大小写),默认为POST * [url]必填,为接口地址,[method]选填,为请求方式(不区分大小写),默认为POST
*/ */
import sys from './sys' import sys from './sys'
import business from './business' import business from './business'
export default { export default {
...sys, ...sys,
...business ...business
} }

View File

@@ -1,34 +1,34 @@
export default { export default {
/** /**
* 系统应用列表 * 系统应用列表
*/ */
getAppPage: ['/sysApp/page', 'post'], getAppPage: ['/sysApp/page', 'post'],
/** /**
* 系统应用列表 * 系统应用列表
*/ */
getAppList: ['/sysApp/list', 'get'], getAppList: ['/sysApp/list', 'get'],
/** /**
* 新增系统应用 * 新增系统应用
*/ */
sysAppAdd: ['/sysApp/add', 'post'], sysAppAdd: ['/sysApp/add', 'post'],
/** /**
* 编辑系统应用 * 编辑系统应用
* *
*/ */
sysAppEdit: ['/sysApp/edit', 'post'], sysAppEdit: ['/sysApp/edit', 'post'],
/** /**
* 删除系统应用 * 删除系统应用
*/ */
sysAppDelete: ['/sysApp/delete', 'post'], sysAppDelete: ['/sysApp/delete', 'post'],
/** /**
* 设为默认应用 * 设为默认应用
*/ */
sysAppSetAsDefault: ['/sysApp/setAsDefault', 'post'], sysAppSetAsDefault: ['/sysApp/setAsDefault', 'post'],
/** /**
* 修改应用状态 * 修改应用状态
*/ */
sysAppChangeStatus: ['/sysApp/changeStatus', 'post'], sysAppChangeStatus: ['/sysApp/changeStatus', 'post'],
} }

View File

@@ -1,26 +1,26 @@
export default { export default {
/** /**
* 分页查询配置列表 * 分页查询配置列表
*/ */
sysConfigPage: ['/sysConfig/page', 'post'], sysConfigPage: ['/sysConfig/page', 'post'],
/** /**
* 添加系统参数配置 * 添加系统参数配置
*/ */
sysConfigAdd: ['/sysConfig/add', 'post'], sysConfigAdd: ['/sysConfig/add', 'post'],
/** /**
* 编辑系统参数配置 * 编辑系统参数配置
*/ */
sysConfigEdit: ['/sysConfig/edit', 'post'], sysConfigEdit: ['/sysConfig/edit', 'post'],
/** /**
* 删除系统参数配置 * 删除系统参数配置
*/ */
sysConfigDelete: ['/sysConfig/delete', 'post'], sysConfigDelete: ['/sysConfig/delete', 'post'],
/** /**
* 获取字典类型下所有字典,举例,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}] * 获取字典类型下所有字典,举例,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}]
*/ */
sysDictTypeDropDown: ['/sysDictType/dropDown', 'get'], sysDictTypeDropDown: ['/sysDictType/dropDown', 'get'],
/** /**
* 获取系统的所有任务列表 * 获取系统的所有任务列表
*/ */
sysTimersGetActionClasses: ['/sysTimers/getActionClasses', 'get'], sysTimersGetActionClasses: ['/sysTimers/getActionClasses', 'get'],
} }

View File

@@ -1,18 +1,18 @@
export default { export default {
/** /**
* 查询系统字典值 * 查询系统字典值
*/ */
sysDictDataPage: ['/sysDictData/page', 'post'], sysDictDataPage: ['/sysDictData/page', 'post'],
/** /**
* 添加系统字典值 * 添加系统字典值
*/ */
sysDictDataAdd: ['/sysDictData/add', 'post'], sysDictDataAdd: ['/sysDictData/add', 'post'],
/** /**
* 编辑系统字典值 * 编辑系统字典值
*/ */
sysDictDataEdit: ['/sysDictData/edit', 'post'], sysDictDataEdit: ['/sysDictData/edit', 'post'],
/** /**
* 删除系统字典值 * 删除系统字典值
*/ */
sysDictDataDelete: ['/sysDictData/delete', 'post'], sysDictDataDelete: ['/sysDictData/delete', 'post'],
} }

View File

@@ -1,26 +1,26 @@
export default { export default {
/** /**
* 分页查询系统字典类型 * 分页查询系统字典类型
*/ */
sysDictTypePage: ['/sysDictType/page', 'post'], sysDictTypePage: ['/sysDictType/page', 'post'],
/** /**
* 添加系统字典类型 * 添加系统字典类型
*/ */
sysDictTypeAdd: ['/sysDictType/add', 'post'], sysDictTypeAdd: ['/sysDictType/add', 'post'],
/** /**
* 编辑系统字典类型 * 编辑系统字典类型
*/ */
sysDictTypeEdit: ['/sysDictType/edit', 'post'], sysDictTypeEdit: ['/sysDictType/edit', 'post'],
/** /**
* 删除系统字典类型 * 删除系统字典类型
*/ */
sysDictTypeDelete: ['/sysDictType/delete', 'post'], sysDictTypeDelete: ['/sysDictType/delete', 'post'],
/** /**
* 获取字典类型下所有字典,举例,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}] * 获取字典类型下所有字典,举例,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}]
*/ */
sysDictTypeDropDown: ['/sysDictType/dropDown', 'get'], sysDictTypeDropDown: ['/sysDictType/dropDown', 'get'],
/** /**
* 获取所有字典,启动时加入缓存使用 * 获取所有字典,启动时加入缓存使用
*/ */
sysDictTypeTree: ['/sysDictType/tree', 'get'], sysDictTypeTree: ['/sysDictType/tree', 'get'],
} }

View File

@@ -1,10 +1,10 @@
export default { export default {
/** /**
* 发送邮件 * 发送邮件
*/ */
emailSendEmail: ['/email/sendEmail', 'post'], emailSendEmail: ['/email/sendEmail', 'post'],
/** /**
* 发送html邮件 * 发送html邮件
*/ */
emailSendEmailHtml: ['/email/sendEmailHtml', 'post'], emailSendEmailHtml: ['/email/sendEmailHtml', 'post'],
} }

View File

@@ -1,36 +1,36 @@
export default { export default {
/** /**
* 分页查询文件信息表 * 分页查询文件信息表
*/ */
sysFileInfoPage: ['/sysFileInfo/page', 'post'], sysFileInfoPage: ['/sysFileInfo/page', 'post'],
/** /**
* 获取全部文件信息表 * 获取全部文件信息表
*/ */
sysFileInfoList: ['/sysFileInfo/list', 'get'], sysFileInfoList: ['/sysFileInfo/list', 'get'],
/** /**
* 上传文件 * 上传文件
*/ */
sysFileInfoUpload: ['/sysFileInfo/upload', 'post'], sysFileInfoUpload: ['/sysFileInfo/upload', 'post'],
/** /**
* 下载文件 * 下载文件
*/ */
sysFileInfoDownload: ['/sysFileInfo/download', 'get', { sysFileInfoDownload: ['/sysFileInfo/download', 'get', {
responseType: 'blob' responseType: 'blob'
}], }],
/** /**
* 查看图片 * 查看图片
*/ */
sysFileInfoPreview: ['/sysFileInfo/preview', 'get', { sysFileInfoPreview: ['/sysFileInfo/preview', 'get', {
responseType: 'arraybuffer' responseType: 'arraybuffer'
}], }],
/** /**
* 查看详情文件信息表 * 查看详情文件信息表
*/ */
sysFileInfoDetail: ['/sysFileInfo/detail', 'get'], sysFileInfoDetail: ['/sysFileInfo/detail', 'get'],
/** /**
* 删除文件信息表 * 删除文件信息表
*/ */
sysFileInfoDelete: ['/sysFileInfo/delete', 'post'], sysFileInfoDelete: ['/sysFileInfo/delete', 'post'],
} }

View File

@@ -1,23 +1,23 @@
export default { export default {
/** /**
* 查询访问日志 * 查询访问日志
*/ */
sysVisLogPage: ['/sysVisLog/page', 'post'], sysVisLogPage: ['/sysVisLog/page', 'post'],
/** /**
* 查询操作日志 * 查询操作日志
*/ */
sysOpLogPage: ['/sysOpLog/page', 'post'], sysOpLogPage: ['/sysOpLog/page', 'post'],
/** /**
* 清空访问日志 * 清空访问日志
*/ */
sysVisLogDelete: ['/sysVisLog/delete', 'post'], sysVisLogDelete: ['/sysVisLog/delete', 'post'],
/** /**
* 清空登录日志 * 清空登录日志
*/ */
sysOpLogDelete: ['/sysOpLog/delete', 'post'], sysOpLogDelete: ['/sysOpLog/delete', 'post'],
} }

View File

@@ -1,34 +1,34 @@
export default { export default {
/** /**
* 登录 * 登录
*/ */
login: ['/login', 'post'], login: ['/login', 'post'],
/** /**
* 登出 * 登出
*/ */
logout: ['/logout', 'post'], logout: ['/logout', 'post'],
/** /**
* 获取登录用户信息 * 获取登录用户信息
*/ */
getLoginUser: ['/getLoginUser', 'get'], getLoginUser: ['/getLoginUser', 'get'],
/** /**
* 获取租户开关 * 获取租户开关
*/ */
getTenantOpen: ['/getTenantOpen', 'get'], getTenantOpen: ['/getTenantOpen', 'get'],
/** /**
* 获取短信验证码 * 获取短信验证码
*/ */
getSmsCaptcha: ['/getSmsCaptcha', 'get'], getSmsCaptcha: ['/getSmsCaptcha', 'get'],
/** /**
* 获取验证码开关 * 获取验证码开关
*/ */
getCaptchaOpen: ['/getCaptchaOpen', 'get'], getCaptchaOpen: ['/getCaptchaOpen', 'get'],
/** /**
* 获取验证图片 以及token * 获取验证图片 以及token
*/ */
reqGet: ['/captcha/get', 'post'], reqGet: ['/captcha/get', 'post'],
/** /**
* 滑动或者点选验证 * 滑动或者点选验证
*/ */
reqCheck: ['/captcha/check', 'post'], reqCheck: ['/captcha/check', 'post'],
} }

View File

@@ -1,10 +1,10 @@
export default { export default {
/** /**
* *
* 系统属性监控 * 系统属性监控
* *
*/ */
sysMachineUse:['/sysMachine/use','get'], sysMachineUse:['/sysMachine/use','get'],
sysMachineBase:['/sysMachine/base','get'], sysMachineBase:['/sysMachine/base','get'],
sysMachineNetwork:['/sysMachine/network','get'] sysMachineNetwork:['/sysMachine/network','get']
} }

View File

@@ -1,66 +1,66 @@
export default { export default {
/** /**
* 获取菜单列表 * 获取菜单列表
* *
* @author yubaoshan * @author yubaoshan
* @param parameter * @param parameter
* @returns {*} * @returns {*}
*/ */
getMenuList:['/sysMenu/list','get'], getMenuList:['/sysMenu/list','get'],
/** /**
* 获取系统菜单树,用于新增,编辑时选择上级节点 * 获取系统菜单树,用于新增,编辑时选择上级节点
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/4/23 12:22 * @date 2020/4/23 12:22
*/ */
getMenuTree:['/sysMenu/tree','get'], getMenuTree:['/sysMenu/tree','get'],
/** /**
* 增加菜单 * 增加菜单
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/4/24 23:23 * @date 2020/4/24 23:23
*/ */
sysMenuAdd:['/sysMenu/add','post'], sysMenuAdd:['/sysMenu/add','post'],
/** /**
* 增加菜单 * 增加菜单
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/4/24 23:23 * @date 2020/4/24 23:23
*/ */
sysMenuDelete:['/sysMenu/delete','post'], sysMenuDelete:['/sysMenu/delete','post'],
/** /**
* 查看菜单详情 * 查看菜单详情
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/4/25 01:11 * @date 2020/4/25 01:11
*/ */
sysMenuDetail:['/sysMenu/detail','post'], sysMenuDetail:['/sysMenu/detail','post'],
/** /**
* 编辑系统菜单 * 编辑系统菜单
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/4/25 01:11 * @date 2020/4/25 01:11
*/ */
sysMenuEdit:['/sysMenu/edit','post'], sysMenuEdit:['/sysMenu/edit','post'],
/** /**
* 获取系统菜单树,用于给角色授权时选择 * 获取系统菜单树,用于给角色授权时选择
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/6/2 17:30 * @date 2020/6/2 17:30
*/ */
SysMenuTreeForGrant:['/sysMenu/treeForGrant','get'], SysMenuTreeForGrant:['/sysMenu/treeForGrant','get'],
/** /**
* 根据系统切换菜单 * 根据系统切换菜单
* *
* @author yubaoshan * @author yubaoshan
* @date 2020/6/28 15:25 * @date 2020/6/28 15:25
*/ */
sysMenuChange:['/sysMenu/change','post'], sysMenuChange:['/sysMenu/change','post'],
} }

View File

@@ -1,38 +1,38 @@
export default { export default {
/** /**
* 查询系统通知公告 * 查询系统通知公告
*/ */
sysNoticePage: ['/sysNotice/page', 'post'], sysNoticePage: ['/sysNotice/page', 'post'],
/** /**
* 添加系统通知公告 * 添加系统通知公告
*/ */
sysNoticeAdd: ['/sysNotice/add', 'post'], sysNoticeAdd: ['/sysNotice/add', 'post'],
/** /**
* 编辑系统通知公告 * 编辑系统通知公告
*/ */
sysNoticeEdit: ['/sysNotice/edit', 'post'], sysNoticeEdit: ['/sysNotice/edit', 'post'],
/** /**
* 删除系统通知公告 * 删除系统通知公告
*/ */
sysNoticeDelete: ['/sysNotice/delete', 'post'], sysNoticeDelete: ['/sysNotice/delete', 'post'],
/** /**
* 通知公告详情 * 通知公告详情
*/ */
sysNoticeDetail: ['/sysNotice/detail', 'get'], sysNoticeDetail: ['/sysNotice/detail', 'get'],
/** /**
* 修改状态 * 修改状态
*/ */
sysNoticeChangeStatus: ['/sysNotice/changeStatus', 'post'], sysNoticeChangeStatus: ['/sysNotice/changeStatus', 'post'],
} }

View File

@@ -1,6 +1,6 @@
export default { export default {
/** /**
* 查询我收到的系统通知公告 * 查询我收到的系统通知公告
*/ */
sysNoticeReceived:['/sysNotice/received','get'], sysNoticeReceived:['/sysNotice/received','get'],
} }

View File

@@ -1,12 +1,12 @@
export default{ export default{
/** /**
* 在线用户列表 * 在线用户列表
*/ */
sysOnlineUserList:['/sysOnlineUser/list','get'], sysOnlineUserList:['/sysOnlineUser/list','get'],
/** /**
* 强制下线 * 强制下线
*/ */
sysOnlineUserForceExist:['/sysOnlineUser/forceExist','post'], sysOnlineUserForceExist:['/sysOnlineUser/forceExist','post'],
} }

View File

@@ -1,38 +1,38 @@
export default { export default {
/** /**
* 获取机构树 * 获取机构树
* *
*/ */
getOrgTree: ['/sysOrg/tree', 'get'], getOrgTree: ['/sysOrg/tree', 'get'],
/** /**
* 获取机构列表 * 获取机构列表
* *
*/ */
getOrgList: ['/sysOrg/list', 'get'], getOrgList: ['/sysOrg/list', 'get'],
/** /**
* 获取机构列表 * 获取机构列表
* *
*/ */
getOrgPage: ['/sysOrg/page', 'post'], getOrgPage: ['/sysOrg/page', 'post'],
/** /**
* 新增机构 * 新增机构
* *
*/ */
sysOrgAdd: ['/sysOrg/add', 'post'], sysOrgAdd: ['/sysOrg/add', 'post'],
/** /**
* 编辑机构 * 编辑机构
* *
*/ */
sysOrgEdit: ['/sysOrg/edit', 'post'], sysOrgEdit: ['/sysOrg/edit', 'post'],
/** /**
* 删除机构 * 删除机构
* *
*/ */
sysOrgDelete: ['/sysOrg/delete', 'post'], sysOrgDelete: ['/sysOrg/delete', 'post'],
} }

View File

@@ -1,32 +1,32 @@
export default { export default {
/** /**
* 查询系统职位 * 查询系统职位
* *
*/ */
sysPosPage: ['/sysPos/page', 'post'], sysPosPage: ['/sysPos/page', 'post'],
/** /**
* 系统职位列表 * 系统职位列表
* *
*/ */
sysPosList: ['/sysPos/list', 'get'], sysPosList: ['/sysPos/list', 'get'],
/** /**
* 添加系统职位 * 添加系统职位
* *
*/ */
sysPosAdd: ['/sysPos/add', 'post'], sysPosAdd: ['/sysPos/add', 'post'],
/** /**
* 编辑系统职位 * 编辑系统职位
* *
*/ */
sysPosEdit: ['/sysPos/edit', 'post'], sysPosEdit: ['/sysPos/edit', 'post'],
/** /**
* 删除系统职位 * 删除系统职位
* *
*/ */
sysPosDelete: ['/sysPos/delete', 'post'], sysPosDelete: ['/sysPos/delete', 'post'],
} }

View File

@@ -1,62 +1,62 @@
export default { export default {
/** /**
* 获取角色列表 * 获取角色列表
*/ */
getRolePage: ['/sysRole/page', 'post'], getRolePage: ['/sysRole/page', 'post'],
/** /**
* 增加角色 * 增加角色
*/ */
sysRoleAdd: ['/sysRole/add', 'post'], sysRoleAdd: ['/sysRole/add', 'post'],
/** /**
* 编辑角色 * 编辑角色
*/ */
sysRoleEdit: ['/sysRole/edit', 'post'], sysRoleEdit: ['/sysRole/edit', 'post'],
/** /**
* 删除角色 * 删除角色
*/ */
sysRoleDelete: ['/sysRole/delete', 'post'], sysRoleDelete: ['/sysRole/delete', 'post'],
/** /**
* 删除角色 * 删除角色
*/ */
sysRoleDeteil: ['/sysRole/detail', 'get'], sysRoleDeteil: ['/sysRole/detail', 'get'],
/** /**
* 获取授权角色列表 * 获取授权角色列表
*/ */
sysRoleDropDown: ['/sysRole/dropDown', 'get'], sysRoleDropDown: ['/sysRole/dropDown', 'get'],
/** /**
* 拥有菜单 * 拥有菜单
*/ */
sysRoleOwnMenu: ['/sysRole/ownMenu', 'get'], sysRoleOwnMenu: ['/sysRole/ownMenu', 'get'],
/** /**
* 授权菜单 * 授权菜单
*/ */
sysRoleGrantMenu: ['/sysRole/grantMenu', 'post'], sysRoleGrantMenu: ['/sysRole/grantMenu', 'post'],
/** /**
* 拥有数据 * 拥有数据
*/ */
sysRoleOwnData: ['/sysRole/ownData', 'get'], sysRoleOwnData: ['/sysRole/ownData', 'get'],
/** /**
* 授权数据 * 授权数据
*/ */
sysRoleGrantData: ['/sysRole/grantData', 'post'], sysRoleGrantData: ['/sysRole/grantData', 'post'],
} }

View File

@@ -1,17 +1,17 @@
export default { export default {
/** /**
* 发送记录查询 * 发送记录查询
*/ */
smsPage: ['/sms/page', 'get'], smsPage: ['/sms/page', 'get'],
/** /**
* 验证短信验证码 * 验证短信验证码
*/ */
sysSendLoginMessage: ['/sms/sendLoginMessage', 'post'], sysSendLoginMessage: ['/sms/sendLoginMessage', 'post'],
/** /**
* 验证短信验证码 * 验证短信验证码
*/ */
sysValidateMessage: ['/sms/validateMessage', 'post'], sysValidateMessage: ['/sms/validateMessage', 'post'],
} }

View File

@@ -1,26 +1,26 @@
export default { export default {
/** /**
* 租户列表 * 租户列表
* *
*/ */
sysTenantPage: ['/sysTenant/page', 'post'], sysTenantPage: ['/sysTenant/page', 'post'],
/** /**
* 新增租户 * 新增租户
* *
*/ */
sysTenantAdd: ['/sysTenant/add', 'post'], sysTenantAdd: ['/sysTenant/add', 'post'],
/** /**
* 删除租户 * 删除租户
* *
*/ */
sysTenantDelete: ['/sysTenant/delete', 'post'], sysTenantDelete: ['/sysTenant/delete', 'post'],
/** /**
* 编辑租户 * 编辑租户
* *
*/ */
sysTenantEdit: ['/sysTenant/edit', 'post'], sysTenantEdit: ['/sysTenant/edit', 'post'],
} }

View File

@@ -1,56 +1,56 @@
export default { export default {
/** /**
* 分页查询定时任务 * 分页查询定时任务
*/ */
sysTimersPage: ['/sysTimers/page', 'post'], sysTimersPage: ['/sysTimers/page', 'post'],
/** /**
* 获取全部定时任务 * 获取全部定时任务
*/ */
sysTimersList: ['/sysTimers/list', 'get'], sysTimersList: ['/sysTimers/list', 'get'],
/** /**
* 查看详情定时任务 * 查看详情定时任务
*/ */
sysTimersDetail: ['/sysTimers/detail', 'get'], sysTimersDetail: ['/sysTimers/detail', 'get'],
/** /**
* 添加定时任务 * 添加定时任务
*/ */
sysTimersAdd: ['/sysTimers/add', 'post'], sysTimersAdd: ['/sysTimers/add', 'post'],
/** /**
* 删除定时任务 * 删除定时任务
*/ */
sysTimersDelete: ['/sysTimers/delete', 'post'], sysTimersDelete: ['/sysTimers/delete', 'post'],
/** /**
* 编辑定时任务 * 编辑定时任务
*/ */
sysTimersEdit: ['/sysTimers/edit', 'post'], sysTimersEdit: ['/sysTimers/edit', 'post'],
/** /**
* 获取系统的所有任务列表 * 获取系统的所有任务列表
*/ */
sysTimersGetActionClasses: ['/sysTimers/getActionClasses', 'post'], sysTimersGetActionClasses: ['/sysTimers/getActionClasses', 'post'],
/** /**
* 启动定时任务 * 启动定时任务
*/ */
sysTimersStart: ['/sysTimers/start', 'post'], sysTimersStart: ['/sysTimers/start', 'post'],
/** /**
* 停止定时任务 * 停止定时任务
*/ */
sysTimersStop: ['/sysTimers/stop', 'post'], sysTimersStop: ['/sysTimers/stop', 'post'],
} }

View File

@@ -1,76 +1,76 @@
export default { export default {
/** /**
* 获取用户列表 * 获取用户列表
*/ */
getUserPage: ['/sysUser/page', 'post'], getUserPage: ['/sysUser/page', 'post'],
/** /**
* 增加用户 * 增加用户
*/ */
sysUserAdd: ['/sysUser/add', 'post'], sysUserAdd: ['/sysUser/add', 'post'],
/** /**
* 编辑用户 * 编辑用户
*/ */
sysUserEdit: ['/sysUser/edit', 'post'], sysUserEdit: ['/sysUser/edit', 'post'],
/** /**
* 获取用户详情 * 获取用户详情
*/ */
sysUserDetail: ['/sysUser/detail', 'get'], sysUserDetail: ['/sysUser/detail', 'get'],
/** /**
* 删除用户 * 删除用户
*/ */
sysUserDelete: ['/sysUser/delete', 'post'], sysUserDelete: ['/sysUser/delete', 'post'],
/** /**
* 拥有角色 * 拥有角色
*/ */
sysUserOwnRole: ['/sysUser/ownRole', 'get'], sysUserOwnRole: ['/sysUser/ownRole', 'get'],
/** /**
* 授权角色 * 授权角色
*/ */
sysUserGrantRole: ['/sysUser/grantRole', 'post'], sysUserGrantRole: ['/sysUser/grantRole', 'post'],
/** /**
* 拥有数据 * 拥有数据
*/ */
sysUserOwnData: ['/sysUser/ownData', 'get'], sysUserOwnData: ['/sysUser/ownData', 'get'],
/** /**
* 授权数据 * 授权数据
*/ */
sysUserGrantData: ['/sysUser/grantData', 'post'], sysUserGrantData: ['/sysUser/grantData', 'post'],
/** /**
* 修改状态 * 修改状态
*/ */
sysUserChangeStatus: ['/sysUser/changeStatus', 'post'], sysUserChangeStatus: ['/sysUser/changeStatus', 'post'],
/** /**
* 重置密码 * 重置密码
*/ */
sysUserResetPwd: ['/sysUser/resetPwd', 'post'], sysUserResetPwd: ['/sysUser/resetPwd', 'post'],
/** /**
* 修改密码 * 修改密码
*/ */
sysUserUpdatePwd: ['/sysUser/updatePwd', 'post'], sysUserUpdatePwd: ['/sysUser/updatePwd', 'post'],
/** /**
* 用户选择器 * 用户选择器
*/ */
sysUserSelector: ['/sysUser/selector', 'get'], sysUserSelector: ['/sysUser/selector', 'get'],
/** /**
* 修改头像 * 修改头像
*/ */
sysUserUpdateAvatar: ['/sysUser/updateAvatar', 'post'], sysUserUpdateAvatar: ['/sysUser/updateAvatar', 'post'],
/** /**
* 更新基本信息 * 更新基本信息
*/ */
sysUserUpdateInfo: ['/sysUser/updateInfo', 'post'], sysUserUpdateInfo: ['/sysUser/updateInfo', 'post'],
} }

View File

@@ -1,206 +1,206 @@
export default { export default {
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 100。 System.Net.HttpStatusCode.Continue 指示客户端可以继续其请求。 // 等效于 HTTP 状态 100。 System.Net.HttpStatusCode.Continue 指示客户端可以继续其请求。
Continue: 100, Continue: 100,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态为 101。 System.Net.HttpStatusCode.SwitchingProtocols 指示正在更改的协议版本或协议。 // 等效于 HTTP 状态为 101。 System.Net.HttpStatusCode.SwitchingProtocols 指示正在更改的协议版本或协议。
SwitchingProtocols: 101, SwitchingProtocols: 101,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 200。 System.Net.HttpStatusCode.OK 指示请求成功,且请求的信息包含在响应中。 这是要接收的最常见状态代码。 // 等效于 HTTP 状态 200。 System.Net.HttpStatusCode.OK 指示请求成功,且请求的信息包含在响应中。 这是要接收的最常见状态代码。
OK: 200, OK: 200,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 201。 System.Net.HttpStatusCode.Created 指示请求导致已发送响应之前创建一个新的资源。 // 等效于 HTTP 状态 201。 System.Net.HttpStatusCode.Created 指示请求导致已发送响应之前创建一个新的资源。
Created: 201, Created: 201,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 202。 System.Net.HttpStatusCode.Accepted 指示请求已被接受进行进一步处理。 // 等效于 HTTP 状态 202。 System.Net.HttpStatusCode.Accepted 指示请求已被接受进行进一步处理。
Accepted: 202, Accepted: 202,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 203。 System.Net.HttpStatusCode.NonAuthoritativeInformation 指示返回的元信息来自而不是原始服务器的缓存副本,因此可能不正确。 // 等效于 HTTP 状态 203。 System.Net.HttpStatusCode.NonAuthoritativeInformation 指示返回的元信息来自而不是原始服务器的缓存副本,因此可能不正确。
NonAuthoritativeInformation: 203, NonAuthoritativeInformation: 203,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 204。 System.Net.HttpStatusCode.NoContent 指示已成功处理请求和响应是有意留为空白。 // 等效于 HTTP 状态 204。 System.Net.HttpStatusCode.NoContent 指示已成功处理请求和响应是有意留为空白。
NoContent: 204, NoContent: 204,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 205。 System.Net.HttpStatusCode.ResetContent 指示客户端应重置 (而不是重新加载) 的当前资源。 // 等效于 HTTP 状态 205。 System.Net.HttpStatusCode.ResetContent 指示客户端应重置 (而不是重新加载) 的当前资源。
ResetContent: 205, ResetContent: 205,
// //
// 摘要: // 摘要:
// 等效于 HTTP 206 状态。 System.Net.HttpStatusCode.PartialContent 指示根据包括字节范围的 GET 请求的请求的响应是部分响应。 // 等效于 HTTP 206 状态。 System.Net.HttpStatusCode.PartialContent 指示根据包括字节范围的 GET 请求的请求的响应是部分响应。
PartialContent: 206, PartialContent: 206,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.MultipleChoices 指示所需的信息有多种表示形式。 默认操作是将此状态视为一个重定向,并按照与此响应关联的位置标头的内容。 // 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.MultipleChoices 指示所需的信息有多种表示形式。 默认操作是将此状态视为一个重定向,并按照与此响应关联的位置标头的内容。
MultipleChoices: 300, MultipleChoices: 300,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.Ambiguous 指示所需的信息有多种表示形式。 默认操作是将此状态视为一个重定向,并按照与此响应关联的位置标头的内容。 // 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.Ambiguous 指示所需的信息有多种表示形式。 默认操作是将此状态视为一个重定向,并按照与此响应关联的位置标头的内容。
Ambiguous: 300, Ambiguous: 300,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.MovedPermanently 指示已将所需的信息移动到的位置标头中指定的 // 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.MovedPermanently 指示已将所需的信息移动到的位置标头中指定的
// URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 // URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。
MovedPermanently: 301, MovedPermanently: 301,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.Moved 指示已将所需的信息移动到的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 // 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.Moved 指示已将所需的信息移动到的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。
// 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。 // 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。
Moved: 301, Moved: 301,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Found 指示所需的信息位于的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 // 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Found 指示所需的信息位于的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。
// 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。 // 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。
Found: 302, Found: 302,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Redirect 指示所需的信息位于的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 // 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Redirect 指示所需的信息位于的位置标头中指定的 URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。
// 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。 // 当原始请求方法是 POST 时,重定向的请求将使用 GET 方法。
Redirect: 302, Redirect: 302,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 303。 System.Net.HttpStatusCode.SeeOther 自动将客户端重定向到的位置标头中指定作为公告的结果的 // 等效于 HTTP 状态 303。 System.Net.HttpStatusCode.SeeOther 自动将客户端重定向到的位置标头中指定作为公告的结果的
// URI。 对指定的位置标头的资源的请求将会执行与 GET。 // URI。 对指定的位置标头的资源的请求将会执行与 GET。
SeeOther: 303, SeeOther: 303,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 303。 System.Net.HttpStatusCode.RedirectMethod 自动将客户端重定向到的位置标头中指定作为公告的结果的 // 等效于 HTTP 状态 303。 System.Net.HttpStatusCode.RedirectMethod 自动将客户端重定向到的位置标头中指定作为公告的结果的
// URI。 对指定的位置标头的资源的请求将会执行与 GET。 // URI。 对指定的位置标头的资源的请求将会执行与 GET。
RedirectMethod: 303, RedirectMethod: 303,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 304。 System.Net.HttpStatusCode.NotModified 指示客户端的缓存的副本是最新。 不会传输资源的内容。 // 等效于 HTTP 状态 304。 System.Net.HttpStatusCode.NotModified 指示客户端的缓存的副本是最新。 不会传输资源的内容。
NotModified: 304, NotModified: 304,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 305。 System.Net.HttpStatusCode.UseProxy 指示该请求应使用的位置标头中指定的 uri 的代理服务器。 // 等效于 HTTP 状态 305。 System.Net.HttpStatusCode.UseProxy 指示该请求应使用的位置标头中指定的 uri 的代理服务器。
UseProxy: 305, UseProxy: 305,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 306。 System.Net.HttpStatusCode.Unused 是对未完全指定的 HTTP/1.1 规范建议的扩展。 // 等效于 HTTP 状态 306。 System.Net.HttpStatusCode.Unused 是对未完全指定的 HTTP/1.1 规范建议的扩展。
Unused: 306, Unused: 306,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.TemporaryRedirect 指示请求信息位于的位置标头中指定的 // 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.TemporaryRedirect 指示请求信息位于的位置标头中指定的
// URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 当原始请求方法是 POST 时,重定向的请求还将使用 POST 方法。 // URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 当原始请求方法是 POST 时,重定向的请求还将使用 POST 方法。
TemporaryRedirect: 307, TemporaryRedirect: 307,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.RedirectKeepVerb 指示请求信息位于的位置标头中指定的 // 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.RedirectKeepVerb 指示请求信息位于的位置标头中指定的
// URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 当原始请求方法是 POST 时,重定向的请求还将使用 POST 方法。 // URI。 当收到此状态时的默认操作是遵循与响应关联的位置标头。 当原始请求方法是 POST 时,重定向的请求还将使用 POST 方法。
RedirectKeepVerb: 307, RedirectKeepVerb: 307,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 400。 System.Net.HttpStatusCode.BadRequest 指示无法由服务器理解此请求。 System.Net.HttpStatusCode.BadRequest // 等效于 HTTP 状态 400。 System.Net.HttpStatusCode.BadRequest 指示无法由服务器理解此请求。 System.Net.HttpStatusCode.BadRequest
// 如果没有其他错误适用,或者如果具体的错误是未知的或不具有其自己的错误代码发送。 // 如果没有其他错误适用,或者如果具体的错误是未知的或不具有其自己的错误代码发送。
BadRequest: 400, BadRequest: 400,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 401。 System.Net.HttpStatusCode.Unauthorized 指示所请求的资源需要身份验证。 Www-authenticate // 等效于 HTTP 状态 401。 System.Net.HttpStatusCode.Unauthorized 指示所请求的资源需要身份验证。 Www-authenticate
// 标头包含如何执行身份验证的详细信息。 // 标头包含如何执行身份验证的详细信息。
Unauthorized: 401, Unauthorized: 401,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 402。 System.Net.HttpStatusCode.PaymentRequired 已保留供将来使用。 // 等效于 HTTP 状态 402。 System.Net.HttpStatusCode.PaymentRequired 已保留供将来使用。
PaymentRequired: 402, PaymentRequired: 402,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 403。 System.Net.HttpStatusCode.Forbidden 指示服务器拒绝无法完成请求。 // 等效于 HTTP 状态 403。 System.Net.HttpStatusCode.Forbidden 指示服务器拒绝无法完成请求。
Forbidden: 403, Forbidden: 403,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 404。 System.Net.HttpStatusCode.NotFound 指示所请求的资源不存在的服务器上。 // 等效于 HTTP 状态 404。 System.Net.HttpStatusCode.NotFound 指示所请求的资源不存在的服务器上。
NotFound: 404, NotFound: 404,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 405。 System.Net.HttpStatusCode.MethodNotAllowed 指示请求方法 POST 或 GET // 等效于 HTTP 状态 405。 System.Net.HttpStatusCode.MethodNotAllowed 指示请求方法 POST 或 GET
// 不允许对所请求的资源。 // 不允许对所请求的资源。
MethodNotAllowed: 405, MethodNotAllowed: 405,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 406。 System.Net.HttpStatusCode.NotAcceptable 表示客户端已指定使用 Accept 标头,它将不接受任何可用的资源表示。 // 等效于 HTTP 状态 406。 System.Net.HttpStatusCode.NotAcceptable 表示客户端已指定使用 Accept 标头,它将不接受任何可用的资源表示。
NotAcceptable: 406, NotAcceptable: 406,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 407。 System.Net.HttpStatusCode.ProxyAuthenticationRequired 指示请求的代理要求身份验证。 // 等效于 HTTP 状态 407。 System.Net.HttpStatusCode.ProxyAuthenticationRequired 指示请求的代理要求身份验证。
// 代理服务器进行身份验证标头包含如何执行身份验证的详细信息。 // 代理服务器进行身份验证标头包含如何执行身份验证的详细信息。
ProxyAuthenticationRequired: 407, ProxyAuthenticationRequired: 407,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 408。 System.Net.HttpStatusCode.RequestTimeout 指示客户端的服务器预期请求的时间内没有未发送请求。 // 等效于 HTTP 状态 408。 System.Net.HttpStatusCode.RequestTimeout 指示客户端的服务器预期请求的时间内没有未发送请求。
RequestTimeout: 408, RequestTimeout: 408,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 409。 System.Net.HttpStatusCode.Conflict 指示该请求可能不会执行由于在服务器上发生冲突。 // 等效于 HTTP 状态 409。 System.Net.HttpStatusCode.Conflict 指示该请求可能不会执行由于在服务器上发生冲突。
Conflict: 409, Conflict: 409,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 410。 System.Net.HttpStatusCode.Gone 指示所请求的资源不再可用。 // 等效于 HTTP 状态 410。 System.Net.HttpStatusCode.Gone 指示所请求的资源不再可用。
Gone: 410, Gone: 410,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 411。 System.Net.HttpStatusCode.LengthRequired 指示缺少必需的内容长度标头。 // 等效于 HTTP 状态 411。 System.Net.HttpStatusCode.LengthRequired 指示缺少必需的内容长度标头。
LengthRequired: 411, LengthRequired: 411,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 412。 System.Net.HttpStatusCode.PreconditionFailed 表示失败,此请求的设置的条件,无法执行请求。 // 等效于 HTTP 状态 412。 System.Net.HttpStatusCode.PreconditionFailed 表示失败,此请求的设置的条件,无法执行请求。
// 使用条件请求标头,如果匹配项,如设置条件无-If-match或如果-修改-自从。 // 使用条件请求标头,如果匹配项,如设置条件无-If-match或如果-修改-自从。
PreconditionFailed: 412, PreconditionFailed: 412,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 413。 System.Net.HttpStatusCode.RequestEntityTooLarge 指示请求来说太大的服务器能够处理。 // 等效于 HTTP 状态 413。 System.Net.HttpStatusCode.RequestEntityTooLarge 指示请求来说太大的服务器能够处理。
RequestEntityTooLarge: 413, RequestEntityTooLarge: 413,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 414。 System.Net.HttpStatusCode.RequestUriTooLong 指示 URI 太长。 // 等效于 HTTP 状态 414。 System.Net.HttpStatusCode.RequestUriTooLong 指示 URI 太长。
RequestUriTooLong: 414, RequestUriTooLong: 414,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 415。 System.Net.HttpStatusCode.UnsupportedMediaType 指示该请求是不受支持的类型。 // 等效于 HTTP 状态 415。 System.Net.HttpStatusCode.UnsupportedMediaType 指示该请求是不受支持的类型。
UnsupportedMediaType: 415, UnsupportedMediaType: 415,
// //
// 摘要: // 摘要:
// 等效于 HTTP 416 状态。 System.Net.HttpStatusCode.RequestedRangeNotSatisfiable 指示从资源请求的数据范围不能返回,或者因为范围的开始处,然后该资源的开头或范围的末尾后在资源的结尾。 // 等效于 HTTP 416 状态。 System.Net.HttpStatusCode.RequestedRangeNotSatisfiable 指示从资源请求的数据范围不能返回,或者因为范围的开始处,然后该资源的开头或范围的末尾后在资源的结尾。
RequestedRangeNotSatisfiable: 416, RequestedRangeNotSatisfiable: 416,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 417。 System.Net.HttpStatusCode.ExpectationFailed 指示无法由服务器满足 Expect // 等效于 HTTP 状态 417。 System.Net.HttpStatusCode.ExpectationFailed 指示无法由服务器满足 Expect
// 标头中给定。 // 标头中给定。
ExpectationFailed: 417, ExpectationFailed: 417,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 426。 System.Net.HttpStatusCode.UpgradeRequired 指示客户端应切换到不同的协议,例如 // 等效于 HTTP 状态 426。 System.Net.HttpStatusCode.UpgradeRequired 指示客户端应切换到不同的协议,例如
// TLS/1.0。 // TLS/1.0。
UpgradeRequired: 426, UpgradeRequired: 426,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 500。 System.Net.HttpStatusCode.InternalServerError 表示在服务器上发生一般性错误。 // 等效于 HTTP 状态 500。 System.Net.HttpStatusCode.InternalServerError 表示在服务器上发生一般性错误。
InternalServerError: 500, InternalServerError: 500,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 501。 System.Net.HttpStatusCode.NotImplemented 指示服务器不支持所请求的功能。 // 等效于 HTTP 状态 501。 System.Net.HttpStatusCode.NotImplemented 指示服务器不支持所请求的功能。
NotImplemented: 501, NotImplemented: 501,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 502。 System.Net.HttpStatusCode.BadGateway 指示中间代理服务器从另一个代理或原始服务器接收到错误响应。 // 等效于 HTTP 状态 502。 System.Net.HttpStatusCode.BadGateway 指示中间代理服务器从另一个代理或原始服务器接收到错误响应。
BadGateway: 502, BadGateway: 502,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 503。 System.Net.HttpStatusCode.ServiceUnavailable 指示将服务器暂时不可用,通常是由于高负载或维护。 // 等效于 HTTP 状态 503。 System.Net.HttpStatusCode.ServiceUnavailable 指示将服务器暂时不可用,通常是由于高负载或维护。
ServiceUnavailable: 503, ServiceUnavailable: 503,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 504。 System.Net.HttpStatusCode.GatewayTimeout 指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。 // 等效于 HTTP 状态 504。 System.Net.HttpStatusCode.GatewayTimeout 指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。
GatewayTimeout: 504, GatewayTimeout: 504,
// //
// 摘要: // 摘要:
// 等效于 HTTP 状态 505。 System.Net.HttpStatusCode.HttpVersionNotSupported 指示服务器不支持请求的 // 等效于 HTTP 状态 505。 System.Net.HttpStatusCode.HttpVersionNotSupported 指示服务器不支持请求的
// HTTP 版本。 // HTTP 版本。
HttpVersionNotSupported: 505 HttpVersionNotSupported: 505
} }

View File

@@ -1,61 +1,61 @@
import { api } from '@/common/api' import { api } from '@/common/api'
import { token } from '@/common/token' import { token } from '@/common/token'
import { encryptByDES, decryptByDES } from '@/util/des' import { encryptByDES, decryptByDES } from '@/util/des'
import { removeGlobal } from '@/util/global' import { removeGlobal } from '@/util/global'
import app from '@/main' import app from '@/main'
const doLogin = (args) => { const doLogin = (args) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
api.login(args).then(({ success, data, message }) => { api.login(args).then(({ success, data, message }) => {
if (success) { if (success) {
token.value = data token.value = data
app.$message.success('登录成功') app.$message.success('登录成功')
if (app.$route.query.return) { if (app.$route.query.return) {
const r = decryptByDES(app.$route.query.return) const r = decryptByDES(app.$route.query.return)
app.$router.replace(r) app.$router.replace(r)
} else { } else {
app.$router.replace('/') app.$router.replace('/')
} }
resolve() resolve()
} else { } else {
app.$message.error(message) app.$message.error(message)
reject() reject()
} }
}).catch(({ message }) => { }).catch(({ message }) => {
if (typeof message === 'object' && message[0]) { if (typeof message === 'object' && message[0]) {
app.$message.error(message[0].messages[0]) app.$message.error(message[0].messages[0])
} }
reject() reject()
}) })
}) })
} }
const doLogout = () => { const doLogout = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
api.logout().then(({ success, message }) => { api.logout().then(({ success, message }) => {
if (success) { if (success) {
removeGlobal() removeGlobal()
token.value = '' token.value = ''
if (app.$route.path === '/') { if (app.$route.path === '/') {
app.$router.replace('/login') app.$router.replace('/login')
} else { } else {
app.$router.replace({ app.$router.replace({
path: '/login', path: '/login',
query: { query: {
return: decodeURIComponent(encryptByDES(app.$route.path)) return: decodeURIComponent(encryptByDES(app.$route.path))
} }
}) })
} }
resolve() resolve()
} else { } else {
app.$message.error(message) app.$message.error(message)
reject() reject()
} }
}) })
}) })
} }
export { export {
doLogin, doLogin,
doLogout, doLogout,
} }

View File

@@ -1,9 +1,9 @@
const SESSION_KEY = '__SESSION' const SESSION_KEY = '__SESSION'
const SETTING_KEY = '__SETTINGS' const SETTING_KEY = '__SETTINGS'
const GLOBAL_INFO_KEY = '__GLOBAL_INFO' const GLOBAL_INFO_KEY = '__GLOBAL_INFO'
export { export {
SESSION_KEY, SESSION_KEY,
SETTING_KEY, SETTING_KEY,
GLOBAL_INFO_KEY, GLOBAL_INFO_KEY,
} }

View File

@@ -1,19 +1,19 @@
import { SESSION_KEY } from '@/common/storage' import { SESSION_KEY } from '@/common/storage'
const token = { const token = {
get value() { get value() {
return window.localStorage.getItem(SESSION_KEY) return window.localStorage.getItem(SESSION_KEY)
}, },
set value(token) { set value(token) {
if (!token) { if (!token) {
window.localStorage.removeItem(SESSION_KEY) window.localStorage.removeItem(SESSION_KEY)
} else { } else {
window.localStorage.setItem(SESSION_KEY, token) window.localStorage.setItem(SESSION_KEY, token)
} }
} }
} }
export { export {
SESSION_KEY, SESSION_KEY,
token token
} }

View File

@@ -1,192 +1,192 @@
/** /**
* auth: 允许的权限 * auth: 允许的权限
* authExclude: 排除的权限 * authExclude: 排除的权限
* *
* auth的几种传值方式 * auth的几种传值方式
* 1.String * 1.String
* 例: auth="sysApp:page" * 例: auth="sysApp:page"
* 直接传入字符串,对单项权限进行验证 * 直接传入字符串,对单项权限进行验证
* *
* 2.Array * 2.Array
* 2.1.单项权限 * 2.1.单项权限
* 例: :auth="['sysApp:page']" * 例: :auth="['sysApp:page']"
* 2.2.并且关系多项权限 * 2.2.并且关系多项权限
* 例: :auth="['sysApp:page', 'sysApp:add']" * 例: :auth="['sysApp:page', 'sysApp:add']"
* 数组中传入多个字符串 * 数组中传入多个字符串
* 此时验证的是同时拥有"sysApp:page"和"sysApp:add"两项权限才会渲染 * 此时验证的是同时拥有"sysApp:page"和"sysApp:add"两项权限才会渲染
* 2.3.或者关系多项权限 * 2.3.或者关系多项权限
* 例: :auth="[['sysApp:page', 'sysApp:add'], ['sysApp:edit']]" * 例: :auth="[['sysApp:page', 'sysApp:add'], ['sysApp:edit']]"
* 二维数组结构,内部数组之间为并且关系 * 二维数组结构,内部数组之间为并且关系
* 此时验证的是"sysApp:page"&"sysApp:add"||"sysApp:edit" * 此时验证的是"sysApp:page"&"sysApp:add"||"sysApp:edit"
* 注意:或者的条件必须包括在数组中,暴露在外则判定为并且 * 注意:或者的条件必须包括在数组中,暴露在外则判定为并且
* 2.4.可直接传入布尔值 * 2.4.可直接传入布尔值
* 例: :auth="['sysApp:page', 1 === 1]" * 例: :auth="['sysApp:page', 1 === 1]"
* :auth="[['sysApp:page', 'sysApp:add'], [1 === 1]]" * :auth="[['sysApp:page', 'sysApp:add'], [1 === 1]]"
* *
* 3.Json * 3.Json
* 如果觉得多项权限时每次都要写应用编号比较繁琐,可对Array形式进行简化 * 如果觉得多项权限时每次都要写应用编号比较繁琐,可对Array形式进行简化
* 3.1.单项权限 * 3.1.单项权限
* 例: :auth="{ sysApp: 'page' }" * 例: :auth="{ sysApp: 'page' }"
* 3.2.并且关系多项权限 * 3.2.并且关系多项权限
* 例: :auth="{ sysApp: ['page', 'add'] }" * 例: :auth="{ sysApp: ['page', 'add'] }"
* 3.3.或者关系多项权限 * 3.3.或者关系多项权限
* 例: :auth="{ sysApp: [['page', 'add'], ['edit']]}" * 例: :auth="{ sysApp: [['page', 'add'], ['edit']]}"
* 3.4.可直接传入布尔值 * 3.4.可直接传入布尔值
* 例: :auth="{ sysApp: ['page', 1 === 1] }" * 例: :auth="{ sysApp: ['page', 1 === 1] }"
* :auth="{ sysApp: [['page', 'add'], [1 === 1]] }" * :auth="{ sysApp: [['page', 'add'], [1 === 1]] }"
* *
*/ */
import app from '@/main' import app from '@/main'
const authByArray = (auth, permissions) => { const authByArray = (auth, permissions) => {
const flags = [] const flags = []
auth.forEach(p => { auth.forEach(p => {
switch (p.constructor) { switch (p.constructor) {
case String: case String:
flags.push([permissions.indexOf(p) > -1, '&&']) flags.push([permissions.indexOf(p) > -1, '&&'])
break break
case Array: case Array:
flags.push([authByArray(p, permissions), '||']) flags.push([authByArray(p, permissions), '||'])
break break
case Boolean: case Boolean:
flags.push([p, '&&']) flags.push([p, '&&'])
break break
} }
}) })
let result let result
flags.forEach((p, i) => { flags.forEach((p, i) => {
if (p[1] === '&&') { if (p[1] === '&&') {
if (i === 0) { if (i === 0) {
result = true result = true
} }
if (result) { if (result) {
result = p[0] result = p[0]
} }
} else { } else {
if (i === 0) { if (i === 0) {
result = false result = false
} }
if (!result) { if (!result) {
result = p[0] result = p[0]
} }
} }
//result = p[1] === '&&' ? result && p[0] : result || p[0] //result = p[1] === '&&' ? result && p[0] : result || p[0]
}) })
return result return result
} }
const authByJson = (auth, permissions) => { const authByJson = (auth, permissions) => {
let result = true let result = true
const flags = [] const flags = []
const deepName = (arr, key) => { const deepName = (arr, key) => {
arr.forEach((p, i) => { arr.forEach((p, i) => {
switch (p.constructor) { switch (p.constructor) {
case String: case String:
arr[i] = `${key}:${p}` arr[i] = `${key}:${p}`
break break
case Array: case Array:
p = deepName(p, key) p = deepName(p, key)
break break
default: default:
p = p p = p
break break
} }
}) })
return arr return arr
} }
for (let key in auth) { for (let key in auth) {
const app = auth[key] const app = auth[key]
switch (app.constructor) { switch (app.constructor) {
case String: case String:
flags.push(permissions.indexOf(`${key}:${p}`) > -1) flags.push(permissions.indexOf(`${key}:${p}`) > -1)
break break
case Array: case Array:
flags.push(authByArray(deepName(app, key), permissions)) flags.push(authByArray(deepName(app, key), permissions))
break break
} }
} }
flags.forEach(p => { flags.forEach(p => {
result = result && p result = result && p
}) })
return result return result
} }
export const auth = (auth) => { export const auth = (auth) => {
const { info } = app.global const { info } = app.global
if (!info) { if (!info) {
return false return false
} }
/** /**
* 超级管理员 * 超级管理员
*/ */
if (info.adminType === 1) { if (info.adminType === 1) {
return true return true
} }
const permissions = info.permissions const permissions = info.permissions
let flag = false let flag = false
if (auth) { if (auth) {
switch (auth.constructor) { switch (auth.constructor) {
case String: case String:
flag = permissions.indexOf(auth) > -1 flag = permissions.indexOf(auth) > -1
break break
case Array: case Array:
flag = authByArray(auth, permissions) flag = authByArray(auth, permissions)
break break
case Object: case Object:
flag = authByJson(auth, permissions) flag = authByJson(auth, permissions)
break break
} }
} }
return flag return flag
} }
export default { export default {
functional: true, functional: true,
props: { props: {
auth: { auth: {
default() { default() {
return new Array() return new Array()
}, },
type: [Array, Object, String], type: [Array, Object, String],
}, },
authExclude: { authExclude: {
default() { default() {
return new Array() return new Array()
}, },
type: Array, type: Array,
}, },
}, },
render(h, context) { render(h, context) {
const { props, scopedSlots } = context const { props, scopedSlots } = context
const authExclude = props.authExclude const authExclude = props.authExclude
let flag = auth(props.auth) let flag = auth(props.auth)
if (flag) { if (flag) {
return scopedSlots.default && scopedSlots.default() return scopedSlots.default && scopedSlots.default()
} }
return false return false
}, },
} }

View File

@@ -1,14 +1,14 @@
<template> <template>
<section :class="mode || $root.global.settings.container || 'container-fluid'"> <section :class="mode || $root.global.settings.container || 'container-fluid'">
<slot /> <slot />
</section> </section>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
mode: { mode: {
type: String, type: String,
}, },
}, },
}; };
</script> </script>

View File

@@ -1,254 +1,254 @@
export default { export default {
props: { props: {
loadData: { loadData: {
type: Function, type: Function,
require: true, require: true,
}, },
autoLoad: { autoLoad: {
type: Boolean, type: Boolean,
default: true default: true
}, },
defaultSelectedKeys: { defaultSelectedKeys: {
type: Array, type: Array,
default: [] default: []
} }
}, },
data() { data() {
return { return {
loading: false, loading: false,
data: [], data: [],
list: [] list: []
} }
}, },
created() { created() {
if (this.autoLoad) { if (this.autoLoad) {
this.onLoadData() this.onLoadData()
} }
}, },
methods: { methods: {
renderDescriptions(data) { renderDescriptions(data) {
return data.map(p => { return data.map(p => {
return p.children && p.children.length ? this.renderItem(p) : this.renderCheckbox(p) return p.children && p.children.length ? this.renderItem(p) : this.renderCheckbox(p)
}) })
}, },
renderItem(data) { renderItem(data) {
return ( return (
<a-descriptions bordered column={1}> <a-descriptions bordered column={1}>
<a-descriptions-item> <a-descriptions-item>
<a-checkbox <a-checkbox
slot="label" slot="label"
value={data.id} value={data.id}
checked={data.checked} checked={data.checked}
indeterminate={data.indeterminate} indeterminate={data.indeterminate}
onChange={(e) => this.onChange(e, data)} onChange={(e) => this.onChange(e, data)}
>{data.title}</a-checkbox> >{data.title}</a-checkbox>
{this.renderDescriptions(data.children)} {this.renderDescriptions(data.children)}
</a-descriptions-item> </a-descriptions-item>
</a-descriptions> </a-descriptions>
) )
}, },
renderCheckbox(data) { renderCheckbox(data) {
return ( return (
<div class="yo-authority-view--checkbox"> <div class="yo-authority-view--checkbox">
{data.visibleParent && data.type == 2 && {data.visibleParent && data.type == 2 &&
<a-tooltip placement="top" title="选中此项才会显示父节点"> <a-tooltip placement="top" title="选中此项才会显示父节点">
<a-icon type="eye" style={{ color: '#1890ff' }} class="mr-xxs" /> <a-icon type="eye" style={{ color: '#1890ff' }} class="mr-xxs" />
</a-tooltip> </a-tooltip>
} }
<a-checkbox <a-checkbox
value={data.id} value={data.id}
checked={data.checked} checked={data.checked}
onChange={(e) => this.onChange(e, data)} onChange={(e) => this.onChange(e, data)}
> >
{data.title} {data.title}
</a-checkbox> </a-checkbox>
</div> </div>
) )
}, },
onLoadData() { onLoadData() {
this.loading = true this.loading = true
this.loadData().then((res) => { this.loadData().then((res) => {
this.data = this.generateCheck(res) this.data = this.generateCheck(res)
this.list = [] this.list = []
this.generateList(this.data) this.generateList(this.data)
if (this.defaultSelectedKeys.length) { if (this.defaultSelectedKeys.length) {
this.list.map(p => { this.list.map(p => {
if (this.defaultSelectedKeys.indexOf(p.id) > -1 && (!p.children || !p.children.length)) { if (this.defaultSelectedKeys.indexOf(p.id) > -1 && (!p.children || !p.children.length)) {
this.onSelect(true, p) this.onSelect(true, p)
} }
}) })
} }
this.loading = false this.loading = false
}) })
}, },
onReloadData() { onReloadData() {
this.data = [] this.data = []
this.onLoadData() this.onLoadData()
}, },
onChange(e, item) { onChange(e, item) {
this.onSelect(e.target.checked, item) this.onSelect(e.target.checked, item)
const visible = this.getVisible() const visible = this.getVisible()
this.$emit('select', this.$emit('select',
// 返回所有选中 // 返回所有选中
this.list.filter(p => p.checked).map(p => p.id), this.list.filter(p => p.checked).map(p => p.id),
// 返回所有选中和半选 // 返回所有选中和半选
this.list.filter(p => p.checked || p.indeterminate).map(p => p.id), this.list.filter(p => p.checked || p.indeterminate).map(p => p.id),
// 返回所有选中和半选,但是不返回没有子级选中visibleParent的半选 // 返回所有选中和半选,但是不返回没有子级选中visibleParent的半选
visible visible
) )
}, },
onSelect(check, item) { onSelect(check, item) {
item.checked = check item.checked = check
item.indeterminate = false item.indeterminate = false
if (item.children && item.children.length) { if (item.children && item.children.length) {
this.onChangeChildren(item.checked, item.children) this.onChangeChildren(item.checked, item.children)
} }
if (item.parentId) { if (item.parentId) {
this.onChangeParent(item.checked, item.parentId) this.onChangeParent(item.checked, item.parentId)
} }
}, },
onChangeParent(checked, parentId) { onChangeParent(checked, parentId) {
const parent = this.list.find(p => p.id === parentId) const parent = this.list.find(p => p.id === parentId)
if (parent) { if (parent) {
const checkedCount = parent.children.filter(p => p.checked).length const checkedCount = parent.children.filter(p => p.checked).length
const indeterminateCount = parent.children.filter(p => p.indeterminate).length const indeterminateCount = parent.children.filter(p => p.indeterminate).length
if (checkedCount === parent.children.length) { if (checkedCount === parent.children.length) {
// 全选 // 全选
parent.checked = true parent.checked = true
parent.indeterminate = false parent.indeterminate = false
} else if (!checkedCount && !indeterminateCount) { } else if (!checkedCount && !indeterminateCount) {
// 全不选 // 全不选
parent.checked = false parent.checked = false
parent.indeterminate = false parent.indeterminate = false
} else { } else {
// 半选 // 半选
parent.checked = false parent.checked = false
parent.indeterminate = true parent.indeterminate = true
} }
this.onChangeParent(checked, parent.parentId) this.onChangeParent(checked, parent.parentId)
} }
}, },
onChangeChildren(checked, children) { onChangeChildren(checked, children) {
children.forEach(p => { children.forEach(p => {
p.checked = checked p.checked = checked
p.indeterminate = false p.indeterminate = false
if (p.children && p.children.length) { if (p.children && p.children.length) {
this.onChangeChildren(checked, p.children) this.onChangeChildren(checked, p.children)
} }
}) })
}, },
generateCheck(data) { generateCheck(data) {
data.forEach(p => { data.forEach(p => {
if (p.children && p.children.length) { if (p.children && p.children.length) {
p.children = this.generateCheck(p.children) p.children = this.generateCheck(p.children)
} }
p.checked = false p.checked = false
p.indeterminate = false p.indeterminate = false
}) })
return data return data
}, },
generateList(data) { generateList(data) {
data.forEach(p => { data.forEach(p => {
if (p.children && p.children.length) { if (p.children && p.children.length) {
this.generateList(p.children) this.generateList(p.children)
} }
this.list.push(p) this.list.push(p)
}) })
}, },
getVisible() { getVisible() {
const checked = this.list.filter(p => p.checked) const checked = this.list.filter(p => p.checked)
const caseChildren = checked.filter(p => p.visibleParent || p.type != 2) const caseChildren = checked.filter(p => p.visibleParent || p.type != 2)
const visibleParents = [] const visibleParents = []
// 递归寻找父级 // 递归寻找父级
const findVisibleParents = (children) => { const findVisibleParents = (children) => {
const parents = [] const parents = []
children.forEach(item => { children.forEach(item => {
if (item.parentId) { if (item.parentId) {
const parent = this.list.find(p => p.id === item.parentId) const parent = this.list.find(p => p.id === item.parentId)
if (parent) { if (parent) {
parents.push(parent) parents.push(parent)
visibleParents.push(parent) visibleParents.push(parent)
} }
} }
}) })
if (parents.length) { if (parents.length) {
findVisibleParents(parents) findVisibleParents(parents)
} }
} }
findVisibleParents(caseChildren) findVisibleParents(caseChildren)
const checkedIds = checked.map(p => p.id) const checkedIds = checked.map(p => p.id)
const visibleParentsIds = visibleParents.map(p => p.id) const visibleParentsIds = visibleParents.map(p => p.id)
const result = checkedIds const result = checkedIds
visibleParentsIds.forEach(p => { visibleParentsIds.forEach(p => {
if (result.indexOf(p) === -1) { if (result.indexOf(p) === -1) {
result.push(p) result.push(p)
} }
}) })
return result return result
}, },
}, },
render() { render() {
return ( return (
<div class="yo-authority-view"> <div class="yo-authority-view">
<a-spin style={{ width: '100%' }} spinning={this.loading}> <a-spin style={{ width: '100%' }} spinning={this.loading}>
<a-icon slot="indicator" type="loading" spin /> <a-icon slot="indicator" type="loading" spin />
{ {
!this.loading && !this.loading &&
<a-descriptions bordered column={1}> <a-descriptions bordered column={1}>
{ {
this.data.map(p => { this.data.map(p => {
return ( return (
<a-descriptions-item> <a-descriptions-item>
<a-checkbox <a-checkbox
slot="label" slot="label"
value={p.id} value={p.id}
checked={p.checked} checked={p.checked}
indeterminate={p.indeterminate} indeterminate={p.indeterminate}
onChange={(e) => this.onChange(e, p)} onChange={(e) => this.onChange(e, p)}
>{p.title}</a-checkbox> >{p.title}</a-checkbox>
{this.renderDescriptions(p.children)} {this.renderDescriptions(p.children)}
</a-descriptions-item> </a-descriptions-item>
) )
}) })
} }
</a-descriptions> </a-descriptions>
} }
</a-spin> </a-spin>
</div> </div>
) )
} }
} }

View File

@@ -1,107 +1,107 @@
export default { export default {
props: { props: {
pageNo: { pageNo: {
default: 1, default: 1,
type: Number, type: Number,
}, },
pageSize: { pageSize: {
default: 10, default: 10,
type: Number, type: Number,
}, },
loadData: { loadData: {
type: Function, type: Function,
require: true, require: true,
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
data: [], data: [],
pagination: { pagination: {
current: this.pageNo, current: this.pageNo,
pageSize: this.pageSize, pageSize: this.pageSize,
total: 0, total: 0,
size: 'small', size: 'small',
showSizeChanger: true, showSizeChanger: true,
showQuickJumper: true, showQuickJumper: true,
showTotal: (total) => `总共${total}条数据` showTotal: (total) => `总共${total}条数据`
}, },
}; };
}, },
created() { created() {
this.onLoadData() this.onLoadData()
}, },
methods: { methods: {
onLoading() { onLoading() {
this.loading = { this.loading = {
indicator: <a-icon type="loading" spin /> indicator: <a-icon type="loading" spin />
} }
}, },
onLoaded() { onLoaded() {
this.loading = false this.loading = false
}, },
onLoadData() { onLoadData() {
this.onLoading() this.onLoading()
this.loadData({ this.loadData({
pageNo: this.pagination.current, pageNo: this.pagination.current,
pageSize: this.pagination.pageSize, pageSize: this.pagination.pageSize,
...this.sorter ...this.sorter
}).then((res) => { }).then((res) => {
this.data = res.rows this.data = res.rows
this.pagination.total = res.totalRows this.pagination.total = res.totalRows
this.onLoaded() this.onLoaded()
}) })
}, },
onReloadData(refresh = false) { onReloadData(refresh = false) {
if (refresh && refresh.constructor === Boolean && this.pagination.constructor === Object) { if (refresh && refresh.constructor === Boolean && this.pagination.constructor === Object) {
this.pagination.current = this.pageNo this.pagination.current = this.pageNo
this.pagination.pageSize = this.pageSize this.pagination.pageSize = this.pageSize
} }
this.onLoadData() this.onLoadData()
}, },
}, },
render() { render() {
const props = { const props = {
loading: this.loading, loading: this.loading,
pagination: this.pagination, pagination: this.pagination,
dataSource: this.data, dataSource: this.data,
rowKey: record => record.id, rowKey: record => record.id,
...this.$attrs ...this.$attrs
} }
const on = { const on = {
//change: this.onTableChange //change: this.onTableChange
} }
return ( return (
<section> <section>
<div class="yo-action-bar"> <div class="yo-action-bar">
<div class="yo-action-bar--actions"> <div class="yo-action-bar--actions">
{this.$scopedSlots.operator && this.$scopedSlots.operator()} {this.$scopedSlots.operator && this.$scopedSlots.operator()}
</div> </div>
<div class="yo-action-bar--actions"> <div class="yo-action-bar--actions">
<a-button-group> <a-button-group>
<a-button onClick={this.onReloadData}>刷新</a-button> <a-button onClick={this.onReloadData}>刷新</a-button>
</a-button-group> </a-button-group>
</div> </div>
</div> </div>
<a-list {...{ props, on, scopedSlots: { ...this.$scopedSlots } }}> <a-list {...{ props, on, scopedSlots: { ...this.$scopedSlots } }}>
{Object.keys(this.$slots).map((name) => ( {Object.keys(this.$slots).map((name) => (
<template slot={name}>{this.$slots[name]}</template> <template slot={name}>{this.$slots[name]}</template>
))} ))}
</a-list> </a-list>
</section> </section>
) )
}, },
} }

View File

@@ -1,64 +1,64 @@
<template> <template>
<a-dropdown :trigger="['click']" placement="bottomRight" v-model="visible"> <a-dropdown :trigger="['click']" placement="bottomRight" v-model="visible">
<a-button>显示列</a-button> <a-button>显示列</a-button>
<a-menu @click="() => { return false; }" class="yo-table--column-setting" slot="overlay"> <a-menu @click="() => { return false; }" class="yo-table--column-setting" slot="overlay">
<a-menu-item> <a-menu-item>
<a-checkbox :checked="checkedAll" :indeterminate="halfChecked" @change="onCheckAll">全选</a-checkbox> <a-checkbox :checked="checkedAll" :indeterminate="halfChecked" @change="onCheckAll">全选</a-checkbox>
</a-menu-item> </a-menu-item>
<a-menu-divider /> <a-menu-divider />
<a-menu-item :key="column.dataIndex || column.key" v-for="column in columns"> <a-menu-item :key="column.dataIndex || column.key" v-for="column in columns">
<a-checkbox :checked="!column.hidden" @change="(e) => onCheck(column, e)">{{column.title}}</a-checkbox> <a-checkbox :checked="!column.hidden" @change="(e) => onCheck(column, e)">{{column.title}}</a-checkbox>
<a-icon <a-icon
:class="{ 'yo-table--fixed': column.fixed }" :class="{ 'yo-table--fixed': column.fixed }"
@click="onFixed(column)" @click="onFixed(column)"
type="pushpin" type="pushpin"
/> />
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
columns: { columns: {
type: Array, type: Array,
require: true, require: true,
}, },
}, },
data() { data() {
return { return {
visible: false, visible: false,
checkedAll: true, checkedAll: true,
halfChecked: false, halfChecked: false,
}; };
}, },
mounted() { mounted() {
this.onHalfCheck(); this.onHalfCheck();
}, },
methods: { methods: {
onHalfCheck() { onHalfCheck() {
this.halfChecked = this.columns.filter((p) => p.hidden).length > 0; this.halfChecked = this.columns.filter((p) => p.hidden).length > 0;
}, },
onCheck(column, e) { onCheck(column, e) {
this.$set(column, 'hidden', !e.target.checked); this.$set(column, 'hidden', !e.target.checked);
this.onHalfCheck(); this.onHalfCheck();
}, },
onCheckAll(e) { onCheckAll(e) {
this.columns.forEach((column) => { this.columns.forEach((column) => {
this.$set(column, 'hidden', !e.target.checked); this.$set(column, 'hidden', !e.target.checked);
}); });
this.checkedAll = e.target.checked; this.checkedAll = e.target.checked;
}, },
onFixed(column) { onFixed(column) {
this.$set(column, 'fixed', !column.fixed); this.$set(column, 'fixed', !column.fixed);
}, },
}, },
}; };
</script> </script>

View File

@@ -1,229 +1,229 @@
// 列设置用jsx实现起来较为困难 // 列设置用jsx实现起来较为困难
import ColumnSetting from './column' import ColumnSetting from './column'
export default { export default {
props: { props: {
pageNo: { pageNo: {
default: 1, default: 1,
type: Number, type: Number,
}, },
pageSize: { pageSize: {
default: 10, default: 10,
type: Number, type: Number,
}, },
loadData: { loadData: {
type: Function, type: Function,
require: true, require: true,
}, },
columns: { columns: {
type: Array, type: Array,
require: true, require: true,
}, },
}, },
data() { data() {
return { return {
loading: false, loading: false,
type: '', type: '',
data: [], data: [],
pagination: { pagination: {
current: this.pageNo, current: this.pageNo,
pageSize: this.pageSize, pageSize: this.pageSize,
total: 0, total: 0,
size: 'small', size: 'small',
showSizeChanger: true, showSizeChanger: true,
showQuickJumper: true, showQuickJumper: true,
showTotal: (total) => `总共${total}条数据` showTotal: (total) => `总共${total}条数据`
}, },
sorter: { sorter: {
sortField: '', sortField: '',
sortOrder: '', sortOrder: '',
}, },
columnSettingVisible: false columnSettingVisible: false
}; };
}, },
created() { created() {
this.onLoadData() this.onLoadData()
}, },
methods: { methods: {
renderColumnSetting() { renderColumnSetting() {
const props = { const props = {
visible: this.columnSettingVisible, visible: this.columnSettingVisible,
placement: 'bottomRight' placement: 'bottomRight'
} }
const on = { const on = {
visibleChange: (visible) => { visibleChange: (visible) => {
this.columnSettingVisible = visible this.columnSettingVisible = visible
} }
} }
return ( return (
<a-dropdown {...{ props, on }}> <a-dropdown {...{ props, on }}>
<a-button onClick={() => this.columnSettingVisible = true}>设置列</a-button> <a-button onClick={() => this.columnSettingVisible = true}>设置列</a-button>
<a-menu slot="overlay" onClick={() => { return false }}> <a-menu slot="overlay" onClick={() => { return false }}>
{ {
this.columns.map(column => { this.columns.map(column => {
return ( return (
<a-menu-item key={column.dataIndex || column.key}> <a-menu-item key={column.dataIndex || column.key}>
<a-checkbox checked={column.hidden} onChange={() => { column.hidden = !column.hidden }}>{column.title}</a-checkbox> <a-checkbox checked={column.hidden} onChange={() => { column.hidden = !column.hidden }}>{column.title}</a-checkbox>
</a-menu-item> </a-menu-item>
) )
}) })
} }
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
) )
}, },
onLoading() { onLoading() {
this.loading = { this.loading = {
indicator: <a-icon type="loading" spin /> indicator: <a-icon type="loading" spin />
} }
}, },
onLoaded() { onLoaded() {
this.loading = false this.loading = false
}, },
onLoadData() { onLoadData() {
this.onLoading() this.onLoading()
this.loadData({ this.loadData({
pageNo: this.pagination.current, pageNo: this.pagination.current,
pageSize: this.pagination.pageSize, pageSize: this.pagination.pageSize,
...this.sorter ...this.sorter
}).then((res) => { }).then((res) => {
if (res.rows) { if (res.rows) {
// 普通表格 // 普通表格
this.type = 'table' this.type = 'table'
this.data = res.rows this.data = res.rows
this.pagination.total = res.totalRows this.pagination.total = res.totalRows
} else if (res) { } else if (res) {
// 树形表格 // 树形表格
this.type = 'tree' this.type = 'tree'
this.data = this.onClearChildren(res) this.data = this.onClearChildren(res)
this.pagination = false this.pagination = false
} }
}).finally(() => { }).finally(() => {
this.onLoaded() this.onLoaded()
}) })
}, },
onReloadData(refresh = false) { onReloadData(refresh = false) {
if (refresh && refresh.constructor === Boolean && this.pagination.constructor === Object) { if (refresh && refresh.constructor === Boolean && this.pagination.constructor === Object) {
this.pagination.current = this.pageNo this.pagination.current = this.pageNo
this.pagination.pageSize = this.pageSize this.pagination.pageSize = this.pageSize
} }
this.onLoadData() this.onLoadData()
}, },
onTableChange(pagination, filters, sorter) { onTableChange(pagination, filters, sorter) {
this.pagination = pagination this.pagination = pagination
this.sorter = { this.sorter = {
sortField: sorter.field, sortField: sorter.field,
sortOrder: sorter.order, sortOrder: sorter.order,
} }
this.onLoadData() this.onLoadData()
}, },
/** /**
* 清除没有子节点内容的子节点位置 * 清除没有子节点内容的子节点位置
*/ */
onClearChildren(data) { onClearChildren(data) {
data.forEach(p => { data.forEach(p => {
if (p.children) { if (p.children) {
if (p.children.length) { if (p.children.length) {
p.children = this.onClearChildren(p.children) p.children = this.onClearChildren(p.children)
} else { } else {
delete p.children delete p.children
} }
} }
}) })
return data return data
}, },
onQuery() { onQuery() {
this.$emit('query') this.$emit('query')
}, },
onResetQuery() { onResetQuery() {
this.$emit('resetQuery') this.$emit('resetQuery')
this.$emit('reset-query') this.$emit('reset-query')
} }
}, },
render() { render() {
const props = { const props = {
loading: this.loading, loading: this.loading,
pagination: this.pagination, pagination: this.pagination,
dataSource: this.data, dataSource: this.data,
columns: this.columns.filter(p => !p.hidden), columns: this.columns.filter(p => !p.hidden),
bordered: true, bordered: true,
size: 'middle', size: 'middle',
rowKey: record => record.id || Math.random().toString(16).slice(2), rowKey: record => record.id || Math.random().toString(16).slice(2),
scroll: { x: 'max-content' } scroll: { x: 'max-content' }
} }
const on = { const on = {
change: this.onTableChange, change: this.onTableChange,
...this.$listeners ...this.$listeners
} }
const queryOn = { const queryOn = {
'submit.native.prevent': () => { } 'submit.native.prevent': () => { }
} }
return ( return (
<section> <section>
<a-alert type="warning" closable> <a-alert type="warning" closable>
<template slot="message"> <template slot="message">
字段固定应该遵循左侧固定到最左,右侧固定到最右(此逻辑难以实现) 字段固定应该遵循左侧固定到最左,右侧固定到最右(此逻辑难以实现)
</template> </template>
</a-alert> </a-alert>
<br /> <br />
{ {
this.$scopedSlots.query && this.$scopedSlots.query &&
<div class="yo-query-bar"> <div class="yo-query-bar">
<a-form-model layout="inline" {...{ on: queryOn }}> <a-form-model layout="inline" {...{ on: queryOn }}>
{this.$scopedSlots.query()} {this.$scopedSlots.query()}
<a-form-model-item> <a-form-model-item>
<a-button-group> <a-button-group>
<a-button onClick={this.onQuery} html-type="submit" type="primary">查询</a-button> <a-button onClick={this.onQuery} html-type="submit" type="primary">查询</a-button>
<a-button onClick={this.onResetQuery}>重置</a-button> <a-button onClick={this.onResetQuery}>重置</a-button>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</div> </div>
} }
<div class="yo-action-bar"> <div class="yo-action-bar">
<div class="yo-action-bar--actions"> <div class="yo-action-bar--actions">
{this.$scopedSlots.operator && this.$scopedSlots.operator()} {this.$scopedSlots.operator && this.$scopedSlots.operator()}
</div> </div>
<div class="yo-action-bar--actions"> <div class="yo-action-bar--actions">
<a-button-group> <a-button-group>
<a-button onClick={this.onReloadData}>刷新</a-button> <a-button onClick={this.onReloadData}>刷新</a-button>
{ {
this.type === 'table' && <ColumnSetting {...{ props: { columns: this.columns } }} /> this.type === 'table' && <ColumnSetting {...{ props: { columns: this.columns } }} />
} }
</a-button-group> </a-button-group>
</div> </div>
</div> </div>
<a-table class="yo-table" {...{ props, on, scopedSlots: { ...this.$scopedSlots } }}> <a-table class="yo-table" {...{ props, on, scopedSlots: { ...this.$scopedSlots } }}>
{Object.keys(this.$slots).map((name) => ( {Object.keys(this.$slots).map((name) => (
<template slot={name}>{this.$slots[name]}</template> <template slot={name}>{this.$slots[name]}</template>
))} ))}
</a-table> </a-table>
</section> </section>
) )
}, },
} }

View File

@@ -1,23 +1,23 @@
export default { export default {
render() { render() {
const components = [] const components = []
const slots = this.$slots.default.filter(p => p.tag) const slots = this.$slots.default.filter(p => p.tag)
slots.forEach((p, i) => { slots.forEach((p, i) => {
components.push(p) components.push(p)
if (i < slots.length - 1) { if (i < slots.length - 1) {
components.push(<a-divider type="vertical" />) components.push(<a-divider type="vertical" />)
} }
}) })
return ( return (
<div class="yo-table-actions"> <div class="yo-table-actions">
<div class="yo-table-actions--inner"> <div class="yo-table-actions--inner">
{components} {components}
</div> </div>
</div> </div>
) )
} }
} }

View File

@@ -1,303 +1,303 @@
import Swiper from 'swiper' import Swiper from 'swiper'
let timer, swiper let timer, swiper
export default { export default {
props: { props: {
loadData: { loadData: {
type: Function, type: Function,
require: true, require: true,
}, },
defaultExpandedKeys: { defaultExpandedKeys: {
default: false, default: false,
type: Boolean type: Boolean
}, },
replaceFields: { replaceFields: {
default() { default() {
return { return {
value: 'id', value: 'id',
title: 'title', title: 'title',
children: 'children' children: 'children'
} }
}, },
type: Object type: Object
} }
}, },
data() { data() {
return { return {
loading: false, loading: false,
data: [], data: [],
list: [], list: [],
searchValue: '', searchValue: '',
selectedKeys: [], selectedKeys: [],
expandedKeys: [], expandedKeys: [],
autoExpandParent: true autoExpandParent: true
} }
}, },
created() { created() {
this.onLoadData() this.onLoadData()
}, },
mounted() { mounted() {
const container = this.$refs.swiper, const container = this.$refs.swiper,
scrollBar = container.querySelector('.swiper-scrollbar') scrollBar = container.querySelector('.swiper-scrollbar')
const swiperOptions = { const swiperOptions = {
direction: 'vertical', direction: 'vertical',
slidesPerView: 'auto', slidesPerView: 'auto',
freeMode: true, freeMode: true,
scrollbar: { scrollbar: {
el: scrollBar, el: scrollBar,
}, },
mousewheel: true, mousewheel: true,
} }
swiper = new Swiper(container, swiperOptions) swiper = new Swiper(container, swiperOptions)
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
this.onUpdateSwiper() this.onUpdateSwiper()
}) })
}, },
methods: { methods: {
renderBreadcrumbItem() { renderBreadcrumbItem() {
const path = ['顶级'] const path = ['顶级']
const findPath = (data, level) => { const findPath = (data, level) => {
level = level || 1 level = level || 1
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const item = data[i] const item = data[i]
path[level] = item[this.replaceFields.title] path[level] = item[this.replaceFields.title]
if (item[this.replaceFields.value] === this.selectedKeys[0]) { if (item[this.replaceFields.value] === this.selectedKeys[0]) {
path.length = level + 1 path.length = level + 1
return true return true
} }
if (item[this.replaceFields.children] && item[this.replaceFields.children].length) { if (item[this.replaceFields.children] && item[this.replaceFields.children].length) {
const found = findPath(item[this.replaceFields.children], level + 1) const found = findPath(item[this.replaceFields.children], level + 1)
if (found) { if (found) {
return true return true
} }
} }
} }
} }
if (this.selectedKeys.length) { if (this.selectedKeys.length) {
findPath(this.data) findPath(this.data)
} }
return path.map(p => ( return path.map(p => (
<a-breadcrumb-item>{p}</a-breadcrumb-item> <a-breadcrumb-item>{p}</a-breadcrumb-item>
)) ))
}, },
onLoadData() { onLoadData() {
this.loading = true this.loading = true
this.loadData().then((res) => { this.loadData().then((res) => {
const data = this.generateKey(res) const data = this.generateKey(res)
this.list = [] this.list = []
this.generateList(data) this.generateList(data)
if (this.defaultExpandedKeys) { if (this.defaultExpandedKeys) {
this.expandedKeys = this.list.map(p => p.key) this.expandedKeys = this.list.map(p => p.key)
} }
this.data = data this.data = data
this.$nextTick(() => { this.$nextTick(() => {
this.onUpdateSwiper() this.onUpdateSwiper()
}) })
}).finally(() => { }).finally(() => {
this.loading = false this.loading = false
}) })
}, },
onReloadData() { onReloadData() {
this.onLoadData() this.onLoadData()
}, },
onExpand(expandedKeys) { onExpand(expandedKeys) {
this.expandedKeys = expandedKeys this.expandedKeys = expandedKeys
this.autoExpandParent = false this.autoExpandParent = false
this.onUpdateSwiper() this.onUpdateSwiper()
}, },
onUnexpandAll() { onUnexpandAll() {
this.expandedKeys = [] this.expandedKeys = []
}, },
onSearch(value) { onSearch(value) {
const expandedKeys = this.list const expandedKeys = this.list
.map(p => { .map(p => {
if (p[this.replaceFields.title].indexOf(value) > -1) { if (p[this.replaceFields.title].indexOf(value) > -1) {
return this.getParentKey(p.key, this.data) return this.getParentKey(p.key, this.data)
} }
return null return null
}) })
.filter((p, i, self) => p && self.indexOf(p) === i) .filter((p, i, self) => p && self.indexOf(p) === i)
this.searchValue = value this.searchValue = value
this.expandedKeys = expandedKeys this.expandedKeys = expandedKeys
this.autoExpandParent = true this.autoExpandParent = true
this.$nextTick(() => { this.$nextTick(() => {
this.onUpdateSwiper() this.onUpdateSwiper()
}) })
}, },
onSelect(selectedKeys) { onSelect(selectedKeys) {
const selectedIds = [] const selectedIds = []
selectedKeys.forEach(p => { selectedKeys.forEach(p => {
const data = this.list.find(m => m.key === p) const data = this.list.find(m => m.key === p)
selectedIds.push(data[this.replaceFields.value]) selectedIds.push(data[this.replaceFields.value])
}) })
this.selectedKeys = selectedIds this.selectedKeys = selectedIds
this.$emit('select', selectedIds) this.$emit('select', selectedIds)
}, },
onUpdateSwiper() { onUpdateSwiper() {
clearTimeout(timer) clearTimeout(timer)
timer = setTimeout(() => { timer = setTimeout(() => {
swiper.update() swiper.update()
swiper.update() swiper.update()
}, 300) }, 300)
}, },
generateKey(data, level) { generateKey(data, level) {
const n = level || [0] const n = level || [0]
n.push(0) n.push(0)
data.forEach((p, i) => { data.forEach((p, i) => {
n[n.length - 1] = i n[n.length - 1] = i
p.key = n.join('-') p.key = n.join('-')
p.scopedSlots = { title: 'title' } p.scopedSlots = { title: 'title' }
if (p[this.replaceFields.children]) { if (p[this.replaceFields.children]) {
this.generateKey(p[this.replaceFields.children], Object.assign([], n)) this.generateKey(p[this.replaceFields.children], Object.assign([], n))
} }
}) })
return data return data
}, },
generateList(data) { generateList(data) {
// 这里获取不到Key // 这里获取不到Key
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const { key } = data[i] const { key } = data[i]
this.list.push({ this.list.push({
key, key,
[this.replaceFields.value]: data[i][this.replaceFields.value], [this.replaceFields.value]: data[i][this.replaceFields.value],
[this.replaceFields.title]: data[i][this.replaceFields.title] [this.replaceFields.title]: data[i][this.replaceFields.title]
}) })
if (data[i][this.replaceFields.children]) { if (data[i][this.replaceFields.children]) {
this.generateList(data[i][this.replaceFields.children]) this.generateList(data[i][this.replaceFields.children])
} }
} }
}, },
getParentKey(key, tree) { getParentKey(key, tree) {
let parentKey; let parentKey;
for (let i = 0; i < tree.length; i++) { for (let i = 0; i < tree.length; i++) {
const node = tree[i] const node = tree[i]
if (node[this.replaceFields.children]) { if (node[this.replaceFields.children]) {
if (node[this.replaceFields.children].some(item => item.key === key)) { if (node[this.replaceFields.children].some(item => item.key === key)) {
parentKey = node.key parentKey = node.key
} else if (this.getParentKey(key, node[this.replaceFields.children])) { } else if (this.getParentKey(key, node[this.replaceFields.children])) {
parentKey = this.getParentKey(key, node[this.replaceFields.children]) parentKey = this.getParentKey(key, node[this.replaceFields.children])
} }
} }
} }
return parentKey; return parentKey;
}, },
}, },
render() { render() {
const props = { const props = {
treeData: this.data, treeData: this.data,
expandedKeys: this.expandedKeys, expandedKeys: this.expandedKeys,
autoExpandParent: this.autoExpandParent, autoExpandParent: this.autoExpandParent,
} }
const on = { const on = {
expand: this.onExpand, expand: this.onExpand,
select: this.onSelect select: this.onSelect
} }
const scopedSlots = { const scopedSlots = {
title: (props) => { title: (props) => {
const title = props[this.replaceFields.title] const title = props[this.replaceFields.title]
return ( return (
<div> <div>
{ {
title.indexOf(this.searchValue) > -1 ? title.indexOf(this.searchValue) > -1 ?
<span> <span>
{title.substr(0, title.indexOf(this.searchValue))} {title.substr(0, title.indexOf(this.searchValue))}
<span style="color: #f50">{this.searchValue}</span> <span style="color: #f50">{this.searchValue}</span>
{title.substr(title.indexOf(this.searchValue) + this.searchValue.length)} {title.substr(title.indexOf(this.searchValue) + this.searchValue.length)}
</span> </span>
: :
<span>{title}</span> <span>{title}</span>
} }
</div> </div>
); );
} }
} }
return ( return (
<a-layout class="yo-tree-layout"> <a-layout class="yo-tree-layout">
<a-layout-sider width="240px"> <a-layout-sider width="240px">
<a-layout-header> <a-layout-header>
<div class="header-actions"> <div class="header-actions">
<a-input-search allowClear={true} placeholder="请输入检索关键字" onSearch={this.onSearch} /> <a-input-search allowClear={true} placeholder="请输入检索关键字" onSearch={this.onSearch} />
</div> </div>
</a-layout-header> </a-layout-header>
<div class="yo-tree-layout--bar"> <div class="yo-tree-layout--bar">
<a-tooltip placement="bottom" title="折叠全部"> <a-tooltip placement="bottom" title="折叠全部">
<a-icon type="switcher" onClick={this.onUnexpandAll} /> <a-icon type="switcher" onClick={this.onUnexpandAll} />
</a-tooltip> </a-tooltip>
</div> </div>
<div class="swiper-container" ref="swiper"> <div class="swiper-container" ref="swiper">
<div class="swiper-wrapper"> <div class="swiper-wrapper">
<div class="swiper-slide"> <div class="swiper-slide">
<a-spin style={{ height: '100%' }} spinning={this.loading}> <a-spin style={{ height: '100%' }} spinning={this.loading}>
<a-icon slot="indicator" type="loading" spin /> <a-icon slot="indicator" type="loading" spin />
{ {
!this.loading && !this.list.length ? !this.loading && !this.list.length ?
<a-empty description={false} class="ant-list-empty-text"> <a-empty description={false} class="ant-list-empty-text">
<template slot="image"> <template slot="image">
<a-icon class="h3 mt-xl mb-md" type="smile" /> <a-icon class="h3 mt-xl mb-md" type="smile" />
<p>暂无数据</p> <p>暂无数据</p>
</template> </template>
</a-empty> </a-empty>
: :
<a-tree {...{ props, on, scopedSlots }} /> <a-tree {...{ props, on, scopedSlots }} />
} }
</a-spin> </a-spin>
</div> </div>
</div> </div>
<div class="swiper-scrollbar" /> <div class="swiper-scrollbar" />
</div> </div>
</a-layout-sider> </a-layout-sider>
<a-layout-content> <a-layout-content>
<container> <container>
<a-breadcrumb class="mt-md mb-md"> <a-breadcrumb class="mt-md mb-md">
{this.renderBreadcrumbItem()} {this.renderBreadcrumbItem()}
</a-breadcrumb> </a-breadcrumb>
</container> </container>
{this.$scopedSlots.default ? this.$scopedSlots.default() : null} {this.$scopedSlots.default ? this.$scopedSlots.default() : null}
</a-layout-content> </a-layout-content>
</a-layout> </a-layout>
) )
} }
} }

View File

@@ -1,107 +1,107 @@
<template> <template>
<a-card :bordered="false" title="年度项目总完成情况"> <a-card :bordered="false" title="年度项目总完成情况">
<a-form-model :model="query" layout="inline"> <a-form-model :model="query" layout="inline">
<a-form-model-item label="区域"> <a-form-model-item label="区域">
<a-dropdown> <a-dropdown>
<span> <span>
宁波市 宁波市
<a-icon type="down" /> <a-icon type="down" />
</span> </span>
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item>宁波市</a-menu-item> <a-menu-item>宁波市</a-menu-item>
<a-menu-item>鄞州区</a-menu-item> <a-menu-item>鄞州区</a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="年份"> <a-form-model-item label="年份">
<a-dropdown> <a-dropdown>
<span> <span>
2021 2021
<a-icon type="down" /> <a-icon type="down" />
</span> </span>
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item>2021</a-menu-item> <a-menu-item>2021</a-menu-item>
<a-menu-item>2020</a-menu-item> <a-menu-item>2020</a-menu-item>
<a-menu-item>2019</a-menu-item> <a-menu-item>2019</a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
<div :style="{ height: '300px' }" ref="chart"></div> <div :style="{ height: '300px' }" ref="chart"></div>
</a-card> </a-card>
</template> </template>
<script> <script>
import * as echarts from 'echarts'; import * as echarts from 'echarts';
export default { export default {
data() { data() {
return { return {
query: { query: {
area: '宁波市', area: '宁波市',
year: '2021', year: '2021',
}, },
options: { options: {
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
}, },
legend: { legend: {
show: false, show: false,
}, },
grid: { grid: {
left: '3%', left: '3%',
right: '4%', right: '4%',
bottom: '3%', bottom: '3%',
containLabel: true, containLabel: true,
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
boundaryGap: false, boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
}, },
series: [ series: [
{ {
name: '邮件营销', name: '邮件营销',
type: 'line', type: 'line',
stack: '总量', stack: '总量',
data: [120, 132, 101, 134, 90, 230, 210], data: [120, 132, 101, 134, 90, 230, 210],
}, },
{ {
name: '联盟广告', name: '联盟广告',
type: 'line', type: 'line',
stack: '总量', stack: '总量',
data: [220, 182, 191, 234, 290, 330, 310], data: [220, 182, 191, 234, 290, 330, 310],
}, },
{ {
name: '视频广告', name: '视频广告',
type: 'line', type: 'line',
stack: '总量', stack: '总量',
data: [150, 232, 201, 154, 190, 330, 410], data: [150, 232, 201, 154, 190, 330, 410],
}, },
{ {
name: '直接访问', name: '直接访问',
type: 'line', type: 'line',
stack: '总量', stack: '总量',
data: [320, 332, 301, 334, 390, 330, 320], data: [320, 332, 301, 334, 390, 330, 320],
}, },
{ {
name: '搜索引擎', name: '搜索引擎',
type: 'line', type: 'line',
stack: '总量', stack: '总量',
data: [820, 932, 901, 934, 1290, 1330, 1320], data: [820, 932, 901, 934, 1290, 1330, 1320],
}, },
], ],
}, },
}; };
}, },
mounted() { mounted() {
var chartDom = this.$refs.chart; var chartDom = this.$refs.chart;
var myChart = echarts.init(chartDom); var myChart = echarts.init(chartDom);
myChart.setOption(this.options); myChart.setOption(this.options);
window.addEventListener("resize",function(){ window.addEventListener("resize",function(){
myChart.resize(); myChart.resize();
}) })
}, },
}; };
</script> </script>

View File

@@ -1,40 +1,40 @@
@import (reference) '~@/assets/style/app.less'; @import (reference) '~@/assets/style/app.less';
.home-header { .home-header {
margin-bottom: @padding-md; margin-bottom: @padding-md;
padding: @padding-lg 0; padding: @padding-lg 0;
background-color: @white; background-color: @white;
} }
.home-header-row { .home-header-row {
display: flex; display: flex;
} }
.home-header-content { .home-header-content {
margin-left: @padding-lg; margin-left: @padding-lg;
h4 { h4 {
span { span {
color: @primary-color; color: @primary-color;
} }
} }
p { p {
margin: 0; margin: 0;
} }
} }
.home-container { .home-container {
.ant-card-meta-title { .ant-card-meta-title {
font-size: @font-size-base + 1px; font-size: @font-size-base + 1px;
display: -webkit-box; display: -webkit-box;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
height: 42px; height: 42px;
white-space: normal; white-space: normal;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
} }
.ant-card-meta-description { .ant-card-meta-description {
.ant-row-flex { .ant-row-flex {
height: 24px; height: 24px;
} }
} }
} }

View File

@@ -1,66 +1,66 @@
<template> <template>
<div> <div>
<div class="home-header"> <div class="home-header">
<container> <container>
<a-row align="middle" justify="space-between" type="flex"> <a-row align="middle" justify="space-between" type="flex">
<a-col> <a-col>
<div class="home-header-row" v-if="$root.global.info"> <div class="home-header-row" v-if="$root.global.info">
<div class="home-header-avatar"> <div class="home-header-avatar">
<yo-image :id="$root.global.info.avatar" :size="64" icon="user" type="avatar" /> <yo-image :id="$root.global.info.avatar" :size="64" icon="user" type="avatar" />
</div> </div>
<div class="home-header-content"> <div class="home-header-content">
<h4> <h4>
{{ $moment().format('A') }} {{ $moment().format('A') }}
<span>{{ $root.global.info.nickName || $root.global.info.name }}</span>欢迎您登录系统 <span>{{ $root.global.info.nickName || $root.global.info.name }}</span>欢迎您登录系统
</h4> </h4>
<p> <p>
<span>上次IP{{ $root.global.info.lastLoginIp }}</span> <span>上次IP{{ $root.global.info.lastLoginIp }}</span>
<a-divider type="vertical" /> <a-divider type="vertical" />
<span>上次登录时间{{ $root.global.info.lastLoginTime }}</span> <span>上次登录时间{{ $root.global.info.lastLoginTime }}</span>
</p> </p>
</div> </div>
</div> </div>
</a-col> </a-col>
<a-col> <a-col>
<a-icon :style="{ fontSize: '20px', color: '#f80000' }" class="mr-xs" type="mail" />您有 <a-icon :style="{ fontSize: '20px', color: '#f80000' }" class="mr-xs" type="mail" />您有
<a href="#">0</a>封未读邮件请尽快查收 <a href="#">0</a>封未读邮件请尽快查收
</a-col> </a-col>
</a-row> </a-row>
</container> </container>
</div> </div>
<container class="home-container"> <container class="home-container">
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="24"> <a-col :span="24">
<Statistics /> <Statistics />
</a-col> </a-col>
<a-col :lg="12" :md="24" :xl="16"> <a-col :lg="12" :md="24" :xl="16">
<Task /> <Task />
<List /> <List />
</a-col> </a-col>
<a-col :lg="12" :md="24" :xl="8"> <a-col :lg="12" :md="24" :xl="8">
<Notice /> <Notice />
<Charts /> <Charts />
</a-col> </a-col>
</a-row> </a-row>
</container> </container>
</div> </div>
</template> </template>
<script> <script>
import './index.less'; import './index.less';
import Statistics from './statistics'; import Statistics from './statistics';
import Task from './task'; import Task from './task';
import Notice from './notice'; import Notice from './notice';
import List from './list'; import List from './list';
import Charts from './charts'; import Charts from './charts';
export default { export default {
components: { components: {
Statistics, Statistics,
Task, Task,
Notice, Notice,
List, List,
Charts, Charts,
}, },
}; };
</script> </script>

View File

@@ -1,99 +1,99 @@
<template> <template>
<a-card <a-card
:active-tab-key="key" :active-tab-key="key"
:bodyStyle="{ padding: 0 }" :bodyStyle="{ padding: 0 }"
:bordered="false" :bordered="false"
:tab-list="tabList" :tab-list="tabList"
@tabChange="key => onTabChange(key, 'key')" @tabChange="key => onTabChange(key, 'key')"
> >
<a-table :columns="columns" :data-source="data" :pagination="false" /> <a-table :columns="columns" :data-source="data" :pagination="false" />
</a-card> </a-card>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
key: '1', key: '1',
tabList: [ tabList: [
{ {
key: '1', key: '1',
tab: '新建项目', tab: '新建项目',
}, },
{ {
key: '2', key: '2',
tab: '正在签约项目', tab: '正在签约项目',
}, },
{ {
key: '3', key: '3',
tab: '完成签约项目', tab: '完成签约项目',
}, },
{ {
key: '4', key: '4',
tab: '项目进度', tab: '项目进度',
}, },
], ],
columns: [ columns: [
{ {
title: '区域', title: '区域',
dataIndex: 'area', dataIndex: 'area',
}, },
{ {
title: '项目名称', title: '项目名称',
dataIndex: 'title', dataIndex: 'title',
}, },
{ {
title: '户数', title: '户数',
dataIndex: 'count', dataIndex: 'count',
}, },
{ {
title: '时间', title: '时间',
dataIndex: 'date', dataIndex: 'date',
}, },
], ],
data: [ data: [
{ {
key: '1', key: '1',
area: '海曙区', area: '海曙区',
title: '曙光电影院地块', title: '曙光电影院地块',
count: 13, count: 13,
date: '2021-01-01', date: '2021-01-01',
}, },
{ {
key: '2', key: '2',
area: '江北区', area: '江北区',
title: '大庆新村地块旧城区改建项目', title: '大庆新村地块旧城区改建项目',
count: 322, count: 322,
date: '2021-01-01', date: '2021-01-01',
}, },
{ {
key: '3', key: '3',
area: '宁海县', area: '宁海县',
title: '桥头胡街道旧城区改造华驰文教地块', title: '桥头胡街道旧城区改造华驰文教地块',
count: 1, count: 1,
date: '2021-01-01', date: '2021-01-01',
}, },
{ {
key: '4', key: '4',
area: '慈溪市', area: '慈溪市',
title: '七二三南延道路工程', title: '七二三南延道路工程',
count: 1, count: 1,
date: '2021-01-01', date: '2021-01-01',
}, },
{ {
key: '5', key: '5',
area: '北仑区', area: '北仑区',
title: '原粮食局宿舍楼1号、2号楼太河路北延工程', title: '原粮食局宿舍楼1号、2号楼太河路北延工程',
count: 32, count: 32,
date: '2021-01-01', date: '2021-01-01',
}, },
], ],
}; };
}, },
methods: { methods: {
onTabChange(key, type) { onTabChange(key, type) {
this[type] = key; this[type] = key;
}, },
}, },
}; };
</script> </script>

View File

@@ -1,28 +1,28 @@
<template> <template>
<a-card :bordered="false" title="通知"> <a-card :bordered="false" title="通知">
<a href="#" slot="extra">更多</a> <a href="#" slot="extra">更多</a>
<a-list :data-source="data" item-layout="horizontal"> <a-list :data-source="data" item-layout="horizontal">
<a-list-item slot="renderItem" slot-scope="item"> <a-list-item slot="renderItem" slot-scope="item">
<a-list-item-meta <a-list-item-meta
:description="$moment().format('YYYY-MM-DD HH:mm:ss')" :description="$moment().format('YYYY-MM-DD HH:mm:ss')"
:title="item.title" :title="item.title"
> >
<a-icon :style="{ fontSize: '18px' }" slot="avatar" theme="twoTone" type="message" /> <a-icon :style="{ fontSize: '18px' }" slot="avatar" theme="twoTone" type="message" />
</a-list-item-meta> </a-list-item-meta>
</a-list-item> </a-list-item>
</a-list> </a-list>
</a-card> </a-card>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
data: [ data: [
{ title: '关于2020年度房屋征收评估机构信用考核情况的通报' }, { title: '关于2020年度房屋征收评估机构信用考核情况的通报' },
{ title: '关于2020年度房屋征收评估机构信用考核情况的通报' }, { title: '关于2020年度房屋征收评估机构信用考核情况的通报' },
{ title: '关于2020年度房屋征收评估机构信用考核情况的通报' }, { title: '关于2020年度房屋征收评估机构信用考核情况的通报' },
], ],
}; };
}, },
}; };
</script> </script>

View File

@@ -1,56 +1,56 @@
<template> <template>
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :lg="5" :md="8" :sm="24"> <a-col :lg="5" :md="8" :sm="24">
<a-card :bordered="false" :hoverable="true"> <a-card :bordered="false" :hoverable="true">
<a-statistic :value="0" class="text-center" title="已完成的项目" /> <a-statistic :value="0" class="text-center" title="已完成的项目" />
</a-card> </a-card>
</a-col> </a-col>
<a-col :lg="5" :md="8" :sm="24"> <a-col :lg="5" :md="8" :sm="24">
<a-card :bordered="false" :hoverable="true"> <a-card :bordered="false" :hoverable="true">
<a-statistic :value="c" class="text-center" title="正在进行的项目" /> <a-statistic :value="c" class="text-center" title="正在进行的项目" />
</a-card> </a-card>
</a-col> </a-col>
<a-col :lg="5" :md="8" :sm="24"> <a-col :lg="5" :md="8" :sm="24">
<a-card :bordered="false" :hoverable="true"> <a-card :bordered="false" :hoverable="true">
<a-statistic :value="0" class="text-center" title="还未开始的项目" /> <a-statistic :value="0" class="text-center" title="还未开始的项目" />
</a-card> </a-card>
</a-col> </a-col>
<a-col :lg="9" :md="24"> <a-col :lg="9" :md="24">
<a-card :bordered="false" :hoverable="true"> <a-card :bordered="false" :hoverable="true">
<a-row> <a-row>
<a-col :span="12"> <a-col :span="12">
<a-statistic :value="8893" class="text-center" title="用户总量" /> <a-statistic :value="8893" class="text-center" title="用户总量" />
</a-col> </a-col>
<a-col :span="12"> <a-col :span="12">
<a-statistic :value="1255" :value-style="{ color: '#3f8600' }" class="text-center"> <a-statistic :value="1255" :value-style="{ color: '#3f8600' }" class="text-center">
<template #title> <template #title>
<a-dropdown> <a-dropdown>
<span> <span>
当月活跃用户 当月活跃用户
<a-icon type="down" /> <a-icon type="down" />
</span> </span>
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item>当月活跃用户</a-menu-item> <a-menu-item>当月活跃用户</a-menu-item>
<a-menu-item>当年活跃用户</a-menu-item> <a-menu-item>当年活跃用户</a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</template> </template>
<template #prefix> <template #prefix>
<a-icon :style="{ fontSize: '13px' }" type="arrow-up" /> <a-icon :style="{ fontSize: '13px' }" type="arrow-up" />
</template> </template>
</a-statistic> </a-statistic>
</a-col> </a-col>
</a-row> </a-row>
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
c: 6, c: 6,
}; };
}, },
}; };
</script> </script>

View File

@@ -1,56 +1,56 @@
<template> <template>
<a-card :bordered="false" title="待办"> <a-card :bordered="false" title="待办">
<a href="#" slot="extra">更多</a> <a href="#" slot="extra">更多</a>
<a-card-grid :key="n" v-for="(item, n) in data"> <a-card-grid :key="n" v-for="(item, n) in data">
<a-card-meta> <a-card-meta>
<div slot="title"> <div slot="title">
<a-tooltip placement="top"> <a-tooltip placement="top">
<template slot="title">{{ item.title }}</template> <template slot="title">{{ item.title }}</template>
{{ item.title }} {{ item.title }}
</a-tooltip> </a-tooltip>
</div> </div>
<a-row align="middle" slot="description" type="flex"> <a-row align="middle" slot="description" type="flex">
<a-col flex="32px" v-if="item.avatar"> <a-col flex="32px" v-if="item.avatar">
<a-avatar :size="24" :src="item.avatar" shape="square" /> <a-avatar :size="24" :src="item.avatar" shape="square" />
</a-col> </a-col>
<a-col flex="auto"> <a-col flex="auto">
<a-row justify="space-between" type="flex"> <a-row justify="space-between" type="flex">
<a-col>软件开发人员</a-col> <a-col>软件开发人员</a-col>
<a-col>2020-01-01</a-col> <a-col>2020-01-01</a-col>
</a-row> </a-row>
</a-col> </a-col>
</a-row> </a-row>
</a-card-meta> </a-card-meta>
</a-card-grid> </a-card-grid>
</a-card> </a-card>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
data: [ data: [
{ {
title: '市区雷公巷地块项目选择评估机构及上传相关材料(软件开发人员)', title: '市区雷公巷地块项目选择评估机构及上传相关材料(软件开发人员)',
avatar: 'https://tb1.bdstatic.com/tb/steam.jpeg', avatar: 'https://tb1.bdstatic.com/tb/steam.jpeg',
}, },
{ {
title: '宁海县山河岭6号地块备案(胡靖)', title: '宁海县山河岭6号地块备案(胡靖)',
avatar: avatar:
'https://gss0.bdstatic.com/6LZ1dD3d1sgCo2Kml5_Y_D3/sys/portrait/item/tb.1.ac342cde.2vNGrtpPcIUN6lJpSnty3g?t=1615176031', 'https://gss0.bdstatic.com/6LZ1dD3d1sgCo2Kml5_Y_D3/sys/portrait/item/tb.1.ac342cde.2vNGrtpPcIUN6lJpSnty3g?t=1615176031',
}, },
{ title: '宁海县盛宁线力洋至胡陈段公路工程田交朱村 地块备案(胡靖)' }, { title: '宁海县盛宁线力洋至胡陈段公路工程田交朱村 地块备案(胡靖)' },
{ {
title: '慈溪市慈溪市危旧房改造一期西门小区A1区块项目备案(陆承)', title: '慈溪市慈溪市危旧房改造一期西门小区A1区块项目备案(陆承)',
avatar: avatar:
'https://gss0.bdstatic.com/6LZ1dD3d1sgCo2Kml5_Y_D3/sys/portrait/item/tb.1.54e2faca.uBtqRshdnVUXL9XFfQMTwg?t=1604074726', 'https://gss0.bdstatic.com/6LZ1dD3d1sgCo2Kml5_Y_D3/sys/portrait/item/tb.1.54e2faca.uBtqRshdnVUXL9XFfQMTwg?t=1604074726',
}, },
{ title: '江北区孔浦成片危旧住宅区改造项目(六号区块)备案(成薇)' }, { title: '江北区孔浦成片危旧住宅区改造项目(六号区块)备案(成薇)' },
{ title: '镇海区宁镇路改扩建工程(庄市段)备案(董力)' }, { title: '镇海区宁镇路改扩建工程(庄市段)备案(董力)' },
{ title: '鄞州区茶桃公路(同谷路—金峨路延伸段)项目备案(软件开发人员)' }, { title: '鄞州区茶桃公路(同谷路—金峨路延伸段)项目备案(软件开发人员)' },
{ title: '鄞州区咸祥大嵩湖工程备案(软件开发人员)' }, { title: '鄞州区咸祥大嵩湖工程备案(软件开发人员)' },
{ title: '江北区三官堂大桥及接线工程项目备案(成薇)' }, { title: '江北区三官堂大桥及接线工程项目备案(成薇)' },
], ],
}; };
}, },
}; };
</script> </script>

View File

@@ -1,5 +1,5 @@
/** /**
基本上所有列表页都可以通过拷贝此处的种子文件实现增删改查的功能 基本上所有列表页都可以通过拷贝此处的种子文件实现增删改查的功能
所有带 ... 的注释是可以依据当前业务添加内容的地方 所有带 ... 的注释是可以依据当前业务添加内容的地方
其他所有尽量不要修改 其他所有尽量不要修改
**/ **/

View File

@@ -1,114 +1,114 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
</div> </div>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
}; };
export default { export default {
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
/* ... */ /* ... */
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
}, },
}; };
</script> </script>

View File

@@ -1,216 +1,216 @@
<template> <template>
<!-- <!--
普通查询表格 普通查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="authCode:page" slot="query"> <Auth auth="authCode:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<!-- ... --> <!-- ... -->
</Auth> </Auth>
<Auth auth="authCode:add" slot="operator"> <Auth auth="authCode:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增...</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增...</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<!-- ... --> <!-- ... -->
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="authCode:edit"> <Auth auth="authCode:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="authCode:delete"> <Auth auth="authCode:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
<!-- ... --> <!-- ... -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form"> <yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form"> <yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
page: 'testPageApi...', page: 'testPageApi...',
add: 'testAddApi', add: 'testAddApi',
edit: 'testEditApi', edit: 'testEditApi',
delete: 'testDeleteApi...', delete: 'testDeleteApi...',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
data() { data() {
return { return {
api, api,
name: '...', name: '...',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [], columns: [],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
codes: { codes: {
code1: [], code1: [],
code2: [], code2: [],
}, },
}; };
}, },
created() { created() {
/** 按需加载字典编码 */ /** 按需加载字典编码 */
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth(/* ... */); const flag = this.$auth(/* ... */);
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {}; this.query = {};
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() { onLoadCodes() {
this.$api this.$api
.$queue([ .$queue([
this.$api.sysDictTypeDropDownAwait({ code: 'code1' }), this.$api.sysDictTypeDropDownAwait({ code: 'code1' }),
this.$api.sysDictTypeDropDownAwait({ code: 'code2' }), this.$api.sysDictTypeDropDownAwait({ code: 'code2' }),
/* ... */ /* ... */
]) ])
.then(([code1, code2]) => { .then(([code1, code2]) => {
this.codes.code1 = code1.data; this.codes.code1 = code1.data;
this.codes.code2 = code2.data; this.codes.code2 = code2.data;
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,158 +1,158 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="应用名称" prop="name"> <a-form-model-item label="应用名称" prop="name">
<a-input placeholder="请输入应用名称" v-model="form.name" /> <a-input placeholder="请输入应用名称" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码" prop="code"> <a-form-model-item label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="图标" prop="icon"> <a-form-model-item label="图标" prop="icon">
<a-input :disabled="true" placeholder="请选择图标" v-model="form.icon"> <a-input :disabled="true" placeholder="请选择图标" v-model="form.icon">
<a-icon :type="form.icon" slot="addonBefore" v-if="form.icon" /> <a-icon :type="form.icon" slot="addonBefore" v-if="form.icon" />
<a-icon @click="onOpenSelectIcon" slot="addonAfter" type="setting" /> <a-icon @click="onOpenSelectIcon" slot="addonAfter" type="setting" />
</a-input> </a-input>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="图标颜色" prop="color"> <a-form-model-item label="图标颜色" prop="color">
<chrome-picker v-model="form.color" /> <chrome-picker v-model="form.color" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="排序" prop="sort"> <a-form-model-item label="排序" prop="sort">
<a-input-number <a-input-number
:max="1000" :max="1000"
:min="0" :min="0"
class="w-100-p" class="w-100-p"
placeholder="请输入排序" placeholder="请输入排序"
v-model="form.sort" v-model="form.sort"
/> />
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-spin> </a-spin>
<yo-icon-selector ref="icon-selector" v-model="form.icon" /> <yo-icon-selector ref="icon-selector" v-model="form.icon" />
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import YoIconSelector from '@/components/yoIconSelector'; import YoIconSelector from '@/components/yoIconSelector';
import { Chrome } from 'vue-color'; import { Chrome } from 'vue-color';
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
color: '#ffffff', color: '#ffffff',
active: false, active: false,
}; };
export default { export default {
components: { components: {
YoIconSelector, YoIconSelector,
ChromePicker: Chrome, ChromePicker: Chrome,
}, },
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: { form: {
...defaultForm, ...defaultForm,
}, },
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
/* ... */ /* ... */
name: [{ required: true, message: '请输入应用名称' }], name: [{ required: true, message: '请输入应用名称' }],
code: [{ required: true, message: '请输入唯一编码' }], code: [{ required: true, message: '请输入唯一编码' }],
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
record.color = record.color.constructor === Object ? record.color.hex : record.color; record.color = record.color.constructor === Object ? record.color.hex : record.color;
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
onOpenSelectIcon() { onOpenSelectIcon() {
this.$refs['icon-selector'].onOpen(this.form.icon); this.$refs['icon-selector'].onOpen(this.form.icon);
}, },
}, },
}; };
</script> </script>

View File

@@ -1,280 +1,280 @@
<template> <template>
<!-- <!--
普通查询表格 普通查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysApp:page" slot="query"> <Auth auth="sysApp:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="应用名称"> <a-form-model-item label="应用名称">
<a-input placeholder="请输入应用名称" v-model="query.name" /> <a-input placeholder="请输入应用名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码"> <a-form-model-item label="唯一编码">
<a-input placeholder="请输入唯一编码" v-model="query.code" /> <a-input placeholder="请输入唯一编码" v-model="query.code" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysApp:add" slot="operator"> <Auth auth="sysApp:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增应用</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增应用</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<!-- ... --> <!-- ... -->
<span slot="active" slot-scope="text, record"> <span slot="active" slot-scope="text, record">
{{ text ? '是' : '否' }} {{ text ? '是' : '否' }}
<Auth auth="sysApp:setAsDefault" v-if="!record.active"> <Auth auth="sysApp:setAsDefault" v-if="!record.active">
<yo-table-actions> <yo-table-actions>
<span></span> <span></span>
<a-popconfirm <a-popconfirm
@confirm="onSetDefault(record)" @confirm="onSetDefault(record)"
placement="topRight" placement="topRight"
title="是否确认设置为默认应用" title="是否确认设置为默认应用"
> >
<a>设为默认</a> <a>设为默认</a>
</a-popconfirm> </a-popconfirm>
</yo-table-actions> </yo-table-actions>
</Auth> </Auth>
</span> </span>
<span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span> <span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span>
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysApp:edit"> <Auth auth="sysApp:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysApp:delete"> <Auth auth="sysApp:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
<!-- ... --> <!-- ... -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form"> <yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form"> <yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
page: 'getAppPage', page: 'getAppPage',
add: 'sysAppAdd', add: 'sysAppAdd',
edit: 'sysAppEdit', edit: 'sysAppEdit',
delete: 'sysAppDelete', delete: 'sysAppDelete',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
data() { data() {
return { return {
api, api,
name: '应用', name: '应用',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [ columns: [
{ {
title: '应用名称', title: '应用名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '唯一编码', title: '唯一编码',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '是否默认', title: '是否默认',
dataIndex: 'active', dataIndex: 'active',
scopedSlots: { scopedSlots: {
customRender: 'active', customRender: 'active',
}, },
sorter: true, sorter: true,
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
scopedSlots: { scopedSlots: {
customRender: 'status', customRender: 'status',
}, },
sorter: true, sorter: true,
}, },
{ {
title: '排序', title: '排序',
dataIndex: 'sort', dataIndex: 'sort',
sorter: true, sorter: true,
}, },
], ],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
codes: { codes: {
yesOrNo: [], yesOrNo: [],
commonStatus: [], commonStatus: [],
}, },
}; };
}, },
created() { created() {
/** 按需加载字典编码 */ /** 按需加载字典编码 */
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ const flag = this.$auth({
sysApp: [['edit'], ['delete']], sysApp: [['edit'], ['delete']],
}); });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {}; this.query = {};
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() { onLoadCodes() {
this.$api this.$api
.$queue([ .$queue([
this.$api.sysDictTypeDropDownAwait({ code: 'yes_or_no' }), this.$api.sysDictTypeDropDownAwait({ code: 'yes_or_no' }),
this.$api.sysDictTypeDropDownAwait({ code: 'common_status' }), this.$api.sysDictTypeDropDownAwait({ code: 'common_status' }),
/* ... */ /* ... */
]) ])
.then(([code1, code2]) => { .then(([code1, code2]) => {
this.codes.yesOrNo = code1.data; this.codes.yesOrNo = code1.data;
this.codes.commonStatus = code2.data; this.codes.commonStatus = code2.data;
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
onSetDefault(record) { onSetDefault(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api.sysAppSetAsDefault({ id: record.id }).then(({ success }) => { this.$api.sysAppSetAsDefault({ id: record.id }).then(({ success }) => {
this.onResult(success, '设置成功'); this.onResult(success, '设置成功');
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,159 +1,159 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="角色名" prop="name"> <a-form-model-item label="角色名" prop="name">
<a-input placeholder="请输入角色名" v-model="form.name" /> <a-input placeholder="请输入角色名" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item :disabled="editDisabled" label="唯一编码" prop="code"> <a-form-model-item :disabled="editDisabled" label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="系统参数" prop="sysFlag"> <a-form-model-item label="系统参数" prop="sysFlag">
<a-radio-group :disabled="editDisabled" v-model="form.sysFlag"> <a-radio-group :disabled="editDisabled" v-model="form.sysFlag">
<a-radio-button value="Y"></a-radio-button> <a-radio-button value="Y"></a-radio-button>
<a-radio-button value="N"></a-radio-button> <a-radio-button value="N"></a-radio-button>
</a-radio-group> </a-radio-group>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="所属分类" prop="groupCode"> <a-form-model-item label="所属分类" prop="groupCode">
<a-select :disabled="editDisabled" placeholder="请选择所属分类" v-model="form.groupCode"> <a-select :disabled="editDisabled" placeholder="请选择所属分类" v-model="form.groupCode">
<a-select-option <a-select-option
:key="i" :key="i"
:value="item.code" :value="item.code"
v-for="(item, i) in groupCode" v-for="(item, i) in groupCode"
>{{ item.value }}</a-select-option> >{{ item.value }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="参数值" prop="name"> <a-form-model-item label="参数值" prop="name">
<a-input placeholder="请输入参数值 " v-model="form.value" /> <a-input placeholder="请输入参数值 " v-model="form.value" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="备注" prop="remark"> <a-form-model-item label="备注" prop="remark">
<a-input placeholder="请输入备注" v-model="form.remark" /> <a-input placeholder="请输入备注" v-model="form.remark" />
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
}; };
export default { export default {
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
name: [{ required: true, message: '请输入应用名称' }], name: [{ required: true, message: '请输入应用名称' }],
code: [{ required: true, message: '请输入唯一编码' }], code: [{ required: true, message: '请输入唯一编码' }],
sysFlag: [{ required: true, message: '请选择参数类型' }], sysFlag: [{ required: true, message: '请选择参数类型' }],
groupCode: [{ required: true, message: '请选择所属分类' }], groupCode: [{ required: true, message: '请选择所属分类' }],
value: [{ required: true, message: '请输入参数值' }], value: [{ required: true, message: '请输入参数值' }],
/* ... */ /* ... */
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
editDisabled: false, editDisabled: false,
groupCode: [], groupCode: [],
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
this.editDisabled = this.form.sysFlag == 'Y'; this.editDisabled = this.form.sysFlag == 'Y';
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
this.groupCode = await this.onLoadgroupCodeData(); this.groupCode = await this.onLoadgroupCodeData();
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
/** /**
* *
* 获取所属分类字典表的内容 * 获取所属分类字典表的内容
*/ */
onLoadgroupCodeData() { onLoadgroupCodeData() {
return this.$api.sysDictTypeDropDown({ code: 'consts_type' }).then(({ data }) => { return this.$api.sysDictTypeDropDown({ code: 'consts_type' }).then(({ data }) => {
return data; return data;
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,238 +1,238 @@
<template> <template>
<!-- <!--
普通查询表格 普通查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysConfig:page" slot="query"> <Auth auth="sysConfig:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="参数名称"> <a-form-model-item label="参数名称">
<a-input placeholder="请输入参数名称" v-model="query.name" /> <a-input placeholder="请输入参数名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码"> <a-form-model-item label="唯一编码">
<a-input placeholder="请输入唯一编码" v-model="query.code" /> <a-input placeholder="请输入唯一编码" v-model="query.code" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysConfig:add" slot="operator"> <Auth auth="sysConfig:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增配置</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增配置</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<!-- ... --> <!-- ... -->
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysConfig:edit"> <Auth auth="sysConfig:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysConfig:delete"> <Auth auth="sysConfig:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
<!-- ... --> <!-- ... -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form"> <yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form"> <yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
page: 'sysConfigPage', page: 'sysConfigPage',
add: 'sysConfigAdd', add: 'sysConfigAdd',
edit: 'sysConfigEdit', edit: 'sysConfigEdit',
delete: 'sysConfigDelete', delete: 'sysConfigDelete',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
data() { data() {
return { return {
api, api,
name: '配置', name: '配置',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [ columns: [
{ {
title: '参数名称', title: '参数名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '唯一编码', title: '唯一编码',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '参数值', title: '参数值',
dataIndex: 'value', dataIndex: 'value',
sorter: true, sorter: true,
}, },
{ {
title: '所属分类', title: '所属分类',
dataIndex: 'groupCode', dataIndex: 'groupCode',
sorter: true, sorter: true,
}, },
{ {
title: '备注', title: '备注',
dataIndex: 'remark', dataIndex: 'remark',
sorter: true, sorter: true,
}, },
], ],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
codes: { codes: {
code1: [], code1: [],
code2: [], code2: [],
}, },
}; };
}, },
created() { created() {
/** 按需加载字典编码 */ /** 按需加载字典编码 */
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ const flag = this.$auth({
sysConfig: [['edit'], ['delete']], sysConfig: [['edit'], ['delete']],
}); });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {}; this.query = {};
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() {}, onLoadCodes() {},
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,221 +1,221 @@
<template> <template>
<a-card> <a-card>
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysDictData:page" slot="query"> <Auth auth="sysDictData:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<a-form-model-item label="文本"> <a-form-model-item label="文本">
<a-input placeholder="请输入文本" v-model="query.value" /> <a-input placeholder="请输入文本" v-model="query.value" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="字典值"> <a-form-model-item label="字典值">
<a-input placeholder="请输入字典值" v-model="query.code" /> <a-input placeholder="请输入字典值" v-model="query.code" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysDictData:add" slot="operator"> <Auth auth="sysDictData:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增字典数据</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增字典数据</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span> <span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span>
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysDictData:edit"> <Auth auth="sysDictData:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysDictData:delete"> <Auth auth="sysDictData:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
<yo-modal-form :action="$api.sysDictDataAdd" @ok="onReloadData" ref="add-form" title="新增字典数据"> <yo-modal-form :action="$api.sysDictDataAdd" @ok="onReloadData" ref="add-form" title="新增字典数据">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<yo-modal-form :action="$api.sysDictDataEdit" @ok="onReloadData" ref="edit-form" title="编辑字典数据"> <yo-modal-form :action="$api.sysDictDataEdit" @ok="onReloadData" ref="edit-form" title="编辑字典数据">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</a-card> </a-card>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
props: { props: {
type: { type: {
type: Object, type: Object,
}, },
codes: { codes: {
type: Object, type: Object,
}, },
}, },
data() { data() {
return { return {
query: { query: {
typeId: this.type.id, typeId: this.type.id,
}, },
columns: [ columns: [
{ {
title: '文本', title: '文本',
dataIndex: 'value', dataIndex: 'value',
sorter: true, sorter: true,
}, },
{ {
title: '字典值', title: '字典值',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '排序', title: '排序',
dataIndex: 'sort', dataIndex: 'sort',
sorter: true, sorter: true,
}, },
{ {
title: '备注', title: '备注',
dataIndex: 'remark', dataIndex: 'remark',
width: 200, width: 200,
sorter: true, sorter: true,
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
scopedSlots: { customRender: 'status' }, scopedSlots: { customRender: 'status' },
sorter: true, sorter: true,
}, },
], ],
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ sysDictData: [['edit'], ['delete']] }); const flag = this.$auth({ sysDictData: [['edit'], ['delete']] });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return ( return (
this.$api this.$api
/** !!此处必须修改调用的接口方法 */ /** !!此处必须修改调用的接口方法 */
.sysDictDataPage({ .sysDictDataPage({
...params, ...params,
...this.query, ...this.query,
}) })
.then((res) => { .then((res) => {
return res.data; return res.data;
}) })
); );
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
Object.keys(this.query).forEach((p) => { Object.keys(this.query).forEach((p) => {
if (p !== 'typeId') { if (p !== 'typeId') {
this.query[p] = undefined; this.query[p] = undefined;
} }
}); });
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() {}, onLoadCodes() {},
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
typeId: this.type.id, typeId: this.type.id,
record, record,
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api this.$api
/** !!此处必须修改调用的接口方法 */ /** !!此处必须修改调用的接口方法 */
.sysDictDataDelete(record) .sysDictDataDelete(record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,232 +1,232 @@
<template> <template>
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysDictType:page" slot="query"> <Auth auth="sysDictType:page" slot="query">
<a-form-model-item label="类型名称"> <a-form-model-item label="类型名称">
<a-input placeholder="请输入类型名称" v-model="query.name" /> <a-input placeholder="请输入类型名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码"> <a-form-model-item label="唯一编码">
<a-input placeholder="请输入唯一编码" v-model="query.code" /> <a-input placeholder="请输入唯一编码" v-model="query.code" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysDictType:add" slot="operator"> <Auth auth="sysDictType:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增字典类型</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增字典类型</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span> <span slot="status" slot-scope="text">{{ bindCodeValue(text, 'commonStatus') }}</span>
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysDictType:edit"> <Auth auth="sysDictType:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysDictType:delete"> <Auth auth="sysDictType:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
</yo-table-actions> </yo-table-actions>
</span> </span>
<div slot="expandedRowRender" slot-scope="record"> <div slot="expandedRowRender" slot-scope="record">
<dict-data :codes="codes" :type="record" /> <dict-data :codes="codes" :type="record" />
</div> </div>
</yo-table> </yo-table>
</a-card> </a-card>
<br /> <br />
<yo-modal-form :action="$api.sysDictTypeAdd" @ok="onReloadData" ref="add-form" title="新增字典类型"> <yo-modal-form :action="$api.sysDictTypeAdd" @ok="onReloadData" ref="add-form" title="新增字典类型">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<yo-modal-form :action="$api.sysDictTypeEdit" @ok="onReloadData" ref="edit-form" title="编辑字典类型"> <yo-modal-form :action="$api.sysDictTypeEdit" @ok="onReloadData" ref="edit-form" title="编辑字典类型">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import DictData from './dictdata'; import DictData from './dictdata';
import FormBody from './form'; import FormBody from './form';
export default { export default {
components: { components: {
DictData, DictData,
FormBody, FormBody,
}, },
data() { data() {
return { return {
query: {}, query: {},
columns: [ columns: [
{ {
title: '类型名称', title: '类型名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '唯一编码', title: '唯一编码',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '排序', title: '排序',
dataIndex: 'sort', dataIndex: 'sort',
sorter: true, sorter: true,
}, },
{ {
title: '备注', title: '备注',
dataIndex: 'remark', dataIndex: 'remark',
width: 200, width: 200,
sorter: true, sorter: true,
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
scopedSlots: { customRender: 'status' }, scopedSlots: { customRender: 'status' },
sorter: true, sorter: true,
}, },
], ],
codes: { codes: {
commonStatus: [], commonStatus: [],
}, },
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ sysDictType: [['edit'], ['delete']] }); const flag = this.$auth({ sysDictType: [['edit'], ['delete']] });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return ( return (
this.$api this.$api
/** !!此处必须修改调用的接口方法 */ /** !!此处必须修改调用的接口方法 */
.sysDictTypePage({ .sysDictTypePage({
...params, ...params,
...this.query, ...this.query,
}) })
.then((res) => { .then((res) => {
const data = res.data; const data = res.data;
data.rows = data.rows.map( data.rows = data.rows.map(
(p) => (p) =>
(p = { (p = {
...p, ...p,
data: [], data: [],
query: {}, query: {},
}) })
); );
return data; return data;
}) })
); );
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {}; this.query = {};
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() { onLoadCodes() {
this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'common_status' })]).then(([commonStatus]) => { this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'common_status' })]).then(([commonStatus]) => {
this.codes.commonStatus = commonStatus.data; this.codes.commonStatus = commonStatus.data;
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api this.$api
/** !!此处必须修改调用的接口方法 */ /** !!此处必须修改调用的接口方法 */
.sysDictTypeDelete(record) .sysDictTypeDelete(record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,213 +1,213 @@
<template> <template>
<container> <container>
<br /> <br />
<a-alert closable type="error"> <a-alert closable type="error">
<template slot="message"> <template slot="message">
<div>后端bug:任何操作的操作类型都是增加</div> <div>后端bug:任何操作的操作类型都是增加</div>
<div>没有记录请求参数.返回结果等信息</div> <div>没有记录请求参数.返回结果等信息</div>
</template> </template>
</a-alert> </a-alert>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<Auth auth="sysOpLog:page"> <Auth auth="sysOpLog:page">
<div class="yo-query-bar"> <div class="yo-query-bar">
<a-form-model :model="query" layout="inline"> <a-form-model :model="query" layout="inline">
<a-form-model-item label="日志名称"> <a-form-model-item label="日志名称">
<a-input placeholder="请输入日志名称" v-model="query.name" /> <a-input placeholder="请输入日志名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="操作类型"> <a-form-model-item label="操作类型">
<a-select <a-select
:style="{ width: '170px' }" :style="{ width: '170px' }"
allow-clear allow-clear
placeholder="请选择操作类型" placeholder="请选择操作类型"
v-model="query.opType" v-model="query.opType"
> >
<a-select-option <a-select-option
:key="item.code" :key="item.code"
:value="item.code" :value="item.code"
v-for="item in codes.opTypeDict" v-for="item in codes.opTypeDict"
>{{ item.value }}</a-select-option> >{{ item.value }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="是否成功"> <a-form-model-item label="是否成功">
<a-select <a-select
:style="{ width: '170px' }" :style="{ width: '170px' }"
allow-clear allow-clear
placeholder="请选择是否成功" placeholder="请选择是否成功"
v-model="query.success" v-model="query.success"
> >
<a-select-option value="true"></a-select-option> <a-select-option value="true"></a-select-option>
<a-select-option value="false"></a-select-option> <a-select-option value="false"></a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="操作时间"> <a-form-model-item label="操作时间">
<a-range-picker <a-range-picker
:show-time="{ :show-time="{
hideDisabledOptions: true, hideDisabledOptions: true,
defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')], defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')],
}" }"
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
v-model="query.dates" v-model="query.dates"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-button-group> <a-button-group>
<a-button @click="onQuery" type="primary">查询</a-button> <a-button @click="onQuery" type="primary">查询</a-button>
<a-button @click="() => { query = {}, onQuery() }">重置</a-button> <a-button @click="() => { query = {}, onQuery() }">重置</a-button>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</div> </div>
</Auth> </Auth>
<yo-table :columns="columns" :load-data="loadData" ref="table"> <yo-table :columns="columns" :load-data="loadData" ref="table">
<Auth auth="sysOpLog:delete" slot="operator"> <Auth auth="sysOpLog:delete" slot="operator">
<a-popconfirm @confirm="onOpLogClear" placement="bottomLeft" title="是否确认清空日志"> <a-popconfirm @confirm="onOpLogClear" placement="bottomLeft" title="是否确认清空日志">
<a-button>清空日志</a-button> <a-button>清空日志</a-button>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<span slot="opType" slot-scope="text">{{ bindCodeValue(text, 'opTypeDict') }}</span> <span slot="opType" slot-scope="text">{{ bindCodeValue(text, 'opTypeDict') }}</span>
<span slot="success" slot-scope="text">{{ text ? '是' : '否' }}</span> <span slot="success" slot-scope="text">{{ text ? '是' : '否' }}</span>
<a-descriptions bordered size="small" slot="expandedRowRender" slot-scope="record"> <a-descriptions bordered size="small" slot="expandedRowRender" slot-scope="record">
<a-descriptions-item :span="1" label="方法名称">{{ record.methodName }}</a-descriptions-item> <a-descriptions-item :span="1" label="方法名称">{{ record.methodName }}</a-descriptions-item>
<a-descriptions-item :span="2" label="地址">{{ record.location }}</a-descriptions-item> <a-descriptions-item :span="2" label="地址">{{ record.location }}</a-descriptions-item>
<a-descriptions-item label="浏览器">{{ record.browser }}</a-descriptions-item> <a-descriptions-item label="浏览器">{{ record.browser }}</a-descriptions-item>
<a-descriptions-item :span="2" label="操作系统">{{ record.os }}</a-descriptions-item> <a-descriptions-item :span="2" label="操作系统">{{ record.os }}</a-descriptions-item>
<a-descriptions-item :span="3" label="类名称">{{ record.className }}</a-descriptions-item> <a-descriptions-item :span="3" label="类名称">{{ record.className }}</a-descriptions-item>
<a-descriptions-item :span="3" label="返回结果">{{ record.result }}</a-descriptions-item> <a-descriptions-item :span="3" label="返回结果">{{ record.result }}</a-descriptions-item>
<a-descriptions-item :span="3" label="请求参数">{{ record.param }}</a-descriptions-item> <a-descriptions-item :span="3" label="请求参数">{{ record.param }}</a-descriptions-item>
<a-descriptions-item :span="3" label="具体消息">{{ record.message }}</a-descriptions-item> <a-descriptions-item :span="3" label="具体消息">{{ record.message }}</a-descriptions-item>
</a-descriptions> </a-descriptions>
</yo-table> </yo-table>
</a-card> </a-card>
<br /> <br />
</container> </container>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
query: {}, query: {},
columns: [ columns: [
{ {
title: '日志名称', title: '日志名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '操作类型', title: '操作类型',
dataIndex: 'opType', dataIndex: 'opType',
scopedSlots: { customRender: 'opType' }, scopedSlots: { customRender: 'opType' },
sorter: true, sorter: true,
}, },
{ {
title: '是否成功', title: '是否成功',
dataIndex: 'success', dataIndex: 'success',
scopedSlots: { customRender: 'success' }, scopedSlots: { customRender: 'success' },
sorter: true, sorter: true,
}, },
{ {
title: 'ip', title: 'ip',
dataIndex: 'ip', dataIndex: 'ip',
sorter: true, sorter: true,
}, },
{ {
title: '请求地址', title: '请求地址',
dataIndex: 'url', dataIndex: 'url',
scopedSlots: { customRender: 'url' }, scopedSlots: { customRender: 'url' },
sorter: true, sorter: true,
}, },
{ {
title: '操作时间', title: '操作时间',
dataIndex: 'opTime', dataIndex: 'opTime',
scopedSlots: { customRender: 'opTime' }, scopedSlots: { customRender: 'opTime' },
sorter: true, sorter: true,
}, },
{ {
title: '操作人', title: '操作人',
dataIndex: 'account', dataIndex: 'account',
sorter: true, sorter: true,
}, },
], ],
codes: { codes: {
opTypeDict: [], opTypeDict: [],
}, },
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
const query = this.$_.cloneDeep(this.query); const query = this.$_.cloneDeep(this.query);
if (query.dates && query.dates.length) { if (query.dates && query.dates.length) {
query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss'); query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss');
query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss'); query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss');
delete query.dates; delete query.dates;
} }
return this.$api return this.$api
.sysOpLogPage({ .sysOpLogPage({
...params, ...params,
...query, ...query,
}) })
.then((res) => { .then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 加载字典数据时的必要方法 * 加载字典数据时的必要方法
*/ */
onLoadCodes() { onLoadCodes() {
this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'op_type' })]).then(([commonStatus]) => { this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'op_type' })]).then(([commonStatus]) => {
this.codes.opTypeDict = commonStatus.data; this.codes.opTypeDict = commonStatus.data;
}); });
}, },
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
onOpLogClear() { onOpLogClear() {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api this.$api
.sysOpLogDelete() .sysOpLogDelete()
.then((res) => { .then((res) => {
if (res.success) { if (res.success) {
this.$message.success('清空成功'); this.$message.success('清空成功');
this.onReloadData(); this.onReloadData();
} else { } else {
this.$message.error('清空失败:' + res.message); this.$message.error('清空失败:' + res.message);
} }
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,205 +1,205 @@
<template> <template>
<container> <container>
<br /> <br />
<a-alert closable type="error"> <a-alert closable type="error">
<template slot="message">页面刷新的时候也会有保存登录日志但是没有ip显示</template> <template slot="message">页面刷新的时候也会有保存登录日志但是没有ip显示</template>
</a-alert> </a-alert>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<Auth auth="sysVisLog:page"> <Auth auth="sysVisLog:page">
<div class="yo-query-bar"> <div class="yo-query-bar">
<a-form-model :model="query" layout="inline"> <a-form-model :model="query" layout="inline">
<a-form-model-item label="日志名称"> <a-form-model-item label="日志名称">
<a-input placeholder="请输入日志名称" v-model="query.name" /> <a-input placeholder="请输入日志名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="访问类型"> <a-form-model-item label="访问类型">
<a-select <a-select
:style="{ width: '170px' }" :style="{ width: '170px' }"
allow-clear allow-clear
placeholder="请选择访问类型" placeholder="请选择访问类型"
v-model="query.visType" v-model="query.visType"
> >
<a-select-option <a-select-option
:key="item.code" :key="item.code"
:value="item.code" :value="item.code"
v-for="item in codes.visTypeDict" v-for="item in codes.visTypeDict"
>{{ item.value }}</a-select-option> >{{ item.value }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="是否成功"> <a-form-model-item label="是否成功">
<a-select <a-select
:style="{ width: '170px' }" :style="{ width: '170px' }"
allow-clear allow-clear
placeholder="请选择是否成功" placeholder="请选择是否成功"
v-model="query.success" v-model="query.success"
> >
<a-select-option value="true"></a-select-option> <a-select-option value="true"></a-select-option>
<a-select-option value="false"></a-select-option> <a-select-option value="false"></a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="操作时间"> <a-form-model-item label="操作时间">
<a-range-picker <a-range-picker
:show-time="{ :show-time="{
hideDisabledOptions: true, hideDisabledOptions: true,
defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')], defaultValue: [$moment('00:00:00', 'HH:mm:ss'), $moment('23:59:59', 'HH:mm:ss')],
}" }"
format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
v-model="query.dates" v-model="query.dates"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-button-group> <a-button-group>
<a-button @click="onQuery" type="primary">查询</a-button> <a-button @click="onQuery" type="primary">查询</a-button>
<a-button @click="() => {query = {}, onQuery()}">重置</a-button> <a-button @click="() => {query = {}, onQuery()}">重置</a-button>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</div> </div>
</Auth> </Auth>
<yo-table :columns="columns" :load-data="loadData" ref="table"> <yo-table :columns="columns" :load-data="loadData" ref="table">
<Auth auth="sysVisLog:delete" slot="operator"> <Auth auth="sysVisLog:delete" slot="operator">
<div class="yo-action-bar--actions"> <div class="yo-action-bar--actions">
<a-popconfirm @confirm="onVisLogClear" placement="bottomLeft" title="是否确认清空日志"> <a-popconfirm @confirm="onVisLogClear" placement="bottomLeft" title="是否确认清空日志">
<a-button>清空日志</a-button> <a-button>清空日志</a-button>
</a-popconfirm> </a-popconfirm>
</div> </div>
</Auth> </Auth>
<span slot="visType" slot-scope="text">{{ bindCodeValue(text, 'visTypeDict') }}</span> <span slot="visType" slot-scope="text">{{ bindCodeValue(text, 'visTypeDict') }}</span>
<span slot="success" slot-scope="text">{{ text ? '是' : '否' }}</span> <span slot="success" slot-scope="text">{{ text ? '是' : '否' }}</span>
<a-descriptions bordered size="small" slot="expandedRowRender" slot-scope="record"> <a-descriptions bordered size="small" slot="expandedRowRender" slot-scope="record">
<a-descriptions-item :span="3" label="具体消息">{{ record.message }}</a-descriptions-item> <a-descriptions-item :span="3" label="具体消息">{{ record.message }}</a-descriptions-item>
</a-descriptions> </a-descriptions>
</yo-table> </yo-table>
</a-card> </a-card>
<br /> <br />
</container> </container>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
query: {}, query: {},
columns: [ columns: [
{ {
title: '日志名称', title: '日志名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '访问类型', title: '访问类型',
dataIndex: 'visType', dataIndex: 'visType',
scopedSlots: { customRender: 'visType' }, scopedSlots: { customRender: 'visType' },
sorter: true, sorter: true,
}, },
{ {
title: '是否成功', title: '是否成功',
dataIndex: 'success', dataIndex: 'success',
scopedSlots: { customRender: 'success' }, scopedSlots: { customRender: 'success' },
sorter: true, sorter: true,
}, },
{ {
title: 'ip', title: 'ip',
dataIndex: 'ip', dataIndex: 'ip',
sorter: true, sorter: true,
}, },
{ {
title: '浏览器', title: '浏览器',
dataIndex: 'browser', dataIndex: 'browser',
sorter: true, sorter: true,
}, },
{ {
title: '访问时间', title: '访问时间',
dataIndex: 'visTime', dataIndex: 'visTime',
scopedSlots: { customRender: 'visTime' }, scopedSlots: { customRender: 'visTime' },
sorter: true, sorter: true,
}, },
{ {
title: '访问人', title: '访问人',
dataIndex: 'account', dataIndex: 'account',
sorter: true, sorter: true,
}, },
], ],
codes: { codes: {
visTypeDict: [], visTypeDict: [],
}, },
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
const query = this.$_.cloneDeep(this.query); const query = this.$_.cloneDeep(this.query);
if (query.dates && query.dates.length) { if (query.dates && query.dates.length) {
query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss'); query.searchBeginTime = this.$moment(query.dates[0]).format('YYYY-MM-DD HH:mm:ss');
query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss'); query.searchEndTime = this.$moment(query.dates[1]).format('YYYY-MM-DD HH:mm:ss');
delete query.dates; delete query.dates;
} }
return this.$api return this.$api
.sysVisLogPage({ .sysVisLogPage({
...params, ...params,
...query, ...query,
}) })
.then((res) => { .then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 加载字典数据时的必要方法 * 加载字典数据时的必要方法
*/ */
onLoadCodes() { onLoadCodes() {
this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'vis_type' })]).then(([commonStatus]) => { this.$api.$queue([this.$api.sysDictTypeDropDownAwait({ code: 'vis_type' })]).then(([commonStatus]) => {
this.codes.visTypeDict = commonStatus.data; this.codes.visTypeDict = commonStatus.data;
}); });
}, },
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
onVisLogClear() { onVisLogClear() {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api this.$api
.sysVisLogDelete() .sysVisLogDelete()
.then((res) => { .then((res) => {
if (res.success) { if (res.success) {
this.$message.success('清空成功'); this.$message.success('清空成功');
this.onReloadData(); this.onReloadData();
} else { } else {
this.$message.error('清空失败:' + res.message); this.$message.error('清空失败:' + res.message);
} }
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,340 +1,340 @@
<template> <template>
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<a-alert type="warning"> <a-alert type="warning">
<template slot="message">当前没有写入字段[重定向]</template> <template slot="message">当前没有写入字段[重定向]</template>
</a-alert> </a-alert>
<br /> <br />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<h3>基本信息</h3> <h3>基本信息</h3>
<div class="yo-form-group"> <div class="yo-form-group">
<a-form-model-item label="菜单类型" prop="type"> <a-form-model-item label="菜单类型" prop="type">
<template slot="help"> <template slot="help">
目录默认添加在顶级 目录默认添加在顶级
<br />菜单 <br />菜单
<br />按钮 <br />按钮
</template> </template>
<a-radio-group @change="onTypeChange" v-model="form.type"> <a-radio-group @change="onTypeChange" v-model="form.type">
<a-radio-button <a-radio-button
:key="type.code" :key="type.code"
:value="type.code" :value="type.code"
v-for="type in codes.menuType" v-for="type in codes.menuType"
>{{ type.value }}</a-radio-button> >{{ type.value }}</a-radio-button>
</a-radio-group> </a-radio-group>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="名称" prop="name"> <a-form-model-item label="名称" prop="name">
<a-input placeholder="请输入名称" v-model="form.name" /> <a-input placeholder="请输入名称" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码" prop="code"> <a-form-model-item label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="所属应用" prop="application"> <a-form-model-item label="所属应用" prop="application">
<a-select @change="onLoadMenuTree" placeholder="请选择所属应用" v-model="form.application"> <a-select @change="onLoadMenuTree" placeholder="请选择所属应用" v-model="form.application">
<a-select-option <a-select-option
:key="item.code" :key="item.code"
:value="item.code" :value="item.code"
v-for="item in appList" v-for="item in appList"
>{{ item.name }}</a-select-option> >{{ item.name }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<!-- 父级菜单只有[目录]不可用 --> <!-- 父级菜单只有[目录]不可用 -->
<a-form-model-item label="父级菜单" prop="pid" v-if="form.type != 0"> <a-form-model-item label="父级菜单" prop="pid" v-if="form.type != 0">
<a-tree-select <a-tree-select
:dropdown-style="{ maxHeight: '300px', overflow: 'auto' }" :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
:tree-data="parentTreeData" :tree-data="parentTreeData"
placeholder="请选择父级菜单" placeholder="请选择父级菜单"
v-model="form.pid" v-model="form.pid"
/> />
</a-form-model-item> </a-form-model-item>
</div> </div>
<h3>扩展信息</h3> <h3>扩展信息</h3>
<div class="yo-form-group"> <div class="yo-form-group">
<a-form-model-item label="打开方式" prop="openType" v-if="form.type == 1"> <a-form-model-item label="打开方式" prop="openType" v-if="form.type == 1">
<a-radio-group @change="onOpenTypeChange" v-model="form.openType"> <a-radio-group @change="onOpenTypeChange" v-model="form.openType">
<a-radio-button <a-radio-button
:key="type.code" :key="type.code"
:value="type.code" :value="type.code"
v-for="type in codes.openType" v-for="type in codes.openType"
>{{ type.value }}</a-radio-button> >{{ type.value }}</a-radio-button>
</a-radio-group> </a-radio-group>
</a-form-model-item> </a-form-model-item>
<!-- 前端组件只有[菜单][组件]可用 --> <!-- 前端组件只有[菜单][组件]可用 -->
<a-form-model-item <a-form-model-item
label="前端组件" label="前端组件"
prop="component" prop="component"
v-if="form.type == 1 && form.openType == 1" v-if="form.type == 1 && form.openType == 1"
v-show="form.type == 1 && form.openType == 1" v-show="form.type == 1 && form.openType == 1"
> >
<a-input placeholder="请输入前端组件" v-model="form.component" /> <a-input placeholder="请输入前端组件" v-model="form.component" />
</a-form-model-item> </a-form-model-item>
<!-- 内链地址只有[菜单][内链]可用 --> <!-- 内链地址只有[菜单][内链]可用 -->
<a-form-model-item label="内链地址" prop="router" v-if="form.type == 1 && form.openType == 2"> <a-form-model-item label="内链地址" prop="router" v-if="form.type == 1 && form.openType == 2">
<a-input placeholder="请输入内链地址" v-model="form.router" /> <a-input placeholder="请输入内链地址" v-model="form.router" />
</a-form-model-item> </a-form-model-item>
<!-- 外链地址只有[菜单][外链]可用 --> <!-- 外链地址只有[菜单][外链]可用 -->
<a-form-model-item label="内外链地址" prop="link" v-if="form.type == 1 && form.openType == 3"> <a-form-model-item label="内外链地址" prop="link" v-if="form.type == 1 && form.openType == 3">
<a-input placeholder="请输入内外链地址" v-model="form.link" /> <a-input placeholder="请输入内外链地址" v-model="form.link" />
</a-form-model-item> </a-form-model-item>
<!-- <a-form-model-item label="权重" prop="weight"> <!-- <a-form-model-item label="权重" prop="weight">
<template slot="help"> <template slot="help">
系统权重菜单可分配给任何角色 系统权重菜单可分配给任何角色
<br />业务权重菜单对超级管理员不可见 <br />业务权重菜单对超级管理员不可见
</template> </template>
<a-radio-group v-model="form.weight"> <a-radio-group v-model="form.weight">
<a-radio-button <a-radio-button
:key="type.code" :key="type.code"
:value="type.code" :value="type.code"
v-for="type in codes.menuWerght" v-for="type in codes.menuWerght"
>{{type.value}}</a-radio-button> >{{type.value}}</a-radio-button>
</a-radio-group> </a-radio-group>
</a-form-model-item>--> </a-form-model-item>-->
<a-form-model-item label="权限标识" prop="permission" v-if="form.type == 2"> <a-form-model-item label="权限标识" prop="permission" v-if="form.type == 2">
<a-input placeholder="请输入权限标识" v-model="form.permission" /> <a-input placeholder="请输入权限标识" v-model="form.permission" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="关联上级菜单显示" prop="visibleParent" v-if="form.type == 2"> <a-form-model-item label="关联上级菜单显示" prop="visibleParent" v-if="form.type == 2">
<a-switch v-model="form.visibleParent" /> <a-switch v-model="form.visibleParent" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="可见性"> <a-form-model-item label="可见性">
<a-switch v-model="form.visible" /> <a-switch v-model="form.visible" />
</a-form-model-item> </a-form-model-item>
<!-- 图标只有[按钮]不可用 --> <!-- 图标只有[按钮]不可用 -->
<a-form-model-item label="图标" v-if="form.type != 2"> <a-form-model-item label="图标" v-if="form.type != 2">
<a-input :disabled="true" placeholder="请选择图标" v-model="form.icon"> <a-input :disabled="true" placeholder="请选择图标" v-model="form.icon">
<a-icon :type="form.icon" slot="addonBefore" v-if="form.icon" /> <a-icon :type="form.icon" slot="addonBefore" v-if="form.icon" />
<a-icon @click="onOpenSelectIcon" slot="addonAfter" type="setting" /> <a-icon @click="onOpenSelectIcon" slot="addonAfter" type="setting" />
</a-input> </a-input>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="排序"> <a-form-model-item label="排序">
<a-input-number <a-input-number
:max="1000" :max="1000"
:min="0" :min="0"
class="w-100-p" class="w-100-p"
placeholder="请输入排序" placeholder="请输入排序"
v-model="form.sort" v-model="form.sort"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="备注信息"> <a-form-model-item label="备注信息">
<a-textarea placeholder="请输入备注信息" v-model="form.remark" /> <a-textarea placeholder="请输入备注信息" v-model="form.remark" />
</a-form-model-item> </a-form-model-item>
</div> </div>
</div> </div>
</a-spin> </a-spin>
<yo-icon-selector ref="icon-selector" v-model="form.icon" /> <yo-icon-selector ref="icon-selector" v-model="form.icon" />
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import { EMPTY_ID } from '@/util/global'; import { EMPTY_ID } from '@/util/global';
import YoIconSelector from '@/components/yoIconSelector'; import YoIconSelector from '@/components/yoIconSelector';
const defaultValue = { const defaultValue = {
type: '1', type: '1',
openType: '1', openType: '1',
weight: '1', weight: '1',
visibleParent: false, visibleParent: false,
visible: true, visible: true,
sort: 100, sort: 100,
}; };
export default { export default {
components: { components: {
YoIconSelector, YoIconSelector,
}, },
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
type: [{ required: true, message: '请选择菜单类型' }], type: [{ required: true, message: '请选择菜单类型' }],
name: [{ required: true, message: '请输入名称' }], name: [{ required: true, message: '请输入名称' }],
code: [{ required: true, message: '请输入唯一编码' }], code: [{ required: true, message: '请输入唯一编码' }],
application: [{ required: true, message: '请选择所属应用' }], application: [{ required: true, message: '请选择所属应用' }],
pid: [{ required: true, message: '请选择父级' }], pid: [{ required: true, message: '请选择父级' }],
component: [{ required: true, message: '请输入前端组件' }], component: [{ required: true, message: '请输入前端组件' }],
router: [{ required: true, message: '请输入内链地址' }], router: [{ required: true, message: '请输入内链地址' }],
link: [{ required: true, message: '请输入外链地址' }], link: [{ required: true, message: '请输入外链地址' }],
permission: [{ required: true, message: '请输入权限标识' }], permission: [{ required: true, message: '请输入权限标识' }],
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/** ... */ /** ... */
appList: [], appList: [],
codes: { codes: {
menuType: [], menuType: [],
menuWerght: [], menuWerght: [],
openType: [], openType: [],
}, },
parentTreeData: [], parentTreeData: [],
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
let form = { let form = {
...defaultValue, ...defaultValue,
...params.record, ...params.record,
/** 在此处添加默认数据转换 */ /** 在此处添加默认数据转换 */
/** ... */ /** ... */
}; };
if (params.isParent) { if (params.isParent) {
form.pid = params.parent.id; form.pid = params.parent.id;
form.application = params.parent.application; form.application = params.parent.application;
} }
this.form = this.$_.cloneDeep(form); this.form = this.$_.cloneDeep(form);
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/** ... */ /** ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
this.form = { this.form = {
...defaultValue, ...defaultValue,
}; };
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/** ... */ /** ... */
this.parentTreeData = []; this.parentTreeData = [];
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/** ...BEGIN */ /** ...BEGIN */
this.codes = await this.onLoadCodes(); this.codes = await this.onLoadCodes();
this.appList = await this.onLoadSysApplist(); this.appList = await this.onLoadSysApplist();
if (params.isParent) { if (params.isParent) {
await this.onLoadMenuTree(params.parent.application); await this.onLoadMenuTree(params.parent.application);
} else if (params.record) { } else if (params.record) {
await this.onLoadMenuTree(params.record.application); await this.onLoadMenuTree(params.record.application);
} }
/** ...END */ /** ...END */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/** ... */ /** ... */
onLoadCodes() { onLoadCodes() {
return this.$api return this.$api
.$queue([ .$queue([
this.$api.sysDictTypeDropDownAwait({ code: 'menu_type' }), this.$api.sysDictTypeDropDownAwait({ code: 'menu_type' }),
this.$api.sysDictTypeDropDownAwait({ code: 'menu_weight' }), this.$api.sysDictTypeDropDownAwait({ code: 'menu_weight' }),
this.$api.sysDictTypeDropDownAwait({ code: 'open_type' }), this.$api.sysDictTypeDropDownAwait({ code: 'open_type' }),
]) ])
.then(([menuType, menuWerght, openType]) => { .then(([menuType, menuWerght, openType]) => {
return { return {
menuType: menuType.data, menuType: menuType.data,
menuWerght: menuWerght.data, menuWerght: menuWerght.data,
openType: openType.data, openType: openType.data,
}; };
}); });
}, },
onLoadSysApplist() { onLoadSysApplist() {
return this.$api.getAppList().then(({ data }) => { return this.$api.getAppList().then(({ data }) => {
return data; return data;
}); });
}, },
onLoadMenuTree(app) { onLoadMenuTree(app) {
return this.$api.getMenuTree({ application: app }).then(({ data }) => { return this.$api.getMenuTree({ application: app }).then(({ data }) => {
this.parentTreeData = [ this.parentTreeData = [
{ {
id: EMPTY_ID, id: EMPTY_ID,
parentId: undefined, parentId: undefined,
title: '顶级', title: '顶级',
value: EMPTY_ID, value: EMPTY_ID,
pid: undefined, pid: undefined,
children: data, children: data,
}, },
]; ];
}); });
}, },
onTypeChangeGroup() { onTypeChangeGroup() {
const { type, openType } = this.form; const { type, openType } = this.form;
if (type == 1 && openType == 2) { if (type == 1 && openType == 2) {
this.$set(this.form, 'component', 'iframe'); this.$set(this.form, 'component', 'iframe');
} else { } else {
this.$set(this.form, 'component', ''); this.$set(this.form, 'component', '');
} }
}, },
onTypeChange() { onTypeChange() {
this.onTypeChangeGroup(); this.onTypeChangeGroup();
if (this.form.type == 0 || this.form.type == 2) { if (this.form.type == 0 || this.form.type == 2) {
this.form.openType = '0'; this.form.openType = '0';
} else { } else {
this.form.openType = '1'; this.form.openType = '1';
} }
}, },
onOpenTypeChange() { onOpenTypeChange() {
this.onTypeChangeGroup(); this.onTypeChangeGroup();
}, },
onOpenSelectIcon() { onOpenSelectIcon() {
this.$refs['icon-selector'].onOpen(this.form.icon); this.$refs['icon-selector'].onOpen(this.form.icon);
}, },
onSelectIcon(icon) { onSelectIcon(icon) {
this.$set(this.form, 'icon', icon); this.$set(this.form, 'icon', icon);
}, },
}, },
}; };
</script> </script>

View File

@@ -1,227 +1,227 @@
<template> <template>
<container> <container>
<br /> <br />
<a-alert type="error"> <a-alert type="error">
<template slot="message">按钮编辑关闭时调用resetFields报错,原因为visible=undefined</template> <template slot="message">按钮编辑关闭时调用resetFields报错,原因为visible=undefined</template>
</a-alert> </a-alert>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table :columns="columns" :load-data="loadData" ref="table"> <yo-table :columns="columns" :load-data="loadData" ref="table">
<Auth auth="sysMenu:add" slot="operator"> <Auth auth="sysMenu:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增菜单</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增菜单</a-button>
</Auth> </Auth>
<span slot="type" slot-scope="text">{{ bindCodeValue(text, 'menu_type') }}</span> <span slot="type" slot-scope="text">{{ bindCodeValue(text, 'menu_type') }}</span>
<span slot="icon" slot-scope="text"> <span slot="icon" slot-scope="text">
<div v-if="text"> <div v-if="text">
<a-icon :type="text" /> <a-icon :type="text" />
</div> </div>
</span> </span>
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysMenu:add" v-if="record.type < 2"> <Auth auth="sysMenu:add" v-if="record.type < 2">
<a @click="onOpen('add-form', record, true)">新增子菜单</a> <a @click="onOpen('add-form', record, true)">新增子菜单</a>
</Auth> </Auth>
<Auth auth="sysMenu:edit"> <Auth auth="sysMenu:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysMenu:delete"> <Auth auth="sysMenu:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<yo-modal-form <yo-modal-form
:action="$api.sysMenuAdd" :action="$api.sysMenuAdd"
:width="800" :width="800"
@ok="onReloadData" @ok="onReloadData"
ref="add-form" ref="add-form"
title="新增菜单" title="新增菜单"
type="drawer" type="drawer"
> >
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<yo-modal-form <yo-modal-form
:action="$api.sysMenuEdit" :action="$api.sysMenuEdit"
:width="800" :width="800"
@ok="onReloadData" @ok="onReloadData"
ref="edit-form" ref="edit-form"
title="编辑菜单" title="编辑菜单"
type="drawer" type="drawer"
> >
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
data() { data() {
return { return {
query: {}, query: {},
columns: [ columns: [
{ {
title: '菜单名称', title: '菜单名称',
width: '220px', width: '220px',
dataIndex: 'name', dataIndex: 'name',
}, },
{ {
title: '菜单类型', title: '菜单类型',
width: '100px', width: '100px',
dataIndex: 'type', dataIndex: 'type',
scopedSlots: { customRender: 'type' }, scopedSlots: { customRender: 'type' },
}, },
{ {
title: '图标', title: '图标',
width: '100px', width: '100px',
dataIndex: 'icon', dataIndex: 'icon',
scopedSlots: { customRender: 'icon' }, scopedSlots: { customRender: 'icon' },
}, },
{ {
title: '前端组件', title: '前端组件',
width: '220px', width: '220px',
dataIndex: 'component', dataIndex: 'component',
ellipsis: true, ellipsis: true,
}, },
{ {
title: '权限标识', title: '权限标识',
width: '220px', width: '220px',
dataIndex: 'permission', dataIndex: 'permission',
ellipsis: true, ellipsis: true,
}, },
{ {
title: '排序', title: '排序',
width: '100px', width: '100px',
dataIndex: 'sort', dataIndex: 'sort',
}, },
], ],
codes: [ codes: [
{ {
code: 'menu_type', code: 'menu_type',
values: [], values: [],
}, },
{ {
code: 'menu_weight', code: 'menu_weight',
values: [], values: [],
}, },
{ {
code: 'open_type', code: 'open_type',
values: [], values: [],
}, },
], ],
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
const flag = this.$auth({ const flag = this.$auth({
sysApp: [['edit'], ['delete']], sysApp: [['edit'], ['delete']],
}); });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api return this.$api
.getMenuList({ .getMenuList({
...params, ...params,
...this.query, ...this.query,
}) })
.then((res) => { .then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 加载字典数据时的必要方法 * 加载字典数据时的必要方法
*/ */
onLoadCodes() { onLoadCodes() {
this.$api this.$api
.$queue([ .$queue([
this.$api.sysDictTypeDropDownAwait({ code: 'menu_type' }), this.$api.sysDictTypeDropDownAwait({ code: 'menu_type' }),
this.$api.sysDictTypeDropDownAwait({ code: 'menu_weight' }), this.$api.sysDictTypeDropDownAwait({ code: 'menu_weight' }),
this.$api.sysDictTypeDropDownAwait({ code: 'open_type' }), this.$api.sysDictTypeDropDownAwait({ code: 'open_type' }),
]) ])
.then(([menuType, menuWerght, openType]) => { .then(([menuType, menuWerght, openType]) => {
this.codes.find((p) => p.code === 'menu_type').values = menuType.data; this.codes.find((p) => p.code === 'menu_type').values = menuType.data;
this.codes.find((p) => p.code === 'menu_weight').values = menuWerght.data; this.codes.find((p) => p.code === 'menu_weight').values = menuWerght.data;
this.codes.find((p) => p.code === 'open_type').values = openType.data; this.codes.find((p) => p.code === 'open_type').values = openType.data;
}); });
}, },
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes.find((p) => p.code == name).values.find((p) => p.code == code); const c = this.codes.find((p) => p.code == name).values.find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 有编辑新增功能的必要方法 * 有编辑新增功能的必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record, isParent = false) { onOpen(formName, record, isParent = false) {
const params = isParent const params = isParent
? { ? {
parent: record, parent: record,
isParent, isParent,
} }
: { : {
record, record,
isParent, isParent,
}; };
this.$refs[formName].onOpen(params); this.$refs[formName].onOpen(params);
}, },
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}, },
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api.sysMenuDelete(record).then(({ success }) => { this.$api.sysMenuDelete(record).then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,219 +1,219 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="机构名称" prop="name"> <a-form-model-item label="机构名称" prop="name">
<a-input placeholder="请输入机构名称" v-model="form.name" /> <a-input placeholder="请输入机构名称" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码" prop="code"> <a-form-model-item label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="上级机构" prop="pid"> <a-form-model-item label="上级机构" prop="pid">
<a-tree-select <a-tree-select
:dropdown-style="{ maxHeight: '300px', overflow: 'auto' }" :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
:tree-data="orgData" :tree-data="orgData"
placeholder="请选择上级机构" placeholder="请选择上级机构"
tree-default-expand-all tree-default-expand-all
v-model="form.pid" v-model="form.pid"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="所属区域" prop="areaCode"> <a-form-model-item label="所属区域" prop="areaCode">
<a-cascader <a-cascader
:field-names="{ label: 'name', value: 'code', children: 'children' }" :field-names="{ label: 'name', value: 'code', children: 'children' }"
:options="areaData" :options="areaData"
change-on-select change-on-select
placeholder="请选择所属区域" placeholder="请选择所属区域"
v-model="form.areaCode" v-model="form.areaCode"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="排序" prop="sort"> <a-form-model-item label="排序" prop="sort">
<a-input-number <a-input-number
:max="1000" :max="1000"
:min="0" :min="0"
class="w-100-p" class="w-100-p"
placeholder="请输入排序" placeholder="请输入排序"
v-model="form.sort" v-model="form.sort"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="备注" prop="remark"> <a-form-model-item label="备注" prop="remark">
<a-textarea placeholder="请输入备注" v-model="form.remark" /> <a-textarea placeholder="请输入备注" v-model="form.remark" />
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import { EMPTY_ID } from '@/util/global'; import { EMPTY_ID } from '@/util/global';
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
pid: undefined, pid: undefined,
sort: 100, sort: 100,
}; };
export default { export default {
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
name: [{ required: true, message: '请输入机构名称' }], name: [{ required: true, message: '请输入机构名称' }],
code: [{ required: true, message: '请输入唯一编码' }], code: [{ required: true, message: '请输入唯一编码' }],
pid: [{ required: true, message: '请选择上级机构' }], pid: [{ required: true, message: '请选择上级机构' }],
areaCode: [{ required: true, message: '请选择所属区域' }], areaCode: [{ required: true, message: '请选择所属区域' }],
/* ... */ /* ... */
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
orgData: [], orgData: [],
areaData: [], areaData: [],
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
// 从字符串areaCode查找到整个层级 // 从字符串areaCode查找到整个层级
const areaCode = []; const areaCode = [];
const findCode = (data, level) => { const findCode = (data, level) => {
level = level || 0; level = level || 0;
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
const item = data[i]; const item = data[i];
areaCode[level] = item.code; areaCode[level] = item.code;
if (item.code === params.record.areaCode) { if (item.code === params.record.areaCode) {
areaCode.length = level + 1; areaCode.length = level + 1;
return true; return true;
} }
if (item.children && item.children.length) { if (item.children && item.children.length) {
const found = findCode(item.children, level + 1); const found = findCode(item.children, level + 1);
if (found) { if (found) {
return true; return true;
} }
} }
} }
}; };
if (params.record && params.record.areaCode) { if (params.record && params.record.areaCode) {
findCode(this.areaData); findCode(this.areaData);
} }
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
pid: params.orgId, pid: params.orgId,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
areaCode, areaCode,
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
record.areaCode = record.areaCode[record.areaCode.length - 1]; record.areaCode = record.areaCode[record.areaCode.length - 1];
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
await this.onLoadOrgData(); await this.onLoadOrgData();
await this.onLoadAreaData(); await this.onLoadAreaData();
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
onLoadOrgData() { onLoadOrgData() {
return this.$api.getOrgTree().then(({ data }) => { return this.$api.getOrgTree().then(({ data }) => {
this.orgData = [ this.orgData = [
{ {
id: EMPTY_ID, id: EMPTY_ID,
parentId: undefined, parentId: undefined,
title: '顶级', title: '顶级',
value: EMPTY_ID, value: EMPTY_ID,
pid: undefined, pid: undefined,
children: data, children: data,
}, },
]; ];
}); });
}, },
onLoadAreaData() { onLoadAreaData() {
return this.$api.getAreaTree().then(({ data }) => { return this.$api.getAreaTree().then(({ data }) => {
// 为了防止出现空的层级选择,删除所有空children节点 // 为了防止出现空的层级选择,删除所有空children节点
const clearChiildren = (data) => { const clearChiildren = (data) => {
data.forEach((item) => { data.forEach((item) => {
if (item.children && item.children.length) { if (item.children && item.children.length) {
clearChiildren(item.children); clearChiildren(item.children);
} else { } else {
delete item.children; delete item.children;
} }
}); });
}; };
clearChiildren(data); clearChiildren(data);
this.areaData = data; this.areaData = data;
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,278 +1,278 @@
<template> <template>
<!-- <!--
普通查询表格 普通查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<yo-tree-layout <yo-tree-layout
:load-data="loadTreeData" :load-data="loadTreeData"
@select="onSelect" @select="onSelect"
default-expanded-keys default-expanded-keys
ref="tree-layout" ref="tree-layout"
> >
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysOrg:page" slot="query"> <Auth auth="sysOrg:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="机构名称"> <a-form-model-item label="机构名称">
<a-input allow-clear placeholder="请输入机构名称" v-model="query.name" /> <a-input allow-clear placeholder="请输入机构名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysOrg:add" slot="operator"> <Auth auth="sysOrg:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增机构</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增机构</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<!-- ... --> <!-- ... -->
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysOrg:edit"> <Auth auth="sysOrg:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysOrg:delete"> <Auth auth="sysOrg:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
<!-- ... --> <!-- ... -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form"> <yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form <yo-modal-form
:action="$api[api.edit]" :action="$api[api.edit]"
:title="'编辑' + name" :title="'编辑' + name"
@ok="onReloadData" @ok="onReloadData"
ref="edit-form" ref="edit-form"
> >
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</yo-tree-layout> </yo-tree-layout>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
import YoTreeLayout from '@/components/yoTreeLayout'; import YoTreeLayout from '@/components/yoTreeLayout';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
page: 'getOrgPage', page: 'getOrgPage',
add: 'sysOrgAdd', add: 'sysOrgAdd',
edit: 'sysOrgEdit', edit: 'sysOrgEdit',
delete: 'sysOrgDelete', delete: 'sysOrgDelete',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
FormBody, FormBody,
YoTreeLayout, YoTreeLayout,
}, },
data() { data() {
return { return {
api, api,
name: '机构', name: '机构',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [ columns: [
{ {
title: '机构名称', title: '机构名称',
width: '400px', width: '400px',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '唯一编码', title: '唯一编码',
width: '200px', width: '200px',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '排序', title: '排序',
width: '80px', width: '80px',
dataIndex: 'sort', dataIndex: 'sort',
sorter: true, sorter: true,
}, },
{ {
title: '备注', title: '备注',
dataIndex: 'remark', dataIndex: 'remark',
sorter: true, sorter: true,
}, },
], ],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
// codes: { // codes: {
// code1: [], // code1: [],
// code2: [], // code2: [],
// }, // },
}; };
}, },
created() { created() {
/** 按需加载字典编码 */ /** 按需加载字典编码 */
//this.onLoadCodes(); //this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth(/* ... */); const flag = this.$auth(/* ... */);
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
Object.keys(this.query).forEach((p) => { Object.keys(this.query).forEach((p) => {
if (p !== 'pid') { if (p !== 'pid') {
this.query[p] = undefined; this.query[p] = undefined;
} }
}); });
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
//onLoadCodes() { //onLoadCodes() {
// this.$api // this.$api
// .$queue([ // .$queue([
// this.$api.sysDictTypeDropDownAwait({ code: 'code1' }), // this.$api.sysDictTypeDropDownAwait({ code: 'code1' }),
// this.$api.sysDictTypeDropDownAwait({ code: 'code2' }), // this.$api.sysDictTypeDropDownAwait({ code: 'code2' }),
// /* ... */ // /* ... */
// ]) // ])
// .then(([code1, code2]) => { // .then(([code1, code2]) => {
// this.codes.code1 = code1.data; // this.codes.code1 = code1.data;
// this.codes.code2 = code2.data; // this.codes.code2 = code2.data;
// /* ... */ // /* ... */
// }); // });
// }, // },
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
orgId: this.query['pid'], orgId: this.query['pid'],
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
/** /**
* 树形选择界面必要的方法 * 树形选择界面必要的方法
* 传给yo-table-layout以示意数据接口 * 传给yo-table-layout以示意数据接口
*/ */
loadTreeData() { loadTreeData() {
return this.$api.getOrgTree().then((res) => { return this.$api.getOrgTree().then((res) => {
return res.data; return res.data;
}); });
}, },
onSelect([id]) { onSelect([id]) {
this.query = { this.query = {
pid: id, pid: id,
}; };
this.onQuery(); this.onQuery();
}, },
}, },
}; };
</script> </script>

View File

@@ -1,135 +1,135 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="职位名称" prop="name"> <a-form-model-item label="职位名称" prop="name">
<a-input placeholder="请输入职位名称" v-model="form.name" /> <a-input placeholder="请输入职位名称" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码" prop="code"> <a-form-model-item label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="排序" prop="sort"> <a-form-model-item label="排序" prop="sort">
<a-input-number <a-input-number
:max="1000" :max="1000"
:min="0" :min="0"
class="w-100-p" class="w-100-p"
placeholder="请输入排序" placeholder="请输入排序"
v-model="form.sort" v-model="form.sort"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="备注" prop="remark"> <a-form-model-item label="备注" prop="remark">
<a-textarea :rows="4" placeholder="请输入备注" v-model="form.remark"></a-textarea> <a-textarea :rows="4" placeholder="请输入备注" v-model="form.remark"></a-textarea>
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
sort: 100, sort: 100,
}; };
export default { export default {
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
/* ... */ /* ... */
name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }], name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
code: [{ required: true, message: '请输入唯一编码', trigger: 'blur' }], code: [{ required: true, message: '请输入唯一编码', trigger: 'blur' }],
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
}, },
}; };
</script> </script>

View File

@@ -1,233 +1,233 @@
<template> <template>
<!-- <!--
普通查询表格 普通查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<container> <container>
<br /> <br />
<a-card :bordered="false"> <a-card :bordered="false">
<yo-table <yo-table
:columns="columns" :columns="columns"
:load-data="loadData" :load-data="loadData"
@query="onQuery" @query="onQuery"
@resetQuery="onResetQuery" @resetQuery="onResetQuery"
ref="table" ref="table"
> >
<Auth auth="sysPos:page" slot="query"> <Auth auth="sysPos:page" slot="query">
<!-- 此处添加查询表单控件 --> <!-- 此处添加查询表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="职位名称"> <a-form-model-item label="职位名称">
<a-input placeholder="请输入职位名称" v-model="query.name" /> <a-input placeholder="请输入职位名称" v-model="query.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码"> <a-form-model-item label="唯一编码">
<a-input placeholder="请输入唯一编码" v-model="query.code" /> <a-input placeholder="请输入唯一编码" v-model="query.code" />
</a-form-model-item> </a-form-model-item>
</Auth> </Auth>
<Auth auth="sysPos:add" slot="operator"> <Auth auth="sysPos:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增职位</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增职位</a-button>
</Auth> </Auth>
<!-- 格式化字段内容 --> <!-- 格式化字段内容 -->
<!-- ... --> <!-- ... -->
<!-- 添加操作控件 --> <!-- 添加操作控件 -->
<span slot="action" slot-scope="text, record"> <span slot="action" slot-scope="text, record">
<yo-table-actions> <yo-table-actions>
<Auth auth="sysPos:edit"> <Auth auth="sysPos:edit">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysPos:delete"> <Auth auth="sysPos:delete">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<!-- 可在此处添加其他操作控件 --> <!-- 可在此处添加其他操作控件 -->
<!-- ... --> <!-- ... -->
</yo-table-actions> </yo-table-actions>
</span> </span>
</yo-table> </yo-table>
</a-card> </a-card>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form"> <yo-modal-form :action="$api[api.add]" :title="'新增' + name" @ok="onReloadData" ref="add-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form"> <yo-modal-form :action="$api[api.edit]" :title="'编辑' + name" @ok="onReloadData" ref="edit-form">
<form-body /> <form-body />
</yo-modal-form> </yo-modal-form>
</container> </container>
</template> </template>
<script> <script>
import FormBody from './form'; import FormBody from './form';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
page: 'sysPosPage', page: 'sysPosPage',
add: 'sysPosAdd', add: 'sysPosAdd',
edit: 'sysPosEdit', edit: 'sysPosEdit',
delete: 'sysPosDelete', delete: 'sysPosDelete',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
FormBody, FormBody,
}, },
data() { data() {
return { return {
api, api,
name: '职位', name: '职位',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [ columns: [
{ {
title: '职位名称', title: '职位名称',
dataIndex: 'name', dataIndex: 'name',
sorter: true, sorter: true,
}, },
{ {
title: '唯一编码', title: '唯一编码',
dataIndex: 'code', dataIndex: 'code',
sorter: true, sorter: true,
}, },
{ {
title: '排序', title: '排序',
dataIndex: 'sort', dataIndex: 'sort',
sorter: true, sorter: true,
}, },
{ {
title: '备注', title: '备注',
dataIndex: 'remark', dataIndex: 'remark',
sorter: true, sorter: true,
}, },
], ],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
codes: { codes: {
code1: [], code1: [],
code2: [], code2: [],
}, },
}; };
}, },
created() { created() {
/** 按需加载字典编码 */ /** 按需加载字典编码 */
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ const flag = this.$auth({
sysPos: [['edit'], ['delete']], sysPos: [['edit'], ['delete']],
}); });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.table.onReloadData(true); this.$refs.table.onReloadData(true);
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 重置查询条件 * 重置查询条件
*/ */
onResetQuery() { onResetQuery() {
/** 在这里重置查询条件时,可对特殊的字段做保留处理 */ /** 在这里重置查询条件时,可对特殊的字段做保留处理 */
this.query = {}; this.query = {};
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.table.onReloadData(); this.$refs.table.onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() {}, onLoadCodes() {},
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 必要方法 * 必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.table.onLoading(); this.$refs.table.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.table.onLoaded(); this.$refs.table.onLoaded();
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,134 +1,134 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<div class="yo-form-group"> <div class="yo-form-group">
<!-- 表单控件 --> <!-- 表单控件 -->
<!-- ... --> <!-- ... -->
<a-form-model-item label="角色名" prop="name"> <a-form-model-item label="角色名" prop="name">
<a-input placeholder="请输入角色名" v-model="form.name" /> <a-input placeholder="请输入角色名" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="唯一编码" prop="code"> <a-form-model-item label="唯一编码" prop="code">
<a-input placeholder="请输入唯一编码" v-model="form.code" /> <a-input placeholder="请输入唯一编码" v-model="form.code" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="排序" prop="sort"> <a-form-model-item label="排序" prop="sort">
<a-input-number <a-input-number
:max="1000" :max="1000"
:min="0" :min="0"
class="w-100-p" class="w-100-p"
placeholder="请输入排序" placeholder="请输入排序"
v-model="form.sort" v-model="form.sort"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="备注" prop="remark"> <a-form-model-item label="备注" prop="remark">
<a-textarea :rows="4" placeholder="请输入备注" v-model="form.remark"></a-textarea> <a-textarea :rows="4" placeholder="请输入备注" v-model="form.remark"></a-textarea>
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
}; };
export default { export default {
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
/* ... */ /* ... */
name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }], name: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
code: [{ required: true, message: '请输入唯一编码', trigger: 'blur' }], code: [{ required: true, message: '请输入唯一编码', trigger: 'blur' }],
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...params.record, ...params.record,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/* ... */ /* ... */
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
}, },
}; };
</script> </script>

View File

@@ -1,101 +1,101 @@
<template> <template>
<a-modal <a-modal
:confirmLoading="confirmLoading" :confirmLoading="confirmLoading"
:visible="visible" :visible="visible"
:width="1200" :width="1200"
@cancel="onCancel" @cancel="onCancel"
@ok="onOk" @ok="onOk"
title="授权菜单" title="授权菜单"
> >
<yo-authority-view <yo-authority-view
:auto-load="false" :auto-load="false"
:default-selected-keys="selectedKeys" :default-selected-keys="selectedKeys"
:load-data="loadData" :load-data="loadData"
@select="onSelect" @select="onSelect"
ref="authority-view" ref="authority-view"
/> />
</a-modal> </a-modal>
</template> </template>
<script> <script>
import YoAuthorityView from '@/components/yoAuthorityView'; import YoAuthorityView from '@/components/yoAuthorityView';
export default { export default {
components: { components: {
YoAuthorityView, YoAuthorityView,
}, },
data() { data() {
return { return {
visible: false, visible: false,
record: {}, record: {},
selectedKeys: [], selectedKeys: [],
confirmLoading: false, confirmLoading: false,
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 从外部调用打开本窗口 * 从外部调用打开本窗口
*/ */
onOpen(params) { onOpen(params) {
this.visible = true; this.visible = true;
this.record = params.record; this.record = params.record;
this.$nextTick(async () => { this.$nextTick(async () => {
const view = this.$refs['authority-view']; const view = this.$refs['authority-view'];
view.loading = true; view.loading = true;
view.data = []; view.data = [];
this.selectedKeys = await this.onLoadRoleOwnMenu(); this.selectedKeys = await this.onLoadRoleOwnMenu();
view.onReloadData(); view.onReloadData();
}); });
}, },
loadData() { loadData() {
return this.$api.SysMenuTreeForGrant().then((res) => { return this.$api.SysMenuTreeForGrant().then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 此角色已有菜单权限 * 此角色已有菜单权限
*/ */
onLoadRoleOwnMenu() { onLoadRoleOwnMenu() {
return this.$api.sysRoleOwnMenu({ id: this.record.id }).then(({ data }) => { return this.$api.sysRoleOwnMenu({ id: this.record.id }).then(({ data }) => {
return data; return data;
}); });
}, },
onSelect(a1, a2, a3) { onSelect(a1, a2, a3) {
this.selectedKeys = a3; this.selectedKeys = a3;
}, },
onOk() { onOk() {
this.confirmLoading = true; this.confirmLoading = true;
this.$api this.$api
.sysRoleGrantMenu({ .sysRoleGrantMenu({
id: this.record.id, id: this.record.id,
grantMenuIdList: this.selectedKeys, grantMenuIdList: this.selectedKeys,
}) })
.then(({ success }) => { .then(({ success }) => {
if (success) { if (success) {
this.$message.success('授权成功'); this.$message.success('授权成功');
this.$emit('ok'); this.$emit('ok');
this.onCancel(); this.onCancel();
} }
}) })
.finally((res) => { .finally((res) => {
this.confirmLoading = false; this.confirmLoading = false;
}); });
}, },
onCancel() { onCancel() {
this.visible = false; this.visible = false;
}, },
}, },
}; };
</script> </script>

View File

@@ -1,363 +1,363 @@
<template> <template>
<!-- <!--
普通编辑窗体 普通编辑窗体
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<a-form-model :model="form" :rules="rules" class="yo-form" ref="form"> <a-form-model :model="form" :rules="rules" class="yo-form" ref="form">
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-icon slot="indicator" spin type="loading" /> <a-icon slot="indicator" spin type="loading" />
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="10"> <a-col :span="10">
<h3 class="h3">基本信息</h3> <h3 class="h3">基本信息</h3>
<div class="yo-form-group"> <div class="yo-form-group">
<a-form-model-item label="账号" prop="account"> <a-form-model-item label="账号" prop="account">
<a-input placeholder="请输入账号" v-model="form.account" /> <a-input placeholder="请输入账号" v-model="form.account" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="姓名" prop="name"> <a-form-model-item label="姓名" prop="name">
<a-input placeholder="请输入姓名" v-model="form.name" /> <a-input placeholder="请输入姓名" v-model="form.name" />
</a-form-model-item> </a-form-model-item>
<template v-if="mode == 'add'"> <template v-if="mode == 'add'">
<a-form-model-item label="密码" prop="password"> <a-form-model-item label="密码" prop="password">
<a-input-password placeholder="请输入密码" v-model="form.password" /> <a-input-password placeholder="请输入密码" v-model="form.password" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="确认密码" prop="confirm"> <a-form-model-item label="确认密码" prop="confirm">
<a-input-password placeholder="请确认密码" v-model="form.confirm" /> <a-input-password placeholder="请确认密码" v-model="form.confirm" />
</a-form-model-item> </a-form-model-item>
</template> </template>
<a-form-model-item label="昵称"> <a-form-model-item label="昵称">
<a-input placeholder="请输入昵称" v-model="form.nickName" /> <a-input placeholder="请输入昵称" v-model="form.nickName" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="生日"> <a-form-model-item label="生日">
<a-date-picker <a-date-picker
@change="(date) => form.birthday = date ? $moment(date).format('YYYY-MM-DD') : null" @change="(date) => form.birthday = date ? $moment(date).format('YYYY-MM-DD') : null"
class="w-100-p" class="w-100-p"
placeholder="请选择生日" placeholder="请选择生日"
v-model="form.birthday" v-model="form.birthday"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="性别" prop="sex"> <a-form-model-item label="性别" prop="sex">
<a-radio-group v-model="form.sex"> <a-radio-group v-model="form.sex">
<a-radio-button :value="0"> <a-radio-button :value="0">
<a-icon class="mr-xxs" type="stop" /> <a-icon class="mr-xxs" type="stop" />
<span>保密</span> <span>保密</span>
</a-radio-button> </a-radio-button>
<a-radio-button :value="1"> <a-radio-button :value="1">
<a-icon :style="{ color: '#1890ff' }" class="mr-xxs" type="man" /> <a-icon :style="{ color: '#1890ff' }" class="mr-xxs" type="man" />
<span></span> <span></span>
</a-radio-button> </a-radio-button>
<a-radio-button :value="2"> <a-radio-button :value="2">
<a-icon :style="{ color: '#eb2f96' }" class="mr-xxs" type="woman" /> <a-icon :style="{ color: '#eb2f96' }" class="mr-xxs" type="woman" />
<span></span> <span></span>
</a-radio-button> </a-radio-button>
</a-radio-group> </a-radio-group>
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="邮箱" prop="email"> <a-form-model-item label="邮箱" prop="email">
<a-input placeholder="请输入邮箱" v-model="form.email" /> <a-input placeholder="请输入邮箱" v-model="form.email" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="手机号" prop="phone"> <a-form-model-item label="手机号" prop="phone">
<a-input placeholder="请输入手机号" v-model="form.phone" /> <a-input placeholder="请输入手机号" v-model="form.phone" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="电话" prop="tel"> <a-form-model-item label="电话" prop="tel">
<a-input placeholder="请输入电话" v-model="form.tel" /> <a-input placeholder="请输入电话" v-model="form.tel" />
</a-form-model-item> </a-form-model-item>
</div> </div>
</a-col> </a-col>
<a-col :span="14" v-if="form.sysEmpParam"> <a-col :span="14" v-if="form.sysEmpParam">
<h3 class="h3">员工信息</h3> <h3 class="h3">员工信息</h3>
<div class="yo-form-group"> <div class="yo-form-group">
<a-form-model-item label="所属组织机构" prop="sysEmpParam.orgId"> <a-form-model-item label="所属组织机构" prop="sysEmpParam.orgId">
<a-tree-select <a-tree-select
:dropdown-style="{ maxHeight: '300px', overflow: 'auto' }" :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
:tree-data="orgData" :tree-data="orgData"
placeholder="请选择所属组织机构" placeholder="请选择所属组织机构"
tree-default-expand-all tree-default-expand-all
v-model="form.sysEmpParam.orgId" v-model="form.sysEmpParam.orgId"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="工号"> <a-form-model-item label="工号">
<a-input placeholder="请输入工号" v-model="form.sysEmpParam.jobNum" /> <a-input placeholder="请输入工号" v-model="form.sysEmpParam.jobNum" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="职位信息" prop="sysEmpParam.posIdList"> <a-form-model-item label="职位信息" prop="sysEmpParam.posIdList">
<a-select mode="multiple" placeholder="请选择职位信息" v-model="form.sysEmpParam.posIdList"> <a-select mode="multiple" placeholder="请选择职位信息" v-model="form.sysEmpParam.posIdList">
<a-select-option <a-select-option
:key="i" :key="i"
:value="item.id" :value="item.id"
v-for="(item, i) in posData" v-for="(item, i) in posData"
>{{ item.name }}</a-select-option> >{{ item.name }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
</div> </div>
<h4 class="h4">附加信息</h4> <h4 class="h4">附加信息</h4>
<div class="pl-md pr-md"> <div class="pl-md pr-md">
<a-table <a-table
:columns="extColumns" :columns="extColumns"
:data-source="form.sysEmpParam.extIds" :data-source="form.sysEmpParam.extIds"
:pagination="false" :pagination="false"
size="small" size="small"
> >
<template slot="footer"> <template slot="footer">
<a-button @click="onAddExtData" block icon="plus" type="dashed">新增一项</a-button> <a-button @click="onAddExtData" block icon="plus" type="dashed">新增一项</a-button>
</template> </template>
<template slot="orgId" slot-scope="text, record"> <template slot="orgId" slot-scope="text, record">
<a-tree-select <a-tree-select
:default-value="text" :default-value="text"
:dropdown-style="{ maxHeight: '300px', overflow: 'auto' }" :dropdown-style="{ maxHeight: '300px', overflow: 'auto' }"
:tree-data="orgData" :tree-data="orgData"
@change="value => onChangeExtData(value, record, 'orgId')" @change="value => onChangeExtData(value, record, 'orgId')"
placeholder="请选择附加组织机构" placeholder="请选择附加组织机构"
tree-default-expand-all tree-default-expand-all
/> />
</template> </template>
<template slot="posId" slot-scope="text, record"> <template slot="posId" slot-scope="text, record">
<a-select <a-select
:default-value="text" :default-value="text"
@change="value => onChangeExtData(value, record, 'posId')" @change="value => onChangeExtData(value, record, 'posId')"
placeholder="请选择附加职位信息" placeholder="请选择附加职位信息"
> >
<a-select-option <a-select-option
:key="i" :key="i"
:value="item.id" :value="item.id"
v-for="(item, i) in posData" v-for="(item, i) in posData"
>{{ item.name }}</a-select-option> >{{ item.name }}</a-select-option>
</a-select> </a-select>
</template> </template>
<template slot="action" slot-scope="text, record"> <template slot="action" slot-scope="text, record">
<a-button @click="onRemoveExtData(record)" size="small" type="danger">删除</a-button> <a-button @click="onRemoveExtData(record)" size="small" type="danger">删除</a-button>
</template> </template>
</a-table> </a-table>
</div> </div>
</a-col> </a-col>
</a-row> </a-row>
</a-spin> </a-spin>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
const validateToNextPassword = (rule, value, callback) => { const validateToNextPassword = (rule, value, callback) => {
callback(); callback();
}; };
const compareToFirstPassword = (rule, value, callback) => { const compareToFirstPassword = (rule, value, callback) => {
callback(); callback();
}; };
/* 表单内容默认值 */ /* 表单内容默认值 */
const defaultForm = { const defaultForm = {
/* ... */ /* ... */
sex: 0, sex: 0,
sysEmpParam: {}, sysEmpParam: {},
}; };
export default { export default {
props: { props: {
mode: { mode: {
type: String, type: String,
default: 'edit', default: 'edit',
}, },
}, },
data() { data() {
return { return {
/** 表单数据 */ /** 表单数据 */
form: {}, form: {},
/** 验证格式 */ /** 验证格式 */
rules: { rules: {
/* ... */ /* ... */
account: [{ required: true, min: 5, message: '请输入至少五个字符的账号', trigger: 'blur' }], account: [{ required: true, min: 5, message: '请输入至少五个字符的账号', trigger: 'blur' }],
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }], name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
password: [ password: [
{ required: true, min: 5, message: '请输入至少五个字符的密码', trigger: 'blur' }, { required: true, min: 5, message: '请输入至少五个字符的密码', trigger: 'blur' },
{ validator: validateToNextPassword, trigger: 'blur' }, { validator: validateToNextPassword, trigger: 'blur' },
], ],
confirm: [ confirm: [
{ required: true, message: '请确认密码', trigger: 'blur' }, { required: true, message: '请确认密码', trigger: 'blur' },
{ validator: compareToFirstPassword, trigger: 'blur' }, { validator: compareToFirstPassword, trigger: 'blur' },
], ],
phone: [ phone: [
{ {
pattern: /^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$/, pattern: /^((13[0-9])|(14[5,7])|(15[^4,\\D])|(17[0,1,3,6-8])|(18[0-9])|(19[8,9])|(166))[0-9]{8}$/,
message: '手机号格式不正确', message: '手机号格式不正确',
trigger: 'blur', trigger: 'blur',
}, },
], ],
email: [ email: [
{ pattern: /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/, message: '邮箱格式不正确', trigger: 'blur' }, { pattern: /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/, message: '邮箱格式不正确', trigger: 'blur' },
], ],
'sysEmpParam.orgId': [{ required: true, message: '请选择所属组织机构' }], 'sysEmpParam.orgId': [{ required: true, message: '请选择所属组织机构' }],
'sysEmpParam.posIdList': [{ required: true, message: '请选择职位信息' }], 'sysEmpParam.posIdList': [{ required: true, message: '请选择职位信息' }],
}, },
/** 加载异步数据状态 */ /** 加载异步数据状态 */
loading: false, loading: false,
/** 其他成员属性 */ /** 其他成员属性 */
/* ... */ /* ... */
orgData: [], orgData: [],
posData: [], posData: [],
extColumns: [ extColumns: [
{ {
title: '附属机构', title: '附属机构',
dataIndex: 'orgId', dataIndex: 'orgId',
width: '45%', width: '45%',
scopedSlots: { customRender: 'orgId' }, scopedSlots: { customRender: 'orgId' },
}, },
{ {
title: '附属岗位', title: '附属岗位',
dataIndex: 'posId', dataIndex: 'posId',
width: '45%', width: '45%',
scopedSlots: { customRender: 'posId' }, scopedSlots: { customRender: 'posId' },
}, },
{ {
title: '操作', title: '操作',
key: 'action', key: 'action',
width: '70px', width: '70px',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}, },
], ],
}; };
}, },
methods: { methods: {
/** /**
* 必要的方法 * 必要的方法
* 在打开编辑页时允许填充数据 * 在打开编辑页时允许填充数据
*/ */
onFillData(params) { onFillData(params) {
const form = this.$_.cloneDeep(params.record || {}); const form = this.$_.cloneDeep(params.record || {});
// 日期特殊处理 // 日期特殊处理
if (form.birthday) { if (form.birthday) {
form.birthday = this.$moment(form.birthday).format('YYYY-MM-DD'); form.birthday = this.$moment(form.birthday).format('YYYY-MM-DD');
} }
// 提交的时候是"param",而获取下来却是"info",在这里转换一下 // 提交的时候是"param",而获取下来却是"info",在这里转换一下
if (form.sysEmpInfo) { if (form.sysEmpInfo) {
form.sysEmpParam = form.sysEmpInfo; form.sysEmpParam = form.sysEmpInfo;
delete form.sysEmpInfo; delete form.sysEmpInfo;
} else if (!form.sysEmpParam) { } else if (!form.sysEmpParam) {
form.sysEmpParam = { form.sysEmpParam = {
extIds: [], extIds: [],
}; };
} }
// 转换职位信息列表 // 转换职位信息列表
if (form.sysEmpParam.positions) { if (form.sysEmpParam.positions) {
form.sysEmpParam.posIdList = form.sysEmpParam.positions.map((p) => p.posId); form.sysEmpParam.posIdList = form.sysEmpParam.positions.map((p) => p.posId);
} }
// 附加信息 // 附加信息
if (form.sysEmpParam.extOrgPos) { if (form.sysEmpParam.extOrgPos) {
form.sysEmpParam.extIds = form.sysEmpParam.extOrgPos.map((p, i) => { form.sysEmpParam.extIds = form.sysEmpParam.extOrgPos.map((p, i) => {
return { return {
key: i, key: i,
orgId: p.orgId, orgId: p.orgId,
posId: p.posId, posId: p.posId,
}; };
}); });
} }
if (params.orgId) { if (params.orgId) {
form.sysEmpParam.orgId = orgId; form.sysEmpParam.orgId = orgId;
} }
/** 将默认数据覆盖到form */ /** 将默认数据覆盖到form */
this.form = this.$_.cloneDeep({ this.form = this.$_.cloneDeep({
...defaultForm, ...defaultForm,
...form, ...form,
/** 在此处添加其他默认数据转换 */ /** 在此处添加其他默认数据转换 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 验证表单并获取表单数据 * 验证表单并获取表单数据
*/ */
onGetData() { onGetData() {
return new Promise((reslove, reject) => { return new Promise((reslove, reject) => {
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const record = this.$_.cloneDeep(this.form); const record = this.$_.cloneDeep(this.form);
/** 验证通过后可以对数据进行转换得到想要提交的格式 */ /** 验证通过后可以对数据进行转换得到想要提交的格式 */
/* ... */ /* ... */
reslove(record); reslove(record);
} else { } else {
reject(); reject();
} }
}); });
}); });
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口进行保存时调用表单验证 * 在外部窗口进行保存时调用表单验证
*/ */
onValidate(callback) { onValidate(callback) {
this.$refs.form.validate(callback); this.$refs.form.validate(callback);
}, },
/** /**
* 必要的方法 * 必要的方法
* 在外部窗口关闭或重置时对表单验证进行初始化 * 在外部窗口关闭或重置时对表单验证进行初始化
*/ */
onResetFields() { onResetFields() {
setTimeout(() => { setTimeout(() => {
this.$refs.form.resetFields(); this.$refs.form.resetFields();
/** 在这里可以初始化当前组件中其他属性 */ /** 在这里可以初始化当前组件中其他属性 */
/* ... */ /* ... */
this.form = { this.form = {
...defaultForm, ...defaultForm,
}; };
}, 300); }, 300);
}, },
/** /**
* 必要方法 * 必要方法
* 加载当前表单中所需要的异步数据 * 加载当前表单中所需要的异步数据
*/ */
async onInit(params) { async onInit(params) {
this.loading = true; this.loading = true;
/** 可以在这里await获取一些异步数据 */ /** 可以在这里await获取一些异步数据 */
/* ... */ /* ... */
this.orgData = await this.onLoadOrgData(); this.orgData = await this.onLoadOrgData();
this.posData = await this.onLoadPosData(); this.posData = await this.onLoadPosData();
this.loading = false; this.loading = false;
}, },
/** 当前组件的其他方法 */ /** 当前组件的其他方法 */
/* ... */ /* ... */
onLoadOrgData() { onLoadOrgData() {
return this.$api.getOrgTree().then(({ data }) => { return this.$api.getOrgTree().then(({ data }) => {
return data; return data;
}); });
}, },
onLoadPosData() { onLoadPosData() {
return this.$api.sysPosList().then(({ data }) => { return this.$api.sysPosList().then(({ data }) => {
return data; return data;
}); });
}, },
onAddExtData() { onAddExtData() {
this.form.sysEmpParam.extIds.push({ this.form.sysEmpParam.extIds.push({
key: this.form.sysEmpParam.extIds.length, key: this.form.sysEmpParam.extIds.length,
orgId: undefined, orgId: undefined,
posId: undefined, posId: undefined,
}); });
}, },
onRemoveExtData(record) { onRemoveExtData(record) {
const ext = this.form.sysEmpParam.extIds, const ext = this.form.sysEmpParam.extIds,
remove = ext.find((p) => p.key === record.key), remove = ext.find((p) => p.key === record.key),
index = ext.indexOf(remove); index = ext.indexOf(remove);
ext.splice(index, 1); ext.splice(index, 1);
}, },
onChangeExtData(value, record, type) { onChangeExtData(value, record, type) {
record[type] = value; record[type] = value;
}, },
}, },
}; };
</script> </script>

View File

@@ -1,384 +1,384 @@
<template> <template>
<!-- <!--
普通树查询表格 普通树查询表格
v 1.2 v 1.2
2021-04-30 2021-04-30
Lufthafen Lufthafen
--> -->
<yo-tree-layout <yo-tree-layout
:load-data="loadTreeData" :load-data="loadTreeData"
@select="onSelect" @select="onSelect"
default-expanded-keys default-expanded-keys
ref="tree-layout" ref="tree-layout"
> >
<container> <container>
<a-card :bordered="false"> <a-card :bordered="false">
<Auth auth="sysUser:page"> <Auth auth="sysUser:page">
<div class="yo-query-bar"> <div class="yo-query-bar">
<a-form-model :model="query" @submit.native.prevent layout="inline"> <a-form-model :model="query" @submit.native.prevent layout="inline">
<a-form-model-item label="关键词"> <a-form-model-item label="关键词">
<a-input allow-clear placeholder="请输入姓名、账号、手机号" v-model="query.searchValue" /> <a-input allow-clear placeholder="请输入姓名、账号、手机号" v-model="query.searchValue" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item label="状态"> <a-form-model-item label="状态">
<a-select <a-select
:style="{ width: '170px' }" :style="{ width: '170px' }"
allow-clear allow-clear
placeholder="请选择状态" placeholder="请选择状态"
v-model="query.searchStatus" v-model="query.searchStatus"
> >
<a-select-option <a-select-option
:key="i" :key="i"
:value="item.code" :value="item.code"
v-for="(item, i) in codes.common_status" v-for="(item, i) in codes.common_status"
>{{ item.value }}</a-select-option> >{{ item.value }}</a-select-option>
</a-select> </a-select>
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-button-group> <a-button-group>
<a-button @click="onQuery" html-type="submit" type="primary">查询</a-button> <a-button @click="onQuery" html-type="submit" type="primary">查询</a-button>
<a-button @click="onReset">重置</a-button> <a-button @click="onReset">重置</a-button>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</div> </div>
</Auth> </Auth>
<yo-list :load-data="loadData" item-layout="horizontal" ref="list" size="large"> <yo-list :load-data="loadData" item-layout="horizontal" ref="list" size="large">
<Auth auth="sysUser:add" slot="operator"> <Auth auth="sysUser:add" slot="operator">
<a-button @click="onOpen('add-form')" icon="plus">新增用户</a-button> <a-button @click="onOpen('add-form')" icon="plus">新增用户</a-button>
</Auth> </Auth>
<a-list-item key="record.id" slot="renderItem" slot-scope="record"> <a-list-item key="record.id" slot="renderItem" slot-scope="record">
<Auth auth="sysUser:edit" slot="actions"> <Auth auth="sysUser:edit" slot="actions">
<a @click="onOpen('edit-form', record)">编辑</a> <a @click="onOpen('edit-form', record)">编辑</a>
</Auth> </Auth>
<Auth auth="sysUser:delete" slot="actions"> <Auth auth="sysUser:delete" slot="actions">
<a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除"> <a-popconfirm @confirm="onDelete(record)" placement="topRight" title="是否确认删除">
<a>删除</a> <a>删除</a>
</a-popconfirm> </a-popconfirm>
</Auth> </Auth>
<Auth :auth="{ sysUser: [['grantRole'], ['grantData']] }" slot="actions"> <Auth :auth="{ sysUser: [['grantRole'], ['grantData']] }" slot="actions">
<a-dropdown placement="bottomRight"> <a-dropdown placement="bottomRight">
<a class="ant-dropdown-link"> <a class="ant-dropdown-link">
授权 授权
<a-icon type="down" /> <a-icon type="down" />
</a> </a>
<a-menu slot="overlay"> <a-menu slot="overlay">
<Auth auth="sysUser:grantRole"> <Auth auth="sysUser:grantRole">
<a-menu-item> <a-menu-item>
<a @click="onOpen('role-form', record)">授权角色</a> <a @click="onOpen('role-form', record)">授权角色</a>
</a-menu-item> </a-menu-item>
</Auth> </Auth>
<Auth auth="sysUser:grantData"> <Auth auth="sysUser:grantData">
<a-menu-item> <a-menu-item>
<a @click="onOpen('data-form', record)">授权额外数据</a> <a @click="onOpen('data-form', record)">授权额外数据</a>
</a-menu-item> </a-menu-item>
</Auth> </Auth>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</Auth> </Auth>
<a-list-item-meta> <a-list-item-meta>
<div slot="title">{{ record.nickName || record.name }}</div> <div slot="title">{{ record.nickName || record.name }}</div>
<div slot="description">{{ record.account }}</div> <div slot="description">{{ record.account }}</div>
<yo-image <yo-image
:id="record.avatar" :id="record.avatar"
:size="48" :size="48"
icon="user" icon="user"
shape="square" shape="square"
slot="avatar" slot="avatar"
type="avatar" type="avatar"
/> />
</a-list-item-meta> </a-list-item-meta>
<div class="yo-list-content--h"> <div class="yo-list-content--h">
<div class="yo-list-content--h--item"> <div class="yo-list-content--h--item">
<span>性别</span> <span>性别</span>
<p>{{ bindCodeValue(record.sex, 'sex') }}</p> <p>{{ bindCodeValue(record.sex, 'sex') }}</p>
</div> </div>
<div class="yo-list-content--h--item"> <div class="yo-list-content--h--item">
<span>手机</span> <span>手机</span>
<p>{{ record.phone || '未设置' }}</p> <p>{{ record.phone || '未设置' }}</p>
</div> </div>
<div class="yo-list-content--h--item"> <div class="yo-list-content--h--item">
<span>邮箱</span> <span>邮箱</span>
<p>{{ record.email || '未设置' }}</p> <p>{{ record.email || '未设置' }}</p>
</div> </div>
<Auth auth="sysUser:changeStatus"> <Auth auth="sysUser:changeStatus">
<div class="yo-list-content--h--item text-center"> <div class="yo-list-content--h--item text-center">
<a-switch <a-switch
:checked="!record.status" :checked="!record.status"
:checked-children="bindCodeValue(0, 'common_status')" :checked-children="bindCodeValue(0, 'common_status')"
:loading="record.statusChanging" :loading="record.statusChanging"
:un-checked-children="bindCodeValue(1, 'common_status')" :un-checked-children="bindCodeValue(1, 'common_status')"
@change="(checked) => onSetUserStatus(record, checked)" @change="(checked) => onSetUserStatus(record, checked)"
/> />
</div> </div>
</Auth> </Auth>
</div> </div>
</a-list-item> </a-list-item>
</yo-list> </yo-list>
</a-card> </a-card>
</container> </container>
<!-- 新增表单 --> <!-- 新增表单 -->
<yo-modal-form <yo-modal-form
:action="$api[api.add]" :action="$api[api.add]"
:title="'新增' + name" :title="'新增' + name"
:width="1024" :width="1024"
@ok="onReloadData" @ok="onReloadData"
ref="add-form" ref="add-form"
> >
<form-body mode="add" /> <form-body mode="add" />
</yo-modal-form> </yo-modal-form>
<!-- 编辑表单 --> <!-- 编辑表单 -->
<yo-modal-form <yo-modal-form
:action="$api[api.edit]" :action="$api[api.edit]"
:title="'编辑' + name" :title="'编辑' + name"
:width="1024" :width="1024"
@ok="onReloadData" @ok="onReloadData"
ref="edit-form" ref="edit-form"
> >
<form-body mode="edit" /> <form-body mode="edit" />
</yo-modal-form> </yo-modal-form>
<role-form @ok="onReloadData" ref="role-form" /> <role-form @ok="onReloadData" ref="role-form" />
<data-form @ok="onReloadData" ref="data-form" /> <data-form @ok="onReloadData" ref="data-form" />
</yo-tree-layout> </yo-tree-layout>
</template> </template>
<script> <script>
/* 需要引用YoTreeLayout组件 */ /* 需要引用YoTreeLayout组件 */
import YoTreeLayout from '@/components/yoTreeLayout'; import YoTreeLayout from '@/components/yoTreeLayout';
import YoList from '@/components/yoList'; import YoList from '@/components/yoList';
import FormBody from './form'; import FormBody from './form';
import RoleForm from './roleForm'; import RoleForm from './roleForm';
import DataForm from './dataForm'; import DataForm from './dataForm';
/* 在此管理整个页面需要的接口名称 */ /* 在此管理整个页面需要的接口名称 */
const api = { const api = {
tree: 'getOrgTree', tree: 'getOrgTree',
page: 'getUserPage', page: 'getUserPage',
add: 'sysUserAdd', add: 'sysUserAdd',
edit: 'sysUserEdit', edit: 'sysUserEdit',
delete: 'sysUserDelete', delete: 'sysUserDelete',
/* ... */ /* ... */
}; };
export default { export default {
components: { components: {
YoTreeLayout, YoTreeLayout,
YoList, YoList,
FormBody, FormBody,
RoleForm, RoleForm,
DataForm, DataForm,
}, },
data() { data() {
return { return {
api, api,
name: '用户', name: '用户',
/* 查询条件 */ /* 查询条件 */
query: {}, query: {},
/* 表格字段 */ /* 表格字段 */
columns: [], columns: [],
/* 字典编码储存格式 */ /* 字典编码储存格式 */
codes: { codes: {
sex: [], sex: [],
common_status: [], common_status: [],
}, },
}; };
}, },
created() { created() {
this.onLoadCodes(); this.onLoadCodes();
/** 根据权限添加操作列 */ /** 根据权限添加操作列 */
const flag = this.$auth({ const flag = this.$auth({
sysUser: [['edit'], ['delete'], ['grantRole'], ['grantData']], sysUser: [['edit'], ['delete'], ['grantRole'], ['grantData']],
}); });
if (flag) { if (flag) {
this.columns.push({ this.columns.push({
title: '操作', title: '操作',
width: '150px', width: '150px',
dataIndex: 'action', dataIndex: 'action',
scopedSlots: { customRender: 'action' }, scopedSlots: { customRender: 'action' },
}); });
} }
}, },
methods: { methods: {
/** /**
* 树形选择界面必要的方法 * 树形选择界面必要的方法
* 传给yo-table-layout以示意数据接口 * 传给yo-table-layout以示意数据接口
*/ */
loadTreeData() { loadTreeData() {
return this.$api[api.tree]().then((res) => { return this.$api[api.tree]().then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 树形选择界面必要的方法 * 树形选择界面必要的方法
* 选择树节点事件 * 选择树节点事件
*/ */
onSelect([id]) { onSelect([id]) {
/** 在选择事件中可以对右侧表格添加父节点id的查询条件 */ /** 在选择事件中可以对右侧表格添加父节点id的查询条件 */
this.query = { this.query = {
'sysEmpParam.orgId': id, 'sysEmpParam.orgId': id,
}; };
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要的方法 * 必要的方法
* 传给yo-table以示意数据接口及其参数和返回的数据结构 * 传给yo-table以示意数据接口及其参数和返回的数据结构
*/ */
loadData(params) { loadData(params) {
return this.$api[api.page]({ return this.$api[api.page]({
...params, ...params,
...this.query, ...this.query,
}).then((res) => { }).then((res) => {
return res.data; return res.data;
}); });
}, },
/** /**
* 有查询功能时的必要方法 * 有查询功能时的必要方法
* 加载数据时初始化分页信息 * 加载数据时初始化分页信息
*/ */
onQuery() { onQuery() {
this.$refs.list.onReloadData(true); this.$refs.list.onReloadData(true);
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReset() { onReset() {
/* 与普通查询页不同的是,这里的父节点参数不应该在重置后被清空 */ /* 与普通查询页不同的是,这里的父节点参数不应该在重置后被清空 */
Object.keys(this.query).forEach((p) => { Object.keys(this.query).forEach((p) => {
if (p !== 'pid') { if (p !== 'pid') {
this.query[p] = undefined; this.query[p] = undefined;
} }
}); });
this.onQuery(); this.onQuery();
}, },
/** /**
* 必要方法 * 必要方法
* 重新列表数据 * 重新列表数据
*/ */
onReloadData() { onReloadData() {
this.$refs.list.onReloadData(); this.$refs.list.onReloadData();
this.$refs['tree-layout'].onReloadData(); this.$refs['tree-layout'].onReloadData();
}, },
/** /**
* 必要方法 * 必要方法
* 加载字典数据 * 加载字典数据
* 如果不需要获取相应的字典数据,此方法内容可空 * 如果不需要获取相应的字典数据,此方法内容可空
*/ */
onLoadCodes() { onLoadCodes() {
this.$api this.$api
.$queue([ .$queue([
this.$api.sysDictTypeDropDownAwait({ code: 'sex' }), this.$api.sysDictTypeDropDownAwait({ code: 'sex' }),
this.$api.sysDictTypeDropDownAwait({ code: 'common_status' }), this.$api.sysDictTypeDropDownAwait({ code: 'common_status' }),
/* ... */ /* ... */
]) ])
.then(([code1, code2]) => { .then(([code1, code2]) => {
this.codes.sex = code1.data; this.codes.sex = code1.data;
this.codes.common_status = code2.data; this.codes.common_status = code2.data;
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 绑定数据字典值 * 绑定数据字典值
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
const c = this.codes[name].find((p) => p.code == code); const c = this.codes[name].find((p) => p.code == code);
if (c) { if (c) {
return c.value; return c.value;
} }
return null; return null;
}, },
/** /**
* 有编辑新增功能的必要方法 * 有编辑新增功能的必要方法
* 从列表页调用窗口的打开方法 * 从列表页调用窗口的打开方法
*/ */
onOpen(formName, record) { onOpen(formName, record) {
this.$refs[formName].onOpen({ this.$refs[formName].onOpen({
record, record,
orgId: this.query['sysEmpParam.orgId'], orgId: this.query['sysEmpParam.orgId'],
/* 按需添加其他参数 */ /* 按需添加其他参数 */
/* ... */ /* ... */
}); });
}, },
/** /**
* 必要方法 * 必要方法
* 可以用做一系列操作的公共回调,此方法中会重新加载当前列表 * 可以用做一系列操作的公共回调,此方法中会重新加载当前列表
*/ */
onResult(success, successMessage) { onResult(success, successMessage) {
if (success) { if (success) {
this.$message.success(successMessage); this.$message.success(successMessage);
this.onReloadData(); this.onReloadData();
} }
}, },
/** /**
* 必要方法 * 必要方法
* 删除时调用 * 删除时调用
*/ */
onDelete(record) { onDelete(record) {
this.$refs.list.onLoading(); this.$refs.list.onLoading();
this.$api[api.delete](record) this.$api[api.delete](record)
.then(({ success }) => { .then(({ success }) => {
this.onResult(success, '删除成功'); this.onResult(success, '删除成功');
}) })
.finally(() => { .finally(() => {
this.$refs.list.onLoaded(); this.$refs.list.onLoaded();
}); });
}, },
onSetUserStatus(record, checked) { onSetUserStatus(record, checked) {
this.$set(record, 'statusChanging', true); this.$set(record, 'statusChanging', true);
this.$api this.$api
.sysUserChangeStatus({ .sysUserChangeStatus({
id: record.id, id: record.id,
status: +!checked, status: +!checked,
}) })
.then(({ success, message }) => { .then(({ success, message }) => {
if (success) { if (success) {
this.$message.success('操作成功'); this.$message.success('操作成功');
this.onReloadData(); this.onReloadData();
} else { } else {
this.$message.error(message); this.$message.error(message);
} }
}) })
.finally(() => { .finally(() => {
record.statusChanging = false; record.statusChanging = false;
}); });
}, },
onResetPassword(record) { onResetPassword(record) {
this.$api this.$api
.sysUserResetPwd({ .sysUserResetPwd({
id: record.id, id: record.id,
}) })
.then(({ success, message }) => { .then(({ success, message }) => {
if (success) { if (success) {
this.$message.success('重置成功'); this.$message.success('重置成功');
} else { } else {
this.$message.error(message); this.$message.error(message);
} }
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,34 +1,34 @@
import Vue from 'vue' import Vue from 'vue'
import Router from 'vue-router' import Router from 'vue-router'
Vue.use(Router) Vue.use(Router)
const router = new Router({ const router = new Router({
mode: 'history', mode: 'history',
routes: [{ routes: [{
path: '/', path: '/',
component: () => import('@/views/main/index'), component: () => import('@/views/main/index'),
}, { }, {
path: '/login', path: '/login',
component: () => import('@/views/login/index') component: () => import('@/views/login/index')
}] }]
}) })
// 路由守卫 // 路由守卫
import { token } from '@/common/token' import { token } from '@/common/token'
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
if (token.value) { if (token.value) {
if (to.path === '/login') { if (to.path === '/login') {
next({ next({
path: '/' path: '/'
}) })
} else { } else {
next() next()
} }
} else if (!token.value && to.path !== '/login') { } else if (!token.value && to.path !== '/login') {
next({ path: '/login' }) next({ path: '/login' })
} }
next() next()
}) })
export default router export default router

View File

@@ -1,34 +1,34 @@
import { import {
TripleDES, TripleDES,
enc, enc,
mode, mode,
pad pad
} from 'crypto-js'; } from 'crypto-js';
const KEY = process.env.VUE_APP_DEV_KEY; const KEY = process.env.VUE_APP_DEV_KEY;
const key = enc.Utf8.parse(KEY); const key = enc.Utf8.parse(KEY);
//TripleDES加密 //TripleDES加密
const encryptByDES = (message) => { const encryptByDES = (message) => {
let encrypted = TripleDES.encrypt(message, key, { let encrypted = TripleDES.encrypt(message, key, {
mode: mode.ECB, mode: mode.ECB,
padding: pad.Pkcs7 padding: pad.Pkcs7
}); });
return encrypted.toString(); return encrypted.toString();
} }
//TripleDES解密 //TripleDES解密
const decryptByDES = (ciphertext) => { const decryptByDES = (ciphertext) => {
let decrypted = TripleDES.decrypt({ let decrypted = TripleDES.decrypt({
ciphertext: enc.Base64.parse(ciphertext) ciphertext: enc.Base64.parse(ciphertext)
}, key, { }, key, {
mode: mode.ECB, mode: mode.ECB,
}); });
const value = decrypted.toString(enc.Utf8); const value = decrypted.toString(enc.Utf8);
return value; return value;
} }
export { export {
encryptByDES, encryptByDES,
decryptByDES decryptByDES
} }

View File

@@ -1,308 +1,308 @@
@import (reference) '~ant-design-vue/dist/antd.less'; @import (reference) '~ant-design-vue/dist/antd.less';
@-webkit-keyframes noise-anim-after { @-webkit-keyframes noise-anim-after {
0% { 0% {
clip: rect(32px, 9999px, 16px, 0); clip: rect(32px, 9999px, 16px, 0);
} }
5% { 5% {
clip: rect(5px, 9999px, 24px, 0); clip: rect(5px, 9999px, 24px, 0);
} }
10% { 10% {
clip: rect(77px, 9999px, 87px, 0); clip: rect(77px, 9999px, 87px, 0);
} }
15% { 15% {
clip: rect(91px, 9999px, 95px, 0); clip: rect(91px, 9999px, 95px, 0);
} }
20% { 20% {
clip: rect(74px, 9999px, 9px, 0); clip: rect(74px, 9999px, 9px, 0);
} }
25% { 25% {
clip: rect(37px, 9999px, 32px, 0); clip: rect(37px, 9999px, 32px, 0);
} }
30% { 30% {
clip: rect(56px, 9999px, 27px, 0); clip: rect(56px, 9999px, 27px, 0);
} }
35% { 35% {
clip: rect(35px, 9999px, 33px, 0); clip: rect(35px, 9999px, 33px, 0);
} }
40% { 40% {
clip: rect(89px, 9999px, 6px, 0); clip: rect(89px, 9999px, 6px, 0);
} }
45% { 45% {
clip: rect(81px, 9999px, 77px, 0); clip: rect(81px, 9999px, 77px, 0);
} }
50% { 50% {
clip: rect(64px, 9999px, 69px, 0); clip: rect(64px, 9999px, 69px, 0);
} }
55% { 55% {
clip: rect(12px, 9999px, 11px, 0); clip: rect(12px, 9999px, 11px, 0);
} }
60% { 60% {
clip: rect(59px, 9999px, 11px, 0); clip: rect(59px, 9999px, 11px, 0);
} }
65% { 65% {
clip: rect(69px, 9999px, 59px, 0); clip: rect(69px, 9999px, 59px, 0);
} }
70% { 70% {
clip: rect(74px, 9999px, 65px, 0); clip: rect(74px, 9999px, 65px, 0);
} }
75% { 75% {
clip: rect(56px, 9999px, 79px, 0); clip: rect(56px, 9999px, 79px, 0);
} }
80% { 80% {
clip: rect(80px, 9999px, 64px, 0); clip: rect(80px, 9999px, 64px, 0);
} }
85% { 85% {
clip: rect(87px, 9999px, 29px, 0); clip: rect(87px, 9999px, 29px, 0);
} }
90% { 90% {
clip: rect(16px, 9999px, 21px, 0); clip: rect(16px, 9999px, 21px, 0);
} }
95% { 95% {
clip: rect(69px, 9999px, 43px, 0); clip: rect(69px, 9999px, 43px, 0);
} }
100% { 100% {
clip: rect(75px, 9999px, 63px, 0); clip: rect(75px, 9999px, 63px, 0);
} }
} }
@keyframes noise-anim-after { @keyframes noise-anim-after {
0% { 0% {
clip: rect(32px, 9999px, 16px, 0); clip: rect(32px, 9999px, 16px, 0);
} }
5% { 5% {
clip: rect(5px, 9999px, 24px, 0); clip: rect(5px, 9999px, 24px, 0);
} }
10% { 10% {
clip: rect(77px, 9999px, 87px, 0); clip: rect(77px, 9999px, 87px, 0);
} }
15% { 15% {
clip: rect(91px, 9999px, 95px, 0); clip: rect(91px, 9999px, 95px, 0);
} }
20% { 20% {
clip: rect(74px, 9999px, 9px, 0); clip: rect(74px, 9999px, 9px, 0);
} }
25% { 25% {
clip: rect(37px, 9999px, 32px, 0); clip: rect(37px, 9999px, 32px, 0);
} }
30% { 30% {
clip: rect(56px, 9999px, 27px, 0); clip: rect(56px, 9999px, 27px, 0);
} }
35% { 35% {
clip: rect(35px, 9999px, 33px, 0); clip: rect(35px, 9999px, 33px, 0);
} }
40% { 40% {
clip: rect(89px, 9999px, 6px, 0); clip: rect(89px, 9999px, 6px, 0);
} }
45% { 45% {
clip: rect(81px, 9999px, 77px, 0); clip: rect(81px, 9999px, 77px, 0);
} }
50% { 50% {
clip: rect(64px, 9999px, 69px, 0); clip: rect(64px, 9999px, 69px, 0);
} }
55% { 55% {
clip: rect(12px, 9999px, 11px, 0); clip: rect(12px, 9999px, 11px, 0);
} }
60% { 60% {
clip: rect(59px, 9999px, 11px, 0); clip: rect(59px, 9999px, 11px, 0);
} }
65% { 65% {
clip: rect(69px, 9999px, 59px, 0); clip: rect(69px, 9999px, 59px, 0);
} }
70% { 70% {
clip: rect(74px, 9999px, 65px, 0); clip: rect(74px, 9999px, 65px, 0);
} }
75% { 75% {
clip: rect(56px, 9999px, 79px, 0); clip: rect(56px, 9999px, 79px, 0);
} }
80% { 80% {
clip: rect(80px, 9999px, 64px, 0); clip: rect(80px, 9999px, 64px, 0);
} }
85% { 85% {
clip: rect(87px, 9999px, 29px, 0); clip: rect(87px, 9999px, 29px, 0);
} }
90% { 90% {
clip: rect(16px, 9999px, 21px, 0); clip: rect(16px, 9999px, 21px, 0);
} }
95% { 95% {
clip: rect(69px, 9999px, 43px, 0); clip: rect(69px, 9999px, 43px, 0);
} }
100% { 100% {
clip: rect(75px, 9999px, 63px, 0); clip: rect(75px, 9999px, 63px, 0);
} }
} }
@-webkit-keyframes noise-anim-before { @-webkit-keyframes noise-anim-before {
0% { 0% {
clip: rect(12px, 9999px, 52px, 0); clip: rect(12px, 9999px, 52px, 0);
} }
5% { 5% {
clip: rect(42px, 9999px, 39px, 0); clip: rect(42px, 9999px, 39px, 0);
} }
10% { 10% {
clip: rect(64px, 9999px, 36px, 0); clip: rect(64px, 9999px, 36px, 0);
} }
15% { 15% {
clip: rect(52px, 9999px, 15px, 0); clip: rect(52px, 9999px, 15px, 0);
} }
20% { 20% {
clip: rect(79px, 9999px, 7px, 0); clip: rect(79px, 9999px, 7px, 0);
} }
25% { 25% {
clip: rect(17px, 9999px, 41px, 0); clip: rect(17px, 9999px, 41px, 0);
} }
30% { 30% {
clip: rect(15px, 9999px, 20px, 0); clip: rect(15px, 9999px, 20px, 0);
} }
35% { 35% {
clip: rect(62px, 9999px, 87px, 0); clip: rect(62px, 9999px, 87px, 0);
} }
40% { 40% {
clip: rect(94px, 9999px, 11px, 0); clip: rect(94px, 9999px, 11px, 0);
} }
45% { 45% {
clip: rect(49px, 9999px, 10px, 0); clip: rect(49px, 9999px, 10px, 0);
} }
50% { 50% {
clip: rect(82px, 9999px, 4px, 0); clip: rect(82px, 9999px, 4px, 0);
} }
55% { 55% {
clip: rect(70px, 9999px, 100px, 0); clip: rect(70px, 9999px, 100px, 0);
} }
60% { 60% {
clip: rect(62px, 9999px, 23px, 0); clip: rect(62px, 9999px, 23px, 0);
} }
65% { 65% {
clip: rect(51px, 9999px, 56px, 0); clip: rect(51px, 9999px, 56px, 0);
} }
70% { 70% {
clip: rect(41px, 9999px, 24px, 0); clip: rect(41px, 9999px, 24px, 0);
} }
75% { 75% {
clip: rect(6px, 9999px, 85px, 0); clip: rect(6px, 9999px, 85px, 0);
} }
80% { 80% {
clip: rect(96px, 9999px, 58px, 0); clip: rect(96px, 9999px, 58px, 0);
} }
85% { 85% {
clip: rect(16px, 9999px, 24px, 0); clip: rect(16px, 9999px, 24px, 0);
} }
90% { 90% {
clip: rect(40px, 9999px, 31px, 0); clip: rect(40px, 9999px, 31px, 0);
} }
95% { 95% {
clip: rect(91px, 9999px, 34px, 0); clip: rect(91px, 9999px, 34px, 0);
} }
100% { 100% {
clip: rect(87px, 9999px, 26px, 0); clip: rect(87px, 9999px, 26px, 0);
} }
} }
@keyframes noise-anim-before { @keyframes noise-anim-before {
0% { 0% {
clip: rect(12px, 9999px, 52px, 0); clip: rect(12px, 9999px, 52px, 0);
} }
5% { 5% {
clip: rect(42px, 9999px, 39px, 0); clip: rect(42px, 9999px, 39px, 0);
} }
10% { 10% {
clip: rect(64px, 9999px, 36px, 0); clip: rect(64px, 9999px, 36px, 0);
} }
15% { 15% {
clip: rect(52px, 9999px, 15px, 0); clip: rect(52px, 9999px, 15px, 0);
} }
20% { 20% {
clip: rect(79px, 9999px, 7px, 0); clip: rect(79px, 9999px, 7px, 0);
} }
25% { 25% {
clip: rect(17px, 9999px, 41px, 0); clip: rect(17px, 9999px, 41px, 0);
} }
30% { 30% {
clip: rect(15px, 9999px, 20px, 0); clip: rect(15px, 9999px, 20px, 0);
} }
35% { 35% {
clip: rect(62px, 9999px, 87px, 0); clip: rect(62px, 9999px, 87px, 0);
} }
40% { 40% {
clip: rect(94px, 9999px, 11px, 0); clip: rect(94px, 9999px, 11px, 0);
} }
45% { 45% {
clip: rect(49px, 9999px, 10px, 0); clip: rect(49px, 9999px, 10px, 0);
} }
50% { 50% {
clip: rect(82px, 9999px, 4px, 0); clip: rect(82px, 9999px, 4px, 0);
} }
55% { 55% {
clip: rect(70px, 9999px, 100px, 0); clip: rect(70px, 9999px, 100px, 0);
} }
60% { 60% {
clip: rect(62px, 9999px, 23px, 0); clip: rect(62px, 9999px, 23px, 0);
} }
65% { 65% {
clip: rect(51px, 9999px, 56px, 0); clip: rect(51px, 9999px, 56px, 0);
} }
70% { 70% {
clip: rect(41px, 9999px, 24px, 0); clip: rect(41px, 9999px, 24px, 0);
} }
75% { 75% {
clip: rect(6px, 9999px, 85px, 0); clip: rect(6px, 9999px, 85px, 0);
} }
80% { 80% {
clip: rect(96px, 9999px, 58px, 0); clip: rect(96px, 9999px, 58px, 0);
} }
85% { 85% {
clip: rect(16px, 9999px, 24px, 0); clip: rect(16px, 9999px, 24px, 0);
} }
90% { 90% {
clip: rect(40px, 9999px, 31px, 0); clip: rect(40px, 9999px, 31px, 0);
} }
95% { 95% {
clip: rect(91px, 9999px, 34px, 0); clip: rect(91px, 9999px, 34px, 0);
} }
100% { 100% {
clip: rect(87px, 9999px, 26px, 0); clip: rect(87px, 9999px, 26px, 0);
} }
} }
.error-result { .error-result {
padding: 100px; padding: 100px;
text-transform: uppercase; text-transform: uppercase;
&--text { &--text {
font-size: @font-size-base * 8; font-size: @font-size-base * 8;
line-height: 1; line-height: 1;
position: relative; position: relative;
display: block; display: block;
width: 12.5rem; width: 12.5rem;
color: #5a5c69; color: #5a5c69;
&::after { &::after {
position: absolute; position: absolute;
top: 0; top: 0;
left: 2px; left: 2px;
overflow: hidden; overflow: hidden;
clip: rect(0, 900px, 0, 0); clip: rect(0, 900px, 0, 0);
content: attr(data-text); content: attr(data-text);
animation: noise-anim-after 2s infinite linear alternate-reverse; animation: noise-anim-after 2s infinite linear alternate-reverse;
color: #5a5c69; color: #5a5c69;
background: @layout-body-background; background: @layout-body-background;
text-shadow: -1px 0 #e74a3b; text-shadow: -1px 0 #e74a3b;
} }
&::before { &::before {
position: absolute; position: absolute;
top: 0; top: 0;
left: -2px; left: -2px;
overflow: hidden; overflow: hidden;
clip: rect(0, 900px, 0, 0); clip: rect(0, 900px, 0, 0);
content: attr(data-text); content: attr(data-text);
animation: noise-anim-before 3s infinite linear alternate-reverse; animation: noise-anim-before 3s infinite linear alternate-reverse;
color: #5a5c69; color: #5a5c69;
background: @layout-body-background; background: @layout-body-background;
text-shadow: 1px 0 #4e73df; text-shadow: 1px 0 #4e73df;
} }
} }
} }

View File

@@ -1,14 +1,14 @@
<template> <template>
<container> <container>
<div class="error-result"> <div class="error-result">
<div class="error-result--code"> <div class="error-result--code">
<span class="error-result--text" data-text="404">404</span> <span class="error-result--text" data-text="404">404</span>
</div> </div>
<p>not found</p> <p>not found</p>
</div> </div>
</container> </container>
</template> </template>
<style lang="less" scope> <style lang="less" scope>
@import './index.less'; @import './index.less';
</style> </style>

View File

@@ -1,308 +1,308 @@
@import (reference) '~ant-design-vue/dist/antd.less'; @import (reference) '~ant-design-vue/dist/antd.less';
@-webkit-keyframes noise-anim-after { @-webkit-keyframes noise-anim-after {
0% { 0% {
clip: rect(32px, 9999px, 16px, 0); clip: rect(32px, 9999px, 16px, 0);
} }
5% { 5% {
clip: rect(5px, 9999px, 24px, 0); clip: rect(5px, 9999px, 24px, 0);
} }
10% { 10% {
clip: rect(77px, 9999px, 87px, 0); clip: rect(77px, 9999px, 87px, 0);
} }
15% { 15% {
clip: rect(91px, 9999px, 95px, 0); clip: rect(91px, 9999px, 95px, 0);
} }
20% { 20% {
clip: rect(74px, 9999px, 9px, 0); clip: rect(74px, 9999px, 9px, 0);
} }
25% { 25% {
clip: rect(37px, 9999px, 32px, 0); clip: rect(37px, 9999px, 32px, 0);
} }
30% { 30% {
clip: rect(56px, 9999px, 27px, 0); clip: rect(56px, 9999px, 27px, 0);
} }
35% { 35% {
clip: rect(35px, 9999px, 33px, 0); clip: rect(35px, 9999px, 33px, 0);
} }
40% { 40% {
clip: rect(89px, 9999px, 6px, 0); clip: rect(89px, 9999px, 6px, 0);
} }
45% { 45% {
clip: rect(81px, 9999px, 77px, 0); clip: rect(81px, 9999px, 77px, 0);
} }
50% { 50% {
clip: rect(64px, 9999px, 69px, 0); clip: rect(64px, 9999px, 69px, 0);
} }
55% { 55% {
clip: rect(12px, 9999px, 11px, 0); clip: rect(12px, 9999px, 11px, 0);
} }
60% { 60% {
clip: rect(59px, 9999px, 11px, 0); clip: rect(59px, 9999px, 11px, 0);
} }
65% { 65% {
clip: rect(69px, 9999px, 59px, 0); clip: rect(69px, 9999px, 59px, 0);
} }
70% { 70% {
clip: rect(74px, 9999px, 65px, 0); clip: rect(74px, 9999px, 65px, 0);
} }
75% { 75% {
clip: rect(56px, 9999px, 79px, 0); clip: rect(56px, 9999px, 79px, 0);
} }
80% { 80% {
clip: rect(80px, 9999px, 64px, 0); clip: rect(80px, 9999px, 64px, 0);
} }
85% { 85% {
clip: rect(87px, 9999px, 29px, 0); clip: rect(87px, 9999px, 29px, 0);
} }
90% { 90% {
clip: rect(16px, 9999px, 21px, 0); clip: rect(16px, 9999px, 21px, 0);
} }
95% { 95% {
clip: rect(69px, 9999px, 43px, 0); clip: rect(69px, 9999px, 43px, 0);
} }
100% { 100% {
clip: rect(75px, 9999px, 63px, 0); clip: rect(75px, 9999px, 63px, 0);
} }
} }
@keyframes noise-anim-after { @keyframes noise-anim-after {
0% { 0% {
clip: rect(32px, 9999px, 16px, 0); clip: rect(32px, 9999px, 16px, 0);
} }
5% { 5% {
clip: rect(5px, 9999px, 24px, 0); clip: rect(5px, 9999px, 24px, 0);
} }
10% { 10% {
clip: rect(77px, 9999px, 87px, 0); clip: rect(77px, 9999px, 87px, 0);
} }
15% { 15% {
clip: rect(91px, 9999px, 95px, 0); clip: rect(91px, 9999px, 95px, 0);
} }
20% { 20% {
clip: rect(74px, 9999px, 9px, 0); clip: rect(74px, 9999px, 9px, 0);
} }
25% { 25% {
clip: rect(37px, 9999px, 32px, 0); clip: rect(37px, 9999px, 32px, 0);
} }
30% { 30% {
clip: rect(56px, 9999px, 27px, 0); clip: rect(56px, 9999px, 27px, 0);
} }
35% { 35% {
clip: rect(35px, 9999px, 33px, 0); clip: rect(35px, 9999px, 33px, 0);
} }
40% { 40% {
clip: rect(89px, 9999px, 6px, 0); clip: rect(89px, 9999px, 6px, 0);
} }
45% { 45% {
clip: rect(81px, 9999px, 77px, 0); clip: rect(81px, 9999px, 77px, 0);
} }
50% { 50% {
clip: rect(64px, 9999px, 69px, 0); clip: rect(64px, 9999px, 69px, 0);
} }
55% { 55% {
clip: rect(12px, 9999px, 11px, 0); clip: rect(12px, 9999px, 11px, 0);
} }
60% { 60% {
clip: rect(59px, 9999px, 11px, 0); clip: rect(59px, 9999px, 11px, 0);
} }
65% { 65% {
clip: rect(69px, 9999px, 59px, 0); clip: rect(69px, 9999px, 59px, 0);
} }
70% { 70% {
clip: rect(74px, 9999px, 65px, 0); clip: rect(74px, 9999px, 65px, 0);
} }
75% { 75% {
clip: rect(56px, 9999px, 79px, 0); clip: rect(56px, 9999px, 79px, 0);
} }
80% { 80% {
clip: rect(80px, 9999px, 64px, 0); clip: rect(80px, 9999px, 64px, 0);
} }
85% { 85% {
clip: rect(87px, 9999px, 29px, 0); clip: rect(87px, 9999px, 29px, 0);
} }
90% { 90% {
clip: rect(16px, 9999px, 21px, 0); clip: rect(16px, 9999px, 21px, 0);
} }
95% { 95% {
clip: rect(69px, 9999px, 43px, 0); clip: rect(69px, 9999px, 43px, 0);
} }
100% { 100% {
clip: rect(75px, 9999px, 63px, 0); clip: rect(75px, 9999px, 63px, 0);
} }
} }
@-webkit-keyframes noise-anim-before { @-webkit-keyframes noise-anim-before {
0% { 0% {
clip: rect(12px, 9999px, 52px, 0); clip: rect(12px, 9999px, 52px, 0);
} }
5% { 5% {
clip: rect(42px, 9999px, 39px, 0); clip: rect(42px, 9999px, 39px, 0);
} }
10% { 10% {
clip: rect(64px, 9999px, 36px, 0); clip: rect(64px, 9999px, 36px, 0);
} }
15% { 15% {
clip: rect(52px, 9999px, 15px, 0); clip: rect(52px, 9999px, 15px, 0);
} }
20% { 20% {
clip: rect(79px, 9999px, 7px, 0); clip: rect(79px, 9999px, 7px, 0);
} }
25% { 25% {
clip: rect(17px, 9999px, 41px, 0); clip: rect(17px, 9999px, 41px, 0);
} }
30% { 30% {
clip: rect(15px, 9999px, 20px, 0); clip: rect(15px, 9999px, 20px, 0);
} }
35% { 35% {
clip: rect(62px, 9999px, 87px, 0); clip: rect(62px, 9999px, 87px, 0);
} }
40% { 40% {
clip: rect(94px, 9999px, 11px, 0); clip: rect(94px, 9999px, 11px, 0);
} }
45% { 45% {
clip: rect(49px, 9999px, 10px, 0); clip: rect(49px, 9999px, 10px, 0);
} }
50% { 50% {
clip: rect(82px, 9999px, 4px, 0); clip: rect(82px, 9999px, 4px, 0);
} }
55% { 55% {
clip: rect(70px, 9999px, 100px, 0); clip: rect(70px, 9999px, 100px, 0);
} }
60% { 60% {
clip: rect(62px, 9999px, 23px, 0); clip: rect(62px, 9999px, 23px, 0);
} }
65% { 65% {
clip: rect(51px, 9999px, 56px, 0); clip: rect(51px, 9999px, 56px, 0);
} }
70% { 70% {
clip: rect(41px, 9999px, 24px, 0); clip: rect(41px, 9999px, 24px, 0);
} }
75% { 75% {
clip: rect(6px, 9999px, 85px, 0); clip: rect(6px, 9999px, 85px, 0);
} }
80% { 80% {
clip: rect(96px, 9999px, 58px, 0); clip: rect(96px, 9999px, 58px, 0);
} }
85% { 85% {
clip: rect(16px, 9999px, 24px, 0); clip: rect(16px, 9999px, 24px, 0);
} }
90% { 90% {
clip: rect(40px, 9999px, 31px, 0); clip: rect(40px, 9999px, 31px, 0);
} }
95% { 95% {
clip: rect(91px, 9999px, 34px, 0); clip: rect(91px, 9999px, 34px, 0);
} }
100% { 100% {
clip: rect(87px, 9999px, 26px, 0); clip: rect(87px, 9999px, 26px, 0);
} }
} }
@keyframes noise-anim-before { @keyframes noise-anim-before {
0% { 0% {
clip: rect(12px, 9999px, 52px, 0); clip: rect(12px, 9999px, 52px, 0);
} }
5% { 5% {
clip: rect(42px, 9999px, 39px, 0); clip: rect(42px, 9999px, 39px, 0);
} }
10% { 10% {
clip: rect(64px, 9999px, 36px, 0); clip: rect(64px, 9999px, 36px, 0);
} }
15% { 15% {
clip: rect(52px, 9999px, 15px, 0); clip: rect(52px, 9999px, 15px, 0);
} }
20% { 20% {
clip: rect(79px, 9999px, 7px, 0); clip: rect(79px, 9999px, 7px, 0);
} }
25% { 25% {
clip: rect(17px, 9999px, 41px, 0); clip: rect(17px, 9999px, 41px, 0);
} }
30% { 30% {
clip: rect(15px, 9999px, 20px, 0); clip: rect(15px, 9999px, 20px, 0);
} }
35% { 35% {
clip: rect(62px, 9999px, 87px, 0); clip: rect(62px, 9999px, 87px, 0);
} }
40% { 40% {
clip: rect(94px, 9999px, 11px, 0); clip: rect(94px, 9999px, 11px, 0);
} }
45% { 45% {
clip: rect(49px, 9999px, 10px, 0); clip: rect(49px, 9999px, 10px, 0);
} }
50% { 50% {
clip: rect(82px, 9999px, 4px, 0); clip: rect(82px, 9999px, 4px, 0);
} }
55% { 55% {
clip: rect(70px, 9999px, 100px, 0); clip: rect(70px, 9999px, 100px, 0);
} }
60% { 60% {
clip: rect(62px, 9999px, 23px, 0); clip: rect(62px, 9999px, 23px, 0);
} }
65% { 65% {
clip: rect(51px, 9999px, 56px, 0); clip: rect(51px, 9999px, 56px, 0);
} }
70% { 70% {
clip: rect(41px, 9999px, 24px, 0); clip: rect(41px, 9999px, 24px, 0);
} }
75% { 75% {
clip: rect(6px, 9999px, 85px, 0); clip: rect(6px, 9999px, 85px, 0);
} }
80% { 80% {
clip: rect(96px, 9999px, 58px, 0); clip: rect(96px, 9999px, 58px, 0);
} }
85% { 85% {
clip: rect(16px, 9999px, 24px, 0); clip: rect(16px, 9999px, 24px, 0);
} }
90% { 90% {
clip: rect(40px, 9999px, 31px, 0); clip: rect(40px, 9999px, 31px, 0);
} }
95% { 95% {
clip: rect(91px, 9999px, 34px, 0); clip: rect(91px, 9999px, 34px, 0);
} }
100% { 100% {
clip: rect(87px, 9999px, 26px, 0); clip: rect(87px, 9999px, 26px, 0);
} }
} }
.error-result { .error-result {
padding: 100px; padding: 100px;
text-transform: uppercase; text-transform: uppercase;
&--text { &--text {
font-size: @font-size-base * 8; font-size: @font-size-base * 8;
line-height: 1; line-height: 1;
position: relative; position: relative;
display: block; display: block;
width: 12.5rem; width: 12.5rem;
color: #5a5c69; color: #5a5c69;
&::after { &::after {
position: absolute; position: absolute;
top: 0; top: 0;
left: 2px; left: 2px;
overflow: hidden; overflow: hidden;
clip: rect(0, 900px, 0, 0); clip: rect(0, 900px, 0, 0);
content: attr(data-text); content: attr(data-text);
animation: noise-anim-after 2s infinite linear alternate-reverse; animation: noise-anim-after 2s infinite linear alternate-reverse;
color: #5a5c69; color: #5a5c69;
background: @layout-body-background; background: @layout-body-background;
text-shadow: -1px 0 #e74a3b; text-shadow: -1px 0 #e74a3b;
} }
&::before { &::before {
position: absolute; position: absolute;
top: 0; top: 0;
left: -2px; left: -2px;
overflow: hidden; overflow: hidden;
clip: rect(0, 900px, 0, 0); clip: rect(0, 900px, 0, 0);
content: attr(data-text); content: attr(data-text);
animation: noise-anim-before 3s infinite linear alternate-reverse; animation: noise-anim-before 3s infinite linear alternate-reverse;
color: #5a5c69; color: #5a5c69;
background: @layout-body-background; background: @layout-body-background;
text-shadow: 1px 0 #4e73df; text-shadow: 1px 0 #4e73df;
} }
} }
} }

View File

@@ -1,14 +1,14 @@
<template> <template>
<container> <container>
<div class="error-result"> <div class="error-result">
<div class="error-result--code"> <div class="error-result--code">
<span class="error-result--text" data-text="404">404</span> <span class="error-result--text" data-text="404">404</span>
</div> </div>
<p>not found</p> <p>not found</p>
</div> </div>
</container> </container>
</template> </template>
<style lang="less" scope> <style lang="less" scope>
@import './index.less'; @import './index.less';
</style> </style>

View File

@@ -1,48 +1,48 @@
<template> <template>
<a-form-model :model="form" @submit="handleSubmit" @submit.native.prevent layout="inline"> <a-form-model :model="form" @submit="handleSubmit" @submit.native.prevent layout="inline">
<a-form-model-item> <a-form-model-item>
<a-input placeholder="Username" v-model="form.user"> <a-input placeholder="Username" v-model="form.user">
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="user" /> <a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="user" />
</a-input> </a-input>
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-input placeholder="Password" type="password" v-model="form.password"> <a-input placeholder="Password" type="password" v-model="form.password">
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="lock" /> <a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="lock" />
</a-input> </a-input>
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-button <a-button
:disabled="form.user === '' || form.password === ''" :disabled="form.user === '' || form.password === ''"
:loading="loading" :loading="loading"
html-type="submit" html-type="submit"
type="primary" type="primary"
>Log in</a-button> >Log in</a-button>
</a-form-model-item> </a-form-model-item>
</a-form-model> </a-form-model>
</template> </template>
<script> <script>
import { doLogin } from '@/common/login'; import { doLogin } from '@/common/login';
export default { export default {
data() { data() {
return { return {
loading: false, loading: false,
form: { form: {
user: '', user: '',
password: '', password: '',
}, },
}; };
}, },
methods: { methods: {
handleSubmit(e) { handleSubmit(e) {
this.loading = true; this.loading = true;
doLogin({ doLogin({
account: this.form.user, account: this.form.user,
password: this.form.password, password: this.form.password,
}).finally(() => { }).finally(() => {
this.loading = false; this.loading = false;
}); });
}, },
}, },
}; };
</script> </script>

View File

@@ -1,138 +1,138 @@
<template> <template>
<a-layout-content> <a-layout-content>
<a-tabs @change="onChange" @edit="onClose" hide-add type="editable-card" v-model="actived"> <a-tabs @change="onChange" @edit="onClose" hide-add type="editable-card" v-model="actived">
<a-tab-pane <a-tab-pane
:closable="pane.closable" :closable="pane.closable"
:forceRender="true" :forceRender="true"
:key="pane.key" :key="pane.key"
v-for="pane in panes" v-for="pane in panes"
> >
<a-dropdown :trigger="['contextmenu']" slot="tab"> <a-dropdown :trigger="['contextmenu']" slot="tab">
<div> <div>
<a-icon :type="pane.icon" v-if="pane.icon" /> <a-icon :type="pane.icon" v-if="pane.icon" />
{{ pane.title }} {{ pane.title }}
</div> </div>
<a-menu slot="overlay"> <a-menu slot="overlay">
<template v-if="mode === 'development'"> <template v-if="mode === 'development'">
<a-menu-item @click="onCopyComponent(pane)" key="-1"> <a-menu-item @click="onCopyComponent(pane)" key="-1">
复制组件地址 复制组件地址
<a-tag color="red">dev</a-tag> <a-tag color="red">dev</a-tag>
</a-menu-item> </a-menu-item>
<a-menu-divider /> <a-menu-divider />
</template> </template>
<a-menu-item @click="onLoadContentWindow(pane.key)" key="0">重新加载</a-menu-item> <a-menu-item @click="onLoadContentWindow(pane.key)" key="0">重新加载</a-menu-item>
<a-menu-divider /> <a-menu-divider />
<a-menu-item :disabled="!pane.closable" @click="$emit('close', pane.key);" key="1">关闭</a-menu-item> <a-menu-item :disabled="!pane.closable" @click="$emit('close', pane.key);" key="1">关闭</a-menu-item>
<a-menu-item <a-menu-item
:disabled="!hasOther(pane)" :disabled="!hasOther(pane)"
@click="$emit('close-other', pane.key)" @click="$emit('close-other', pane.key)"
key="2" key="2"
>关闭其他标签页</a-menu-item> >关闭其他标签页</a-menu-item>
<a-menu-item <a-menu-item
:disabled="!hasRight(pane)" :disabled="!hasRight(pane)"
@click="$emit('close-right', pane.key)" @click="$emit('close-right', pane.key)"
key="3" key="3"
>关闭右侧标签页</a-menu-item> >关闭右侧标签页</a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
<component <component
:is="pane.component" :is="pane.component"
:key="pane.key" :key="pane.key"
:param="pane.param" :param="pane.param"
ref="panes" ref="panes"
v-if="pane.loaded" v-if="pane.loaded"
/> />
</a-tab-pane> </a-tab-pane>
</a-tabs> </a-tabs>
</a-layout-content> </a-layout-content>
</template> </template>
<script> <script>
import NProgress from 'nprogress'; import NProgress from 'nprogress';
import 'nprogress/nprogress.css'; import 'nprogress/nprogress.css';
NProgress.configure({ parent: '.ant-layout-content > .ant-tabs > .ant-tabs-content' }); NProgress.configure({ parent: '.ant-layout-content > .ant-tabs > .ant-tabs-content' });
export default { export default {
props: { props: {
panes: { panes: {
type: Array, type: Array,
}, },
tabActived: { tabActived: {
type: [String, Number], type: [String, Number],
}, },
}, },
data() { data() {
return { return {
mode: process.env.VUE_APP_NODE_ENV, mode: process.env.VUE_APP_NODE_ENV,
actived: '', actived: '',
}; };
}, },
watch: { watch: {
tabActived() { tabActived() {
if (this.tabActived !== this.actived) { if (this.tabActived !== this.actived) {
this.actived = this.tabActived; this.actived = this.tabActived;
} }
}, },
}, },
created() { created() {
this.actived = this.tabActived; this.actived = this.tabActived;
}, },
methods: { methods: {
onLoadContentWindow(key) { onLoadContentWindow(key) {
NProgress.start(); NProgress.start();
const pane = this.panes.find((p) => p.key === key); const pane = this.panes.find((p) => p.key === key);
// 打开之前先销毁 // 打开之前先销毁
const index = this.panes.indexOf(pane); const index = this.panes.indexOf(pane);
const component = this.$refs.panes && this.$refs.panes[index]; const component = this.$refs.panes && this.$refs.panes[index];
if (component) { if (component) {
component.$destroy(); component.$destroy();
} }
const i = import(`@/pages${pane.path}`); const i = import(`@/pages${pane.path}`);
pane.component = () => i; pane.component = () => i;
pane.loaded = false; pane.loaded = false;
i.then(() => { i.then(() => {
pane.loaded = true; pane.loaded = true;
NProgress.done(); NProgress.done();
}).catch(() => { }).catch(() => {
pane.component = () => import('@/views/error/404'); pane.component = () => import('@/views/error/404');
pane.loaded = true; pane.loaded = true;
NProgress.done(); NProgress.done();
}); });
}, },
onClose(targetKey, action) { onClose(targetKey, action) {
if (action === 'remove') { if (action === 'remove') {
this.$emit('close', targetKey); this.$emit('close', targetKey);
} }
}, },
onChange(activeKey) { onChange(activeKey) {
this.$emit('change', activeKey); this.$emit('change', activeKey);
}, },
onCopyComponent(pane) { onCopyComponent(pane) {
try { try {
const copy = document.createElement('textarea'); const copy = document.createElement('textarea');
document.body.append(copy); document.body.append(copy);
copy.value = `/pages${pane.path}`; copy.value = `/pages${pane.path}`;
copy.select(); copy.select();
setTimeout(() => { setTimeout(() => {
document.execCommand('copy'); document.execCommand('copy');
copy.remove(); copy.remove();
this.$message.success('已复制到剪切板'); this.$message.success('已复制到剪切板');
}); });
} catch { } catch {
this.$message.error('复制错误'); this.$message.error('复制错误');
} }
}, },
hasOther(pane) { hasOther(pane) {
return this.panes.filter((p) => p.key !== pane.key && p.closable).length > 0; return this.panes.filter((p) => p.key !== pane.key && p.closable).length > 0;
}, },
hasRight(pane) { hasRight(pane) {
return this.panes.length > this.panes.indexOf(pane) + 1; return this.panes.length > this.panes.indexOf(pane) + 1;
}, },
}, },
}; };
</script> </script>

View File

@@ -1,100 +1,100 @@
<template> <template>
<a-layout-header class="header"> <a-layout-header class="header">
<section <section
v-if="$root.global.settings.layout === 'left-menu' || $root.global.settings.layout === 'right-menu'" v-if="$root.global.settings.layout === 'left-menu' || $root.global.settings.layout === 'right-menu'"
> >
<div class="header-actions"> <div class="header-actions">
<a <a
@click="$root.global.settings.siderCollapsed = !$root.global.settings.siderCollapsed" @click="$root.global.settings.siderCollapsed = !$root.global.settings.siderCollapsed"
class="header-action" class="header-action"
> >
<a-icon :type="$root.global.settings.siderCollapsed ? 'menu-unfold' : 'menu-fold'" /> <a-icon :type="$root.global.settings.siderCollapsed ? 'menu-unfold' : 'menu-fold'" />
</a> </a>
<search :menus="nav.content" /> <search :menus="nav.content" />
</div> </div>
<div class="header-actions"> <div class="header-actions">
<User /> <User />
<a @click="$emit('reload')" class="header-action"> <a @click="$emit('reload')" class="header-action">
<a-icon type="reload" /> <a-icon type="reload" />
</a> </a>
<a class="header-action"> <a class="header-action">
<a-badge count="5"> <a-badge count="5">
<a-icon type="bell" /> <a-icon type="bell" />
</a-badge> </a-badge>
</a> </a>
<a @click="$emit('setting')" class="header-action"> <a @click="$emit('setting')" class="header-action">
<a-icon type="setting" /> <a-icon type="setting" />
</a> </a>
</div> </div>
</section> </section>
<container v-else-if="$root.global.settings.layout === 'top-nav'"> <container v-else-if="$root.global.settings.layout === 'top-nav'">
<div class="header-actions"> <div class="header-actions">
<a @click="showNav = !showNav" class="header-action mr-md"> <a @click="showNav = !showNav" class="header-action mr-md">
<a-icon type="menu" /> <a-icon type="menu" />
</a> </a>
<Logo /> <Logo />
<search :menus="nav.content" /> <search :menus="nav.content" />
</div> </div>
<div class="header-actions"> <div class="header-actions">
<User /> <User />
<a @click="$emit('reload')" class="header-action"> <a @click="$emit('reload')" class="header-action">
<a-icon type="reload" /> <a-icon type="reload" />
</a> </a>
<a class="header-action"> <a class="header-action">
<a-badge count="5"> <a-badge count="5">
<a-icon type="bell" /> <a-icon type="bell" />
</a-badge> </a-badge>
</a> </a>
<a @click="$emit('setting')" class="header-action"> <a @click="$emit('setting')" class="header-action">
<a-icon type="setting" /> <a-icon type="setting" />
</a> </a>
</div> </div>
<a-drawer <a-drawer
:body-style="{ padding: 0 }" :body-style="{ padding: 0 }"
:closable="false" :closable="false"
:get-container="'.ant-layout-content > .ant-tabs'" :get-container="'.ant-layout-content > .ant-tabs'"
:visible="showNav" :visible="showNav"
:wrap-style="{ position: 'absolute' }" :wrap-style="{ position: 'absolute' }"
@close="showNav = false" @close="showNav = false"
placement="left" placement="left"
width="38.2%" width="38.2%"
> >
<div @blur="showNav = false" @mouseleave="showNav = false"> <div @blur="showNav = false" @mouseleave="showNav = false">
<Nav :nav="nav" @open="showNav = false" /> <Nav :nav="nav" @open="showNav = false" />
</div> </div>
</a-drawer> </a-drawer>
</container> </container>
</a-layout-header> </a-layout-header>
</template> </template>
<script> <script>
import Logo from '../logo'; import Logo from '../logo';
import Nav from '../nav'; import Nav from '../nav';
import User from './user'; import User from './user';
import Search from './search'; import Search from './search';
export default { export default {
components: { components: {
Logo, Logo,
Nav, Nav,
User, User,
Search, Search,
}, },
props: { props: {
nav: { nav: {
default() { default() {
return { return {
content: [], content: [],
}; };
}, },
type: Object, type: Object,
}, },
}, },
data() { data() {
return { return {
showNav: false, showNav: false,
}; };
}, },
}; };
</script> </script>

View File

@@ -1,149 +1,149 @@
export default { export default {
props: { props: {
menus: { menus: {
type: Array, type: Array,
require: true require: true
} }
}, },
data() { data() {
return { return {
searchText: '', searchText: '',
searchResult: [], searchResult: [],
timer: null timer: null
}; };
}, },
methods: { methods: {
renderSelect(menu) { renderSelect(menu) {
return menu.map((p) => { return menu.map((p) => {
return p.children ? this.renderSelectGroup(p) : this.renderSelectOption(p) return p.children ? this.renderSelectGroup(p) : this.renderSelectOption(p)
}) })
}, },
renderSelectGroup(menu) { renderSelectGroup(menu) {
return ( return (
<a-select-opt-group key={menu.parents}> <a-select-opt-group key={menu.parents}>
<span slot="label"> <span slot="label">
{menu.parents} {menu.parents}
</span> </span>
{this.renderSelect(menu.children)} {this.renderSelect(menu.children)}
</a-select-opt-group> </a-select-opt-group>
) )
}, },
renderSelectOption(menu) { renderSelectOption(menu) {
return (<a-select-option key={menu.id} value={ return (<a-select-option key={menu.id} value={
JSON.stringify(menu) JSON.stringify(menu)
}> }>
{menu.meta.icon && <a-icon type={menu.meta.icon} />} {menu.meta.icon && <a-icon type={menu.meta.icon} />}
{menu.meta.title} {menu.meta.title}
<small style={{ display: 'block', color: '#aaa' }}>{menu.component}</small> <small style={{ display: 'block', color: '#aaa' }}>{menu.component}</small>
</a-select-option>) </a-select-option>)
}, },
onSearch(value) { onSearch(value) {
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
this.doSearch(value) this.doSearch(value)
}, 300) }, 300)
}, },
doSearch(value) { doSearch(value) {
this.searchText = value this.searchText = value
const menus = this.$_.concat.apply(this, this.$_.cloneDeep(this.menus.map(p => p.menu))) const menus = this.$_.concat.apply(this, this.$_.cloneDeep(this.menus.map(p => p.menu)))
const search = (m) => { const search = (m) => {
if (!value) return [] if (!value) return []
return m.filter((p) => { return m.filter((p) => {
if (p.children) { if (p.children) {
p.children = search(p.children) p.children = search(p.children)
} else { } else {
return p.meta.title.indexOf(value) > -1 || (p.component || '').toLowerCase().indexOf(value.toLowerCase()) > -1 return p.meta.title.indexOf(value) > -1 || (p.component || '').toLowerCase().indexOf(value.toLowerCase()) > -1
} }
return p.children.length return p.children.length
}) })
} }
/** /**
* 拆分层级,只留下 [父级-父级-...] [子级] * 拆分层级,只留下 [父级-父级-...] [子级]
* *******在更为复杂的目录下会出现父级联动错误的问题 * *******在更为复杂的目录下会出现父级联动错误的问题
*/ */
const unzip = (m) => { const unzip = (m) => {
const getSeed = (parent, seed) => { const getSeed = (parent, seed) => {
if (parent.children) { if (parent.children) {
seed.parents.push(parent.meta.title) seed.parents.push(parent.meta.title)
seed.children = parent.children seed.children = parent.children
parent.children.forEach(p => { parent.children.forEach(p => {
getSeed(p, seed) getSeed(p, seed)
}) })
} }
return seed return seed
} }
const result = [] const result = []
m.forEach(p => { m.forEach(p => {
const r = { parents: [], children: [] } const r = { parents: [], children: [] }
result.push(getSeed(p, r)) result.push(getSeed(p, r))
}) })
return result return result
} }
const result = unzip(search(menus)).filter(p => p.parents.length).map(p => { const result = unzip(search(menus)).filter(p => p.parents.length).map(p => {
return { return {
parents: p.parents.join('-'), parents: p.parents.join('-'),
children: p.children children: p.children
} }
}) })
this.searchResult = result this.searchResult = result
}, },
onSearchSelect(value, node) { onSearchSelect(value, node) {
this.searchText = ''; this.searchText = '';
this.onSearch(this.searchText); this.onSearch(this.searchText);
const menu = JSON.parse(node.componentOptions.propsData.value) const menu = JSON.parse(node.componentOptions.propsData.value)
this.openContentWindow({ this.openContentWindow({
key: menu.id, key: menu.id,
title: menu.meta.title, title: menu.meta.title,
icon: menu.meta.icon, icon: menu.meta.icon,
path: menu.component, path: menu.component,
}); });
}, },
}, },
render() { render() {
const props = { const props = {
dropdownMatchSelectWidth: false, dropdownMatchSelectWidth: false,
dropdownStyle: { width: '300px' }, dropdownStyle: { width: '300px' },
optionLabelProp: 'value', optionLabelProp: 'value',
placeholder: '请输入检索关键字', placeholder: '请输入检索关键字',
value: this.searchText value: this.searchText
} }
const on = { const on = {
search: this.onSearch, search: this.onSearch,
select: this.onSearchSelect select: this.onSearchSelect
} }
return ( return (
<a-auto-complete {...{ props, on }}> <a-auto-complete {...{ props, on }}>
<template slot="dataSource"> <template slot="dataSource">
{this.renderSelect(this.searchResult)} {this.renderSelect(this.searchResult)}
</template> </template>
<a-input allow-clear> <a-input allow-clear>
<a-icon slot="suffix" type="search" class="certain-category-icon" /> <a-icon slot="suffix" type="search" class="certain-category-icon" />
</a-input> </a-input>
</a-auto-complete> </a-auto-complete>
) )
} }
} }

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