为什么都没了

This commit is contained in:
路 范
2021-09-24 12:59:34 +08:00
parent a975b3bdee
commit a66921f0f4
962 changed files with 252792 additions and 0 deletions

26
framework/Web/src/App.vue Normal file
View File

@@ -0,0 +1,26 @@
<template>
<div id="app">
<a-config-provider :locale="zh_CN">
<template #renderEmpty>
<div class="text-center pt-md">
<a-icon class="h3 mb-md" type="smile" />
<p>暂无数据</p>
</div>
</template>
<router-view />
</a-config-provider>
</div>
</template>
<script>
import zh_CN from 'ant-design-vue/es/locale/zh_CN';
export default {
name: 'App',
data() {
return {
zh_CN,
};
},
};
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

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

View File

@@ -0,0 +1,6 @@
@import '~ant-design-vue/dist/antd.less';
@padding-xxs: 4px;
@padding-xl: 32px;
body {
line-height: 1.42857143;
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,11 @@
@import (reference) '~@/assets/style/extend.less';
.ant-anchor-ink-ball {
width: 2px;
height: 28px;
transform: translate(-50%, -10px);
border: 0;
border-radius: 0;
background-color: @primary-color;
}

View File

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

View File

@@ -0,0 +1,5 @@
@import (reference) '~@/assets/style/extend.less';
@btn-default-border: @border-color-split;
.ant-btn {
box-shadow: none;
}

View File

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

View File

@@ -0,0 +1,6 @@
@import (reference) '~@/assets/style/extend.less';
.ant-cascader-picker-arrow {
svg {
transform: scaleY(.75);
}
}

View File

@@ -0,0 +1,10 @@
@import (reference) '~@/assets/style/extend.less';
.ant-checkbox-wrapper {
margin-right: @padding-xs;
&:last-child {
margin-right: 0;
}
+.ant-checkbox-wrapper {
margin-left: 0;
}
}

View File

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

View File

@@ -0,0 +1,10 @@
@import (reference) '~@/assets/style/extend.less';
.ant-descriptions-bordered {
.ant-descriptions-view {
>table {
border-collapse: collapse;
background-color: @white;
}
}
}

View File

@@ -0,0 +1,36 @@
@import (reference) '~@/assets/style/extend.less';
.ant-btn-primary-disabled,
.ant-btn-primary.disabled,
.ant-btn-primary[disabled],
.ant-btn-primary-disabled:hover,
.ant-btn-primary.disabled:hover,
.ant-btn-primary[disabled]:hover,
.ant-btn-primary-disabled:focus,
.ant-btn-primary.disabled:focus,
.ant-btn-primary[disabled]:focus,
.ant-btn-primary-disabled:active,
.ant-btn-primary.disabled:active,
.ant-btn-primary[disabled]:active,
.ant-btn-primary-disabled.active,
.ant-btn-primary.disabled.active,
.ant-btn-primary[disabled].active {
opacity: .5;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
box-shadow: @btn-primary-shadow;
text-shadow: @btn-text-shadow;
}
.ant-radio-button-wrapper-disabled:first-child,
.ant-radio-button-wrapper-disabled:hover {
opacity: .5;
color: @radio-button-color;
background-color: @radio-button-bg;
}
.ant-radio-button-wrapper-disabled.ant-radio-button-wrapper-checked {
opacity: .5;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
box-shadow: @btn-primary-shadow;
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,168 @@
@import (reference) '~@/assets/style/extend.less';
.yo-form-page {
position: relative;
height: 100%;
.yo-tab-external-mount {
display: flex;
flex-direction: column;
height: 100%;
>.ant-tabs {
>.ant-tabs-bar {
margin-bottom: 0;
background-color: @white;
&.ant-tabs-card-bar {
.ant-tabs-nav-container {
height: @tabs-card-height + @padding-xs;
padding: (@tabs-card-height + @padding-xs - @btn-height-base) / 2 @padding-md;
}
.ant-tabs-extra-content {
padding: (@tabs-card-height + @padding-xs - @btn-height-base) / 2 @padding-md;
}
.ant-tabs-tab {
transition: none;
.ant-btn();
&:hover {
border-color: @btn-default-border;
}
}
.ant-tabs-tab {
line-height: @btn-height-base;
margin-right: -1px;
}
.ant-tabs-tab-active {
z-index: 2;
color: @btn-primary-color;
border-color: @btn-primary-bg;
background-color: @btn-primary-bg;
&:hover {
color: @btn-primary-color;
border-color: color(~`colorPalette('@{btn-primary-bg}', 5) `);
background-color: color(~`colorPalette('@{btn-primary-bg}', 5) `);
}
}
}
}
}
>.yo-tab-external-mount-content {
position: relative;
flex: 1;
>.yo-tab-external-tabpane {
position: absolute;
top: 0;
left: 0;
overflow: auto;
width: 100%;
height: 100%;
&.yo-tab-external-tabpane-inactive {
pointer-events: none;
opacity: 0;
}
}
}
}
&--bar {
position: sticky;
bottom: 0;
z-index: 200;
&--with-tab {
position: absolute;
display: flex;
align-items: flex-end;
width: 100%;
height: 0;
padding-right: 7px;
>.container-fluid {
width: 100%;
}
~.yo-tab-external-mount {
>.yo-tab-external-mount-content {
>.yo-tab-external-tabpane {
padding-bottom: @padding-xs * 2 + @btn-height-base + @border-width-base * 2;
}
}
}
}
}
&--bar-inner {
display: flex;
justify-content: space-between;
padding: @padding-xs @padding-md;
border: @border-width-base @border-style-base @border-color-split;
background-color: fade(@white, 80%);
backdrop-filter: blur(5px);
>:first-child {
flex: 1;
}
.ant-btn {
margin-left: @padding-sm;
}
}
&--body {
>.ant-card-body {
padding: 0;
>section {
padding: @padding-lg;
>h5 {
padding-left: @padding-md;
border-left: @padding-xs @border-style-base @primary-color;
}
}
}
}
&-layout {
display: flex;
flex-direction: column;
height: 100%;
&--horizontal {
flex-direction: row;
}
}
&--header {
padding: @padding-md 0;
background-color: @white;
}
}

View File

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

View File

@@ -0,0 +1,60 @@
@import (reference) '~@/assets/style/extend.less';
.yo-icon-selector {
.ant-drawer-wrapper-body {
display: flex;
flex-direction: column;
}
.ant-drawer-body {
position: relative;
flex: 1 1 100%;
padding: 0;
}
.ant-tabs {
height: 100%;
.ant-tabs-left-content {
position: relative;
height: 100%;
padding: 0;
.ant-tabs-tabpane {
position: absolute;
top: 0;
left: 0;
overflow-y: auto;
width: 100%;
height: 100%;
padding: @padding-lg;
}
}
}
.ant-card {
margin: 0;
}
.ant-card-grid {
width: 25%;
text-align: center;
>span {
font-size: @font-size-sm;
display: block;
margin: @padding-xxs -@padding-lg 0;
white-space: nowrap;
color: fade(@black, 50%);
}
&.yo-icon--selected {
color: @white;
background-color: @primary-color;
>span {
color: fade(@white, 50%);
}
}
}
}

View File

@@ -0,0 +1,10 @@
@import (reference) '~@/assets/style/extend.less';
/* input前缀有2个字符的 */
.yo-input-prefix-2 {
.ant-input:not(:first-child) {
padding-left: 45px;
}
}
.yo-addon {
padding: 0 @padding-xs;
}

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
@import (reference) '~@/assets/style/extend.less';
.ant-modal-content {
background-color: fade(@white, 90%);
backdrop-filter: blur(5px);
}
.ant-modal-header {
padding: @padding-sm @padding-md;
background-color: transparent;
}
.ant-modal-body {
background-color: @white;
}
.ant-modal-footer {
background-color: @white;
}
.ant-modal-close-x {
line-height: 46px;
width: 46px;
height: 46px;
}

View File

@@ -0,0 +1,8 @@
@import (reference) '~@/assets/style/extend.less';
.yo-page {
&--header {
padding: @padding-md 0;
background-color: @white;
}
}

View File

@@ -0,0 +1,7 @@
@import (reference) '~@/assets/style/extend.less';
.ant-radio-button-wrapper-checked {
&:not(.ant-radio-button-wrapper-disabled),
&:not(.ant-radio-button-wrapper-disabled):hover {
box-shadow: none;
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,32 @@
@import (reference) '~@/assets/style/extend.less';
.text-primary {
color: @primary-color;
}
.text-info {
color: @info-color;
}
.text-success {
color: @success-color;
}
.text-processing {
color: @processing-color;
}
.text-error,
.text-danger {
color: @error-color;
}
.text-highlight {
color: @highlight-color;
}
.text-warning {
color: @warning-color;
}
.text-normal {
color: @normal-color;
}
.text-white {
color: @white;
}
.text-black {
color: @black;
}

View File

@@ -0,0 +1,72 @@
@import (reference) '~@/assets/style/extend.less';
.yo-tree-layout {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.ant-layout-sider {
background-color: @white;
.ant-layout-header {
height: @layout-header-height - 20px;
background-color: @white;
.header-actions {
>.ant-input-search {
.ant-input {
color: @black;
background-color: @white;
&:focus {
background-color: fade(@black, 5%);
}
}
.anticon-search {
color: fade(@black, 45%);
}
}
}
}
}
&--bar {
line-height: 20px;
height: 20px;
padding: 0 @padding-md;
text-align: right;
>.anticon {
cursor: pointer;
color: fade(@black, 50%);
&:hover {
color: fade(@black, 80%);
}
}
}
&--content {
position: absolute;
top: @layout-header-height;
left: 0;
bottom: 0;
overflow-y: auto;
width: 100%;
&::-webkit-scrollbar {
width: 5px;
height: 5px;
background-color: @white;
}
&::-webkit-scrollbar-thumb {
background-color: transparent;
}
&:hover::-webkit-scrollbar-thumb {
background-color: fade(@black, 30%);
}
&::-webkit-scrollbar-thumb:active {
background-color: fade(@black, 45%);
}
}
}

View File

@@ -0,0 +1,29 @@
@import (reference) '~@/assets/style/extend.less';
.ant-upload-list-text {
display: flex;
flex-wrap: wrap;
.ant-upload-list-item {
height: auto;
margin-right: @padding-xs;
}
.ant-upload-list-item-info {
position: relative;
padding: @padding-xxs @padding-xs;
border: @border-width-base @border-style-base @border-color-split;
.anticon-paper-clip {
top: 7.5px;
}
>span {
display: flex;
}
}
.ant-upload-list-item-card-actions {
position: relative;
margin-left: @padding-xs;
white-space: nowrap;
}
}

View File

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

View File

@@ -0,0 +1,30 @@
@import (reference) '~@/assets/style/extend.less';
.width-height (@i) when (@i <=20) {
@n : @i * 50;
.w-@{n} {
width: @n * 1px !important;
}
.h-@{n} {
height: @n * 1px !important;
}
.w-@{n}-p {
width: @n * 1% !important;
}
.h-@{n}-p {
height: @n * 1% !important;
}
.width-height(@i + 1);
}
.width-height(0);
.flex-1 {
flex: 1;
}

View File

@@ -0,0 +1,77 @@
@import (reference) './app.less';
.yo-login {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
>img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
&::before {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
background: fade(@black, 30%) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABZJREFUeNpiMLJ0+w8EDIwgAgQAAgwAUdAHrAFSJ6cAAAAASUVORK5CYII=);
}
&--placeholder {
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 0;
.container-sm {
display: flex;
align-items: center;
justify-content: flex-end;
height: 0;
}
}
.ant-form {
width: 300px;
padding: @padding-lg;
border-radius: @border-radius-base + 2px;
background: linear-gradient(45deg, @white, fade(@white, 80%));
}
.ant-form-item {
margin-bottom: 0;
}
/deep/.ant-form-item-label {
transition: @animation-duration-base;
transform: translate(0);
>label {
color: fade(@black, 40%);
}
}
&--label {
/deep/.ant-form-item-label {
transform: translate(11px, 28px);
}
}
/deep/.ant-input {
border-width: 0 0 @border-width-base 0 !important;
border-color: fade(@black, 10%);
background-color: transparent;
}
/deep/.ant-input:hover,
/deep/.ant-input:focus {
border-width: 0 0 @border-width-base 0 !important;
border-color: @primary-color;
box-shadow: none;
}
}

View File

@@ -0,0 +1,602 @@
@import (reference) './extend.less';
@import (reference) './lib/container.less';
.main(@nav-background: @layout-header-background,
@nav-box-shadow-color: fade(@black, 25%),
@nav-scrollbar-background: fade(@white, 30%),
@nav-app-color: fade(@white, 35%),
@logo-color: @white,
@logo-box-shadow: none,
@header-action-color: fade(@white, 60%),
@header-action-hover-color: @white,
@header-action-hover-background: fade(@white, 20%),
@header-search-color: @white,
@header-search-background: fade(@white, 15%),
@header-search-focus-background: fade(@white, 30%),
@header-search-icon-color: fade(@white, 60%),
@header-search-icon-hover-color: @white,
) {
.yo-layout--spin {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
>div>.ant-spin {
max-height: none;
}
>.ant-spin-container {
width: 100%;
height: 100%;
}
}
.ant-layout-header {
.header-actions {
display: flex;
.header-action {
display: inline-block;
padding: 0 @padding-md;
cursor: pointer;
transition: @animation-duration-slow;
transition-property: background-color;
.anticon {
font-size: @font-size-base + 6px;
transition: @animation-duration-slow;
transition-property: color;
}
&:active {
box-shadow: inset 1px 1px 10px rgba(0, 0, 0, .05);
}
}
>.ant-input-search,
>.ant-select-auto-complete {
display: flex;
align-items: center;
margin: 5px @padding-md;
.ant-input {
height: 34px;
padding: 5px 30px 5px 11px;
transition: @animation-duration-slow;
transition-property: background-color;
border-color: transparent;
&:focus {
box-shadow: none;
}
}
.ant-select-selection {
background-color: transparent;
}
}
}
.user-container {
z-index: 10;
width: 32px + @padding-sm * 2;
height: @layout-header-height - 24px;
margin: 2px 0;
transition: @animation-duration-slow;
.user-container-inner {
position: relative;
transition: @animation-duration-slow;
border-radius: @border-radius-base;
}
.user {
&--base {
line-height: @layout-header-height - 24px;
position: relative;
display: flex;
overflow: hidden;
align-items: center;
width: 100%;
height: @layout-header-height - 24px;
padding: 0 @padding-sm;
transition: @animation-duration-slow;
}
&--avatar {
box-shadow: 0 0 0 2px @white;
}
&--name {
font-weight: bolder;
position: absolute;
left: 32px + @padding-sm * 2;
transition: @animation-duration-slow;
opacity: 0;
}
&--dropdown {
width: 200px;
transition: @animation-duration-base;
transform: scaleY(0);
transform-origin: top;
opacity: 0;
.ant-dropdown-menu {
box-shadow: none;
}
}
}
&.open {
width: 200px;
.user-container-inner {
background-color: @white;
box-shadow: @box-shadow-base;
}
.user {
&--name {
opacity: 1;
}
}
}
&.drop {
.user {
&--dropdown {
transform: scaleY(1);
opacity: 1;
}
}
}
}
}
.ant-layout-content {
position: relative;
>.yo-tab-external-mount {
position: absolute;
top: 0;
left: 0;
bottom: 0;
display: flex;
flex-direction: column;
width: 100%;
>.ant-tabs {
z-index: 5;
overflow: visible;
>.ant-tabs-bar {
margin-bottom: 0;
border-bottom: 0;
background-color: @white;
box-shadow: 0 2px 12px fade(@black, 8%);
&::before {
content: none;
}
.ant-tabs-nav-container {
height: 30px;
margin-bottom: 0;
}
.ant-tabs-tab {
line-height: 30px;
height: 30px;
margin-right: 0;
padding: 0;
transition: none;
border: 0;
background-color: transparent;
&:hover {
color: @black;
}
&.ant-tabs-tab-active {
color: @white;
border-color: darken(@primary-color, 10%);
background-color: @primary-color;
.ant-tabs-close-x {
color: fade(@white, 70%);
&:hover {
color: @white;
}
}
}
.yo-layout-tab-subtitle {
line-height: 1;
display: inline-block;
overflow: hidden;
max-width: 150px;
transform: translateY(1px);
white-space: nowrap;
text-overflow: ellipsis;
opacity: .75;
}
+.ant-tabs-tab {
margin-left: 0;
}
.ant-dropdown-trigger {
padding: 0 @padding-md * 2 0 @padding-md;
}
.ant-tabs-tab-unclosable {
.ant-dropdown-trigger {
padding: 0 @padding-lg 0 @padding-md;
}
}
.ant-tabs-close-x {
position: absolute;
top: 9px;
right: 9px;
margin: 0;
transition: none;
}
}
}
}
>.yo-tab-external-mount-content {
position: relative;
height: 100%;
>.yo-tab-external-tabpane {
position: absolute;
top: 0;
left: 0;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: 100%;
&.yo-tab-external-tabpane-inactive {
pointer-events: none;
opacity: 0;
}
}
}
}
}
.ant-layout-sider {
.ant-menu-inline {
border-right: 0;
}
}
.yo-nav {
padding-top: @padding-lg;
padding-bottom: @padding-lg;
&--row {
padding: 1px 0;
column-gap: @padding-md;
column-count: 3;
}
&--col {
break-inside: avoid;
}
&--sub-item {
}
&--item-group {
font-size: @font-size-base;
line-height: 1.5;
margin-bottom: @padding-xs;
padding-top: @padding-xs * 2;
color: fade(@black, 35%);
border: @border-width-base @border-style-base transparent;
}
&--item {
font-size: @font-size-base;
line-height: 1.5;
position: relative;
margin-bottom: @padding-xs;
padding: @padding-xs @padding-sm;
cursor: pointer;
transition: @animation-duration-fast;
border: @border-width-base @border-style-base @border-color-split;
border-radius: @border-radius-base;
background-color: @white;
&:hover {
color: @white;
border-color: @primary-color;
background-color: @primary-color;
}
}
}
.yo-layout-sider {
height: 100%;
background-color: @nav-background;
.ant-layout-sider-children {
display: flex;
flex-direction: column;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height + 10px;
z-index: 11;
display: flex;
overflow: hidden;
align-items: center;
flex: 0 0 @layout-header-height + 10px;
height: @layout-header-height + 10px;
padding: 0 @padding-md 0 @padding-lg;
color: @logo-color;
box-shadow: @logo-box-shadow;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
transition: @animation-duration-slow;
transition-property: opacity;
}
}
&.ant-layout-sider-collapsed {
.logo {
span {
opacity: 0;
}
}
}
.yo-sider-nav {
position: relative;
z-index: 10;
flex: 1 1 100%;
box-shadow: 2px 0 8px @nav-box-shadow-color;
&--app {
font-size: @font-size-sm;
margin-top: @padding-sm;
padding: 0 @padding-md;
color: @nav-app-color;
}
}
.swiper-container {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
.swiper-scrollbar {
transition: @animation-duration-slow;
transition-property: opacity;
opacity: 0;
}
.swiper-scrollbar-drag {
background-color: @nav-scrollbar-background;
}
&:hover {
.swiper-scrollbar {
opacity: 1;
}
}
}
.swiper-slide {
height: auto;
min-height: 100%;
>.ant-spin-nested-loading {
height: 100%;
.ant-spin-blur {
&::after {
opacity: 0;
}
}
}
}
}
.yo-layout--left-menu,
.yo-layout--right-menu {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.ant-layout-header {
line-height: @layout-header-height - 20px;
z-index: 6;
height: @layout-header-height - 20px;
padding: 0;
background-color: @white;
>section {
display: flex;
justify-content: space-between;
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
height: @layout-header-height - 20px;
.anticon {
color: fade(@black, 35%);
}
&:hover {
background-color: fade(@black, 5%);
.anticon {
color: @icon-color-hover;
}
}
}
>.ant-input-search,
>.ant-select-auto-complete {
.ant-input {
&:focus {
background-color: fade(@black, 5%);
}
}
}
}
}
.layout-sider {
}
>section {
>.ant-layout-sider {
.yo-layout-sider();
}
}
}
.yo-layout--top-nav {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
width: 100%;
min-width: @container-width;
height: 100%;
@layout-header-height: 54px;
.ant-layout-header {
line-height: @layout-header-height;
z-index: 11;
flex: 0 0 @layout-header-height;
height: @layout-header-height;
padding: 0;
background-color: @nav-background;
section {
display: flex;
justify-content: space-between;
height: 100%;
}
.header-actions {
.header-action {
.anticon {
color: @header-action-color;
}
&:hover {
background-color: @header-action-hover-background;
.anticon {
color: @header-action-hover-color;
}
}
}
>.ant-input-search,
>.ant-select-auto-complete {
.ant-input {
color: @header-search-color;
background-color: @header-search-background;
&:focus {
background-color: @header-search-focus-background;
}
}
.anticon-search {
color: @header-search-icon-color;
&:hover {
color: @header-search-icon-hover-color;
}
}
}
}
.user-container {
margin: (@layout-header-height - 40px) / 2 0;
}
.logo {
font-size: @font-size-lg * 1.5;
font-weight: 500;
line-height: @layout-header-height - 10px;
display: flex;
overflow: hidden;
align-items: center;
height: @layout-header-height 10px;
margin: 5px @padding-lg 5px 0;
color: @logo-color;
img {
max-height: 100%;
}
span {
margin-left: @padding-sm;
}
}
.ant-menu-horizontal {
line-height: @layout-header-height;
border-bottom: 0;
>.ant-menu-submenu {
top: 0;
border-bottom: 0;
}
}
.header-actions {
.header-action {
line-height: @layout-header-height - 16px;
margin: 10px 0;
}
}
}
&--container {
.ant-layout-header {
.ant-menu-horizontal {
width: 400px;
}
}
.ant-layout-content {
.yo-tab-external-mount {
>.ant-tabs {
>.ant-tabs-bar {
.ant-tabs-nav-container {
width: @container-width - @padding-md * 2;
margin: 0 auto;
}
}
}
}
}
}
&--container-fluid {
.ant-layout-header {
.ant-menu-horizontal {
width: 800px;
}
@media (max-width: 1400px) {
.ant-menu-horizontal {
width: 600px;
}
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
@import (reference) './extend.less';
.yo-map {
&-container {
position: relative;
padding: @padding-sm;
border: @border-width-base @border-style-base @border-color-split;
border-radius: @border-radius-base;
background-color: @white;
.amap-icon {
img {
width: 25px;
}
}
}
&--search {
position: absolute;
top: @padding-md;
left: @padding-md;
z-index: 20;
width: 25%;
min-width: 300px;
padding: @padding-xxs @padding-sm;
background: fade(@black, 20%);
box-shadow: @box-shadow-base;
backdrop-filter: blur(5px);
}
}

View File

@@ -0,0 +1 @@
/** 在此文件夹中添加控制主题颜色的less文件 **/

View File

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

View File

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

View File

@@ -0,0 +1,6 @@
export default {
houseCodeAdd: ['/houseCode/add', 'post'],
houseCodeEdit: ['/houseCode/edit', 'post'],
houseCodePage: ['/houseCode/page', 'post'],
houseCodeNo: '/houseCode/getNextNoByCode',
}

View File

@@ -0,0 +1,5 @@
export default {
houseInfoGetByTaskId: ['/houseInfo/getByTaskId', 'get'],
houseInfoSave: ['houseInfo/save', 'post'],
houseInfoSubmitToCheck: ['/houseInfo/submitToCheck', 'post']
}

View File

@@ -0,0 +1,12 @@
export default {
houseMemberPage: ['/houseMember/page', 'post'],
houseMemberAdd: ['/houseMember/add', 'post'],
houseMemberEdit: ['/houseMember/edit', 'post'],
houseMemberDelete: ['/houseMember/delete', 'post'],
houseMemberOwnRole: ['/houseMember/ownRole', 'get'],
houseMemberOwnData: ['/houseMember/ownData', 'get'],
houseMemberGrantData: ['/houseMember/grantData', 'post'],
houseMemberChangeStatus: ['/houseMember/changeStatus', 'post'],
houseMemberDefaultRole: ['/houseMember/defaultRole', 'get'],
houseMemberDefaultRoleList: ['/houseMember/defaultRoleRange', 'get']
}

View File

@@ -0,0 +1,9 @@
export default {
getHouseProjectPage: ['/houseProjectInfo/page', 'post'],
houseProejctAdd: ['/houseProjectInfo/add', 'post'],
houseProejctEdit: ['/houseProjectInfo/edit', 'post'],
houseProejctDelete: ['/houseProjectInfo/delete', 'post'],
houseProejctDetail: ['/houseProjectInfo/detail', 'get'],
houseProjectNextSort: ['/houseProjectInfo/nextSort', 'get'],
houseProjectList: ['houseProjectInfo/list', 'get']
}

View File

@@ -0,0 +1,6 @@
export default {
houseSelect: ['/houseSelector/select', 'post'],
houseSelectRevoke: ['/houseSelector/revoke', 'post'],
houseSelectorPage: ['/houseSelector/selectorPage', 'post'],
houseSelectedPage: ['/houseSelector/selectedPage', 'post'],
}

View File

@@ -0,0 +1,5 @@
export default {
houseTaskPage: ['/houseTask/page', 'post'],
houseTaskEdit: ['/houseTask/edit', 'post'],
houseTaskSubmit: ['/houseTask/submit', 'post']
}

View File

@@ -0,0 +1,5 @@
export default {
houseZoneList: '/houseZone/list',
houseZoneAutoIncrement: '/houseZone/autoIncrement',
houseZoneAdd: ['/houseZone/add', 'post']
}

View File

@@ -0,0 +1,17 @@
import houseProjectInfo from './houseProjectInfo'
import houseZone from './houseZone'
import houseCode from './houseCode'
import houseMember from './houseMember'
import houseSelector from './houseSelector'
import houseTask from './houseTask'
import houseInfo from './houseInfo'
export default {
...houseProjectInfo,
...houseZone,
...houseCode,
...houseMember,
...houseSelector,
...houseTask,
...houseInfo
}

View File

@@ -0,0 +1,5 @@
import houseSafety from './houseSafety'
export default {
...houseSafety,
}

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
export default {
getAreaTree: ['/sysArea/tree', 'get'],
sysAreaPage: ['/sysArea/page', 'post'],
sysAreaAdd: ['/sysArea/add', 'post'],
sysAreaEdit: ['/sysArea/edit', 'post'],
sysAreaDelete: ['/sysArea/delete', 'post'],
}

View File

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

View File

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

View File

@@ -0,0 +1,30 @@
export default {
/**
* 分页查询系统字典类型
*/
sysDictTypePage: ['/sysDictType/page', 'post'],
/**
* 添加系统字典类型
*/
sysDictTypeAdd: ['/sysDictType/add', 'post'],
/**
* 编辑系统字典类型
*/
sysDictTypeEdit: ['/sysDictType/edit', 'post'],
/**
* 删除系统字典类型
*/
sysDictTypeDelete: ['/sysDictType/delete', 'post'],
/**
* 获取字典类型下所有字典,举例,返回格式为:[{code:"M",value:"男"},{code:"F",value:"女"}]
*/
sysDictTypeDropDown: ['/sysDictType/dropDown', 'get'],
/**
* 获取字典类型下所有的字典,可批量获取
*/
sysDictTypeDropDowns: ['/sysDictType/dropDowns', 'get'],
/**
* 获取所有字典树
*/
sysDictTypeTree: ['/sysDictType/tree', 'get'],
}

View File

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

View File

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

View File

@@ -0,0 +1,43 @@
import appManage from './appManage'
import configManage from './configManage'
import dictDataManage from './dictDataManage'
import dictManage from './dictManage'
import emailManage from './emailManage'
import fileManage from './fileManage'
import loginManage from './loginManage'
import logManage from './logManage'
import machineManage from './machineManage'
import menuManage from './menuManage'
import noticeManage from './noticeManage'
import onlineUserManage from './onlineUserManage'
import orgManage from './orgManage'
import posManage from './posManage'
import roleManage from './roleManage'
import smsManage from './smsManage'
import tenantManage from './tenantManage'
import timersManage from './timersManage'
import userManage from './userManage'
import areaManage from './areaManage'
export default {
...appManage,
...configManage,
...dictDataManage,
...dictManage,
...emailManage,
...fileManage,
...loginManage,
...logManage,
...machineManage,
...menuManage,
...noticeManage,
...onlineUserManage,
...orgManage,
...posManage,
...roleManage,
...smsManage,
...tenantManage,
...timersManage,
...userManage,
...areaManage,
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,10 @@
const SESSION_KEY = '__SESSION'
const SETTING_KEY = '__SETTINGS'
const GLOBAL_INFO_KEY = '__GLOBAL_INFO'
const COUNT_DWON_KEY = '__COUNT_DWON'
export {
SESSION_KEY,
SETTING_KEY,
GLOBAL_INFO_KEY,
COUNT_DWON_KEY
}

View File

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

View File

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

View File

@@ -0,0 +1,23 @@
<template>
<section
:class="{
[mode || $root.global.settings.container || 'container-fluid']: true,
'container-flex': flex
}"
>
<slot />
</section>
</template>
<script>
export default {
props: {
mode: {
type: String,
},
flex: {
type: Boolean,
default: false,
},
},
};
</script>

View File

@@ -0,0 +1,56 @@
<template>
<div aria-hidden="true" class="pswp" role="dialog" tabindex="-1">
<div class="pswp__bg"></div>
<div class="pswp__scroll-wrap">
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import 'photoswipe/dist/photoswipe.css';
import 'photoswipe/dist/default-skin/default-skin.css';
import PhotoSwipe from 'photoswipe';
import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default';
const defaultOptions = {
index: 0,
bgOpacity: 0.75,
};
export default {
methods: {
initPhotoSwipe(items = [], options) {
const pswpElement = this.$el;
const gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, Object.assign(defaultOptions, options));
gallery.init();
},
},
};
</script>

View File

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

View File

@@ -0,0 +1,26 @@
export default {
props: {
title: {
type: [String, Number],
default: ''
},
content: {
type: [String, Number],
default: ''
}
},
render() {
return (
<div class="yo-form-link">
<div class="yo-form-link--title">
{this.$scopedSlots.default ? this.$scopedSlots.default() : this.title}
</div>
<div class="yo-form-link--content">
{this.$scopedSlots.content ? this.$scopedSlots.content() : this.content}
</div>
<a-icon type="right" class="yo-form-link--right-icon" />
</div>
)
}
}

View File

@@ -0,0 +1,32 @@
export default [
{
key: 'directional',
title: '方向性图标',
icons: ['step-backward', 'step-forward', 'fast-backward', 'fast-forward', 'shrink', 'arrows-alt', 'down', 'up', 'left', 'right', 'caret-up', 'caret-down', 'caret-left', 'caret-right', 'up-circle', 'down-circle', 'left-circle', 'right-circle', 'double-right', 'double-left', 'vertical-left', 'vertical-right', 'forward', 'backward', 'rollback', 'enter', 'retweet', 'swap', 'swap-left', 'swap-right', 'arrow-up', 'arrow-down', 'arrow-left', 'arrow-right', 'play-circle', 'up-square', 'down-square', 'left-square', 'right-square', 'login', 'logout', 'menu-fold', 'menu-unfold', 'border-bottom', 'border-horizontal', 'border-inner', 'border-left', 'border-right', 'border-top', 'border-verticle', 'pic-center', 'pic-left', 'pic-right', 'radius-bottomleft', 'radius-bottomright', 'radius-upleft', 'fullscreen', 'fullscreen-exit']
},
{
key: 'suggested',
title: '提示建议性图标',
icons: ['question', 'question-circle', 'plus', 'plus-circle', 'pause', 'pause-circle', 'minus', 'minus-circle', 'plus-square', 'minus-square', 'info', 'info-circle', 'exclamation', 'exclamation-circle', 'close', 'close-circle', 'close-square', 'check', 'check-circle', 'check-square', 'clock-circle', 'warning', 'issues-close', 'stop']
},
{
key: 'editor',
title: '编辑类图标',
icons: ['edit', 'form', 'copy', 'scissor', 'delete', 'snippets', 'diff', 'highlight', 'align-center', 'align-left', 'align-right', 'bg-colors', 'bold', 'italic', 'underline', 'strikethrough', 'redo', 'undo', 'zoom-in', 'zoom-out', 'font-colors', 'font-size', 'line-height', 'column-height', 'dash', 'small-dash', 'sort-ascending', 'sort-descending', 'drag', 'ordered-list', 'radius-setting']
},
{
key: 'data',
title: '数据类图标',
icons: ['area-chart', 'pie-chart', 'bar-chart', 'dot-chart', 'line-chart', 'radar-chart', 'heat-map', 'fall', 'rise', 'stock', 'box-plot', 'fund', 'sliders']
},
{
key: 'brand_logo',
title: '网站通用图标',
icons: ['lock', 'unlock', 'bars', 'book', 'calendar', 'cloud', 'cloud-download', 'code', 'copy', 'credit-card', 'delete', 'desktop', 'download', 'ellipsis', 'file', 'file-text', 'file-unknown', 'file-pdf', 'file-word', 'file-excel', 'file-jpg', 'file-ppt', 'file-markdown', 'file-add', 'folder', 'folder-open', 'folder-add', 'hdd', 'frown', 'meh', 'smile', 'inbox', 'laptop', 'appstore', 'link', 'mail', 'mobile', 'notification', 'paper-clip', 'picture', 'poweroff', 'reload', 'search', 'setting', 'share-alt', 'shopping-cart', 'tablet', 'tag', 'tags', 'to-top', 'upload', 'user', 'video-camera', 'home', 'loading', 'loading-3-quarters', 'cloud-upload', 'star', 'heart', 'environment', 'eye', 'camera', 'save', 'team', 'solution', 'phone', 'filter', 'exception', 'export', 'customer-service', 'qrcode', 'scan', 'like', 'dislike', 'message', 'pay-circle', 'calculator', 'pushpin', 'bulb', 'select', 'switcher', 'rocket', 'bell', 'disconnect', 'database', 'compass', 'barcode', 'hourglass', 'key', 'flag', 'layout', 'printer', 'sound', 'usb', 'skin', 'tool', 'sync', 'wifi', 'car', 'schedule', 'user-add', 'user-delete', 'usergroup-add', 'usergroup-delete', 'man', 'woman', 'shop', 'gift', 'idcard', 'medicine-box', 'red-envelope', 'coffee', 'copyright', 'trademark', 'safety', 'wallet', 'bank', 'trophy', 'contacts', 'global', 'shake', 'api', 'fork', 'dashboard', 'table', 'profile', 'alert', 'audit', 'branches', 'build', 'border', 'crown', 'experiment', 'fire', 'money-collect', 'property-safety', 'read', 'reconciliation', 'rest', 'security-scan', 'insurance', 'interaction', 'safety-certificate', 'project', 'thunderbolt', 'block', 'cluster', 'deployment-unit', 'dollar', 'euro', 'pound', 'file-done', 'file-exclamation', 'file-protect', 'file-search', 'file-sync', 'gateway', 'gold', 'robot', 'shopping']
},
{
key: 'application',
title: '品牌和标识',
icons: ['android', 'apple', 'windows', 'ie', 'chrome', 'github', 'aliwangwang', 'dingding', 'weibo-square', 'weibo-circle', 'taobao-circle', 'html5', 'weibo', 'twitter', 'wechat', 'youtube', 'alipay-circle', 'taobao', 'skype', 'qq', 'medium-workmark', 'gitlab', 'medium', 'linkedin', 'google-plus', 'dropbox', 'facebook', 'codepen', 'code-sandbox', 'amazon', 'google', 'codepen-circle', 'alipay', 'ant-design', 'aliyun', 'zhihu', 'slack', 'slack-square', 'behance', 'behance-square', 'dribbble', 'dribbble-square', 'instagram', 'yuque', 'alibaba', 'yahoo']
}
]

View File

@@ -0,0 +1,63 @@
<template>
<a-drawer :visible="visible" @close="onClose" class="yo-icon-selector" title="选择图标" width="600">
<a-tabs tab-position="left" v-model="active">
<a-tab-pane :key="iconGroup.key" :tab="iconGroup.title" v-for="iconGroup in icons">
<a-card>
<a-card-grid
:class="{ 'yo-icon--selected': selected == icon }"
:key="icon"
@click="onSelectIcon(icon)"
v-for="icon in iconGroup.icons"
>
<a-icon :style="{ fontSize: '36px' }" :type="icon" />
<span>{{ icon }}</span>
</a-card-grid>
</a-card>
</a-tab-pane>
</a-tabs>
</a-drawer>
</template>
<script>
import icons from './icons';
export default {
model: {
prop: 'selected',
event: 'select',
},
props: {
selected: {
type: String,
},
},
data() {
return {
visible: false,
icons,
active: icons[0].key,
};
},
methods: {
onOpen() {
this.visible = true;
if (this.selected) {
this.active = (icons.find((p) => p.icons.indexOf(this.selected) > -1) || icons[0]).key;
} else {
this.active = icons[0].key;
}
},
onClose() {
this.visible = false;
},
onSelectIcon(icon) {
this.$emit('select', icon);
this.onClose();
},
},
};
</script>

View File

@@ -0,0 +1,47 @@
import { PreviewFileBase64 } from '@/util/file'
export default {
props: {
type: {
type: String,
default: 'image'
},
id: {
type: [String, Number],
require: true
}
},
data() {
return {
src: ''
}
},
watch: {
async id() {
this.src = await this.getSrc()
}
},
async created() {
if (this.id) {
this.src = await this.getSrc()
}
},
methods: {
async getSrc() {
const base64 = await PreviewFileBase64(this.id)
return base64
}
},
render() {
return this.type == 'avatar' ?
<a-avatar src={this.src} {...{ props: this.$attrs }} />
:
<img src={this.src} {...{ props: this.$attrs }} />
},
}

View File

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

View File

@@ -0,0 +1,155 @@
export default {
props: {
type: {
type: String,
default: 'modal',
validator: function (value) {
return ['modal', 'drawer'].indexOf(value) > -1
}
},
compareOnClose: {
type: Boolean,
default: true
},
action: {
type: Function
},
successMessage: {
type: String
}
},
data() {
return {
visible: false,
confirmLoading: false,
form: {}
}
},
computed: {
body() {
return this.$slots.default && this.$slots.default[0].componentInstance
}
},
created() {
},
methods: {
renderModal(props) {
const _props = {
...props,
confirmLoading: this.confirmLoading
}
const _on = {
cancel: () => this.onClose(this.compareOnClose),
ok: () => this.onOk()
}
return (<a-modal {...{ props: _props, on: _on }} class="yo-modal-form">
{this.renderBody()}
</a-modal>)
},
renderDrawer(props) {
const _props = {
...props
}
const _on = {
close: () => this.onClose(this.compareOnClose),
ok: () => this.onOk()
}
return (<a-drawer {...{ props: _props, on: _on }} class="yo-drawer-form">
<div class="yo-drawer-form--body">
{this.renderBody()}
</div>
<div class="ant-drawer-footer">
<a-button onClick={_on.close}>取消</a-button>
<a-button loading={this.confirmLoading} onClick={_on.ok} type="primary">确定</a-button>
</div >
</a-drawer>)
},
renderBody() {
return this.$scopedSlots.default && this.$scopedSlots.default()
},
onOpen(data) {
this.visible = true
this.$nextTick(async () => {
if (!this.body) return
this.body.onInit && await this.body.onInit(data)
this.body.onFillData && this.body.onFillData(data)
this.form = this.$_.cloneDeep(this.body.form)
})
},
onClose(compare = false) {
const close = () => {
this.body
&& this.body.onResetFields
&& this.body.onResetFields()
this.visible = false
}
if (this.body) {
if (!this.$_.isEqual(this.form, this.body.form) && compare) {
this.$confirm({
title: '是否确认关闭',
content: '当前内容已更改,是否确认不保存并且关闭',
onOk: () => {
close()
}
})
} else {
close()
}
} else {
close()
}
},
onOk() {
this.body
&& this.body.onGetData
&& this.body.onGetData()
.then((data) => {
if (this.action) {
this.confirmLoading = true
this.action(data)
.then(({ success }) => {
if (success) {
this.$message.success(this.successMessage || '保存成功')
this.onClose();
this.$emit('ok', data)
}
})
.finally(() => {
this.confirmLoading = false
})
} else {
this.onClose()
this.$emit('ok', data)
}
}).catch(() => { })
}
},
render() {
const props = {
...this.$props,
...this.$attrs,
visible: this.visible
}
return this.type === 'modal' ? this.renderModal(props) : this.renderDrawer(props)
}
}

View File

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

View File

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

View File

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

View File

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

183
framework/Web/src/main.js Normal file
View File

@@ -0,0 +1,183 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
/**
* 引入antd
*/
import Antd from 'ant-design-vue'
Vue.use(Antd)
/**
* 引入swiper
*/
import 'swiper/swiper-bundle.css'
import {
Swiper as SwiperClass,
Pagination,
Mousewheel,
Autoplay,
Scrollbar
} from 'swiper/core'
import getAwesomeSwiper from 'vue-awesome-swiper/dist/exporter'
SwiperClass.use([Pagination, Mousewheel, Autoplay, Scrollbar])
Vue.use(getAwesomeSwiper(SwiperClass))
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai-sublime.css'
Vue.use(hljs.vuePlugin);
/**
* api全局化
*/
import { api } from './common/api'
Vue.prototype.$api = api
/**
* Lodash全局化
*/
import _ from 'lodash'
import * as _extend from './util/lodash-extend'
Object.assign(_, _extend)
Vue.prototype.$_ = _
/**
* moment全局化
*/
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.updateLocale('zh-cn', {
meridiem: function (hour, minute, isLowercase) {
if (hour < 9) {
return '早上'
} else if (hour < 11) {
return '上午'
} else if (hour < 13) {
return '中午'
} else if (hour < 18) {
return '下午'
} else {
return '晚上'
}
}
})
Vue.prototype.$moment = moment
/**
* 权限验证全局化
*/
import { auth } from './components/authorized'
Vue.prototype.$auth = auth
/**
* 常用工具函数全局化
*/
import { getSearchInfo } from './util/query'
Vue.prototype.$getSearchInfo = getSearchInfo
/**
* 注册全局组件
*/
import Container from './components/container'
Vue.component('Container', Container)
import Authorized from './components/authorized'
Vue.component('Auth', Authorized)
import YoTable from './components/yoTable'
Vue.component('YoTable', YoTable)
import YoTableActions from './components/yoTableActions'
Vue.component('YoTableActions', YoTableActions)
import YoModalForm from './components/yoModalForm'
Vue.component('YoModalForm', YoModalForm)
import YoImage from './components/yoImage'
Vue.component('YoImage', YoImage)
import YoFormLink from './components/yoFormLink'
Vue.component('YoFormLink', YoFormLink)
/**
* 引入主题样式
*/
import './assets/style/app.less'
import { SETTING_KEY } from './common/storage'
const settings = JSON.parse(window.localStorage.getItem(SETTING_KEY)) || {}
Object.assign(settings, {
layout: 'top-nav',
container: 'container-fluid',
navTheme: 'dark'
})
const app = new Vue({
data: {
/**
* 全局属性
* 可通过this.$root.global调用
*/
global: {
defaultWindow: [{
title: '首页',
path: '/home',
icon: 'home',
closable: false,
}],
/**
* 用于存储用户信息
*/
info: undefined,
/**
* 设置
*/
settings: settings || {
/**
* 导航颜色
*/
navTheme: 'dark',
/**
* 布局类型
* left-menu 左侧菜单经典结构
* top-nav 顶部导航菜单
*/
layout: 'left-menu',
/**
* 内容区域宽度
* container-fluid 整宽
* container 1200px宽度并居中
*/
container: 'container-fluid',
/**
* 左侧菜单是否收缩
*/
siderCollapsed: false
}
},
transfer: {
}
},
mounted() {
this.onChangeNavTheme()
},
watch: {
'global.settings': {
deep: true,
handler() {
window.localStorage.setItem(SETTING_KEY, JSON.stringify(this.global.settings))
}
},
'global.settings.navTheme'() {
this.onChangeNavTheme()
}
},
methods: {
onChangeNavTheme() {
document.body.classList.remove('yo-nav-theme--dark', 'yo-nav-theme--light')
document.body.classList.add(`yo-nav-theme--${this.global.settings.navTheme}`)
}
},
router,
render: h => h(App),
}).$mount('#app')
export default app

View File

@@ -0,0 +1,136 @@
<template>
<!--
整页表单的页签外框架
v 1.0
2021-05-12
Lufthafen
-->
<div class="yo-form-page">
<!-- 表单主体 -->
<!-- 如果不想使用固钉,删除a-row->a-col,只留内部的template层即可 -->
<container mode="container">
<a-row :gutter="16" type="flex">
<a-col flex="1">
<br />
<div class="yo-form">
<div class="yo-form-group">
<yo-form-link content="对片区信息进行管理" title="片区管理" />
<yo-form-link content="对项目信息进行管理" title="项目管理" />
</div>
</div>
<a-card class="yo-form-page--body">
<template v-for="(part, index) in parts">
<section :id="`form-${index}-${id}`" :key="index">
<h5 v-if="part.title">{{part.title}}</h5>
<component
:is="part.component"
:key="index"
:param="param"
ref="forms"
v-if="part.component"
/>
</section>
<a-divider :key="`divider-${index}`" v-if="index < parts.length - 1" />
</template>
</a-card>
</a-col>
</a-row>
</container>
<!-- 底部工具栏 -->
<div class="yo-form-page--bar">
<container mode="container">
<div class="yo-form-page--bar-inner">
<span>
<!-- 可以在工具栏中增加其他控件(只能在一行内) -->
<!-- ... -->
</span>
<span>
<a-button @click="closeContentWindow()">取消</a-button>
<Auth :auth="{ houseCode: [['add'], ['edit']] }">
<a-button :loading="saving" @click="onSubmit" type="primary">保存</a-button>
</Auth>
</span>
</div>
</container>
</div>
</div>
</template>
<script>
export default {
props: ['id', 'param'],
data() {
return {
parts: [
/**
* {
* title: '标题',
* component: () => import('...'),
* }
*/
{
component: () => import('./part'),
},
],
saving: false,
};
},
methods: {
async onSubmit() {
let formData = {};
for (let i = 0; i < this.$refs.forms.length; i++) {
const form = this.$refs.forms[i];
try {
const data = await form.onGetData();
formData = {
...formData,
...data,
};
} catch {
return;
}
}
/**
* 对表单提交进行处理
*/
this.saving = true;
if (!this.param.record) {
this.$api
.houseCodeAdd(formData)
.then(({ success }) => {
if (success) {
this.$message.success('保存成功');
this.$confirm({
content: '已添加成功,是否继续添加?',
onOk: () => {
this.$refs.forms[0].onProjectChange();
},
onCancel: () => {
this.closeContentWindow();
},
});
}
})
.finally(() => {
this.saving = false;
});
} else {
this.$api
.houseCodeEdit(formData)
.then(({ success }) => {
if (success) {
this.$message.success('保存成功');
}
})
.finally(() => {
this.saving = false;
});
}
},
},
};
</script>

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