Merge remote-tracking branch 'origin/feature-20240104' into feature-20240104

master
382696293@qq.com 2 years ago
commit 487738f53a

@ -5,7 +5,10 @@ VUE_APP_TITLE = 花至管理系统
ENV = 'development' ENV = 'development'
# 花至管理系统/开发环境 # 花至管理系统/开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/prod-api'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true
# 设置端口号
port=8080

@ -6,3 +6,6 @@ ENV = 'production'
# 花至管理系统/生产环境 # 花至管理系统/生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'
# 设置端口号
# port=8080

@ -5,7 +5,8 @@
"author": "花至", "author": "花至",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev": "set NODE_OPTIONS=--openssl-legacy-provider & vue-cli-service serve", "local": "vue-cli-service serve --mode local",
"dev": "vue-cli-service serve --mode development",
"build:prod": "vue-cli-service build", "build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging", "build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview", "preview": "node build/index.js --preview",
@ -45,11 +46,14 @@
"file-saver": "2.0.5", "file-saver": "2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"i": "^0.3.7",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"npm": "^10.2.5",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "1.3.7", "quill": "^2.0.0-dev.3",
"quill-better-table": "^1.2.10",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"vue": "2.6.12", "vue": "2.6.12",

@ -0,0 +1,978 @@
/*!
* Quill Editor v2.0.0-dev.3
* https://quilljs.com/
* Copyright (c) 2014, Jason Chen
* Copyright (c) 2013, salesforce.com
*/
.ql-container {
box-sizing: border-box;
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
height: 100%;
margin: 0;
position: relative;
}
.ql-container.ql-disabled .ql-tooltip {
visibility: hidden;
}
.ql-container:not(.ql-disabled) li[data-list="checked"] > .ql-ui,
.ql-container:not(.ql-disabled) li[data-list="unchecked"] > .ql-ui {
cursor: pointer;
}
.ql-clipboard {
left: -100000px;
height: 1px;
overflow-y: hidden;
position: absolute;
top: 50%;
}
.ql-clipboard p {
margin: 0;
padding: 0;
}
.ql-editor {
box-sizing: border-box;
counter-reset: list-0;
line-height: 1.42;
height: 100%;
outline: 0;
overflow-y: auto;
padding: 12px 15px;
tab-size: 4;
-moz-tab-size: 4;
text-align: left;
white-space: pre-wrap;
word-wrap: break-word;
}
.ql-editor > * {
cursor: text;
}
.ql-editor blockquote,
.ql-editor h1,
.ql-editor h2,
.ql-editor h3,
.ql-editor h4,
.ql-editor h5,
.ql-editor h6,
.ql-editor ol,
.ql-editor p,
.ql-editor pre {
margin: 0;
padding: 0;
}
.ql-editor h1,
.ql-editor h2,
.ql-editor h3,
.ql-editor h4,
.ql-editor h5,
.ql-editor h6,
.ql-editor p {
counter-reset: list-0 list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8
list-9;
}
.ql-editor table {
border-collapse: collapse;
}
.ql-editor td {
border: 1px solid #000;
padding: 2px 5px;
}
.ql-editor ol {
padding-left: 1.5em;
}
.ql-editor li {
list-style-type: none;
padding-left: 1.5em;
position: relative;
}
.ql-editor li > .ql-ui:before {
display: inline-block;
margin-left: -1.5em;
margin-right: 0.3em;
text-align: right;
white-space: nowrap;
width: 1.2em;
}
.ql-editor li[data-list="checked"] > .ql-ui,
.ql-editor li[data-list="unchecked"] > .ql-ui {
color: #777;
}
.ql-editor li[data-list="bullet"] > .ql-ui:before {
content: "\2022";
}
.ql-editor li[data-list="checked"] > .ql-ui:before {
content: "\2611";
}
.ql-editor li[data-list="unchecked"] > .ql-ui:before {
content: "\2610";
}
.ql-editor li[data-list="ordered"] {
counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
counter-increment: list-0;
}
.ql-editor li[data-list="ordered"] > .ql-ui:before {
content: counter(list-0, decimal) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-1 {
counter-increment: list-1;
}
.ql-editor li[data-list="ordered"].ql-indent-1 > .ql-ui:before {
content: counter(list-1, lower-alpha) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-1 {
counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-2 {
counter-increment: list-2;
}
.ql-editor li[data-list="ordered"].ql-indent-2 > .ql-ui:before {
content: counter(list-2, lower-roman) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-2 {
counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-3 {
counter-increment: list-3;
}
.ql-editor li[data-list="ordered"].ql-indent-3 > .ql-ui:before {
content: counter(list-3, decimal) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-3 {
counter-reset: list-4 list-5 list-6 list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-4 {
counter-increment: list-4;
}
.ql-editor li[data-list="ordered"].ql-indent-4 > .ql-ui:before {
content: counter(list-4, lower-alpha) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-4 {
counter-reset: list-5 list-6 list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-5 {
counter-increment: list-5;
}
.ql-editor li[data-list="ordered"].ql-indent-5 > .ql-ui:before {
content: counter(list-5, lower-roman) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-5 {
counter-reset: list-6 list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-6 {
counter-increment: list-6;
}
.ql-editor li[data-list="ordered"].ql-indent-6 > .ql-ui:before {
content: counter(list-6, decimal) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-6 {
counter-reset: list-7 list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-7 {
counter-increment: list-7;
}
.ql-editor li[data-list="ordered"].ql-indent-7 > .ql-ui:before {
content: counter(list-7, lower-alpha) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-7 {
counter-reset: list-8 list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-8 {
counter-increment: list-8;
}
.ql-editor li[data-list="ordered"].ql-indent-8 > .ql-ui:before {
content: counter(list-8, lower-roman) ". ";
}
.ql-editor li[data-list="ordered"].ql-indent-8 {
counter-reset: list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-9 {
counter-increment: list-9;
}
.ql-editor li[data-list="ordered"].ql-indent-9 > .ql-ui:before {
content: counter(list-9, decimal) ". ";
}
.ql-editor .ql-indent-1:not(.ql-direction-rtl) {
padding-left: 3em;
}
.ql-editor li.ql-indent-1:not(.ql-direction-rtl) {
padding-left: 4.5em;
}
.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 3em;
}
.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right {
padding-right: 4.5em;
}
.ql-editor .ql-indent-2:not(.ql-direction-rtl) {
padding-left: 6em;
}
.ql-editor li.ql-indent-2:not(.ql-direction-rtl) {
padding-left: 7.5em;
}
.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 6em;
}
.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right {
padding-right: 7.5em;
}
.ql-editor .ql-indent-3:not(.ql-direction-rtl) {
padding-left: 9em;
}
.ql-editor li.ql-indent-3:not(.ql-direction-rtl) {
padding-left: 10.5em;
}
.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 9em;
}
.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right {
padding-right: 10.5em;
}
.ql-editor .ql-indent-4:not(.ql-direction-rtl) {
padding-left: 12em;
}
.ql-editor li.ql-indent-4:not(.ql-direction-rtl) {
padding-left: 13.5em;
}
.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 12em;
}
.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right {
padding-right: 13.5em;
}
.ql-editor .ql-indent-5:not(.ql-direction-rtl) {
padding-left: 15em;
}
.ql-editor li.ql-indent-5:not(.ql-direction-rtl) {
padding-left: 16.5em;
}
.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 15em;
}
.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right {
padding-right: 16.5em;
}
.ql-editor .ql-indent-6:not(.ql-direction-rtl) {
padding-left: 18em;
}
.ql-editor li.ql-indent-6:not(.ql-direction-rtl) {
padding-left: 19.5em;
}
.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 18em;
}
.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right {
padding-right: 19.5em;
}
.ql-editor .ql-indent-7:not(.ql-direction-rtl) {
padding-left: 21em;
}
.ql-editor li.ql-indent-7:not(.ql-direction-rtl) {
padding-left: 22.5em;
}
.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 21em;
}
.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right {
padding-right: 22.5em;
}
.ql-editor .ql-indent-8:not(.ql-direction-rtl) {
padding-left: 24em;
}
.ql-editor li.ql-indent-8:not(.ql-direction-rtl) {
padding-left: 25.5em;
}
.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 24em;
}
.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right {
padding-right: 25.5em;
}
.ql-editor .ql-indent-9:not(.ql-direction-rtl) {
padding-left: 27em;
}
.ql-editor li.ql-indent-9:not(.ql-direction-rtl) {
padding-left: 28.5em;
}
.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 27em;
}
.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right {
padding-right: 28.5em;
}
.ql-editor li.ql-direction-rtl {
padding-right: 1.5em;
}
.ql-editor li.ql-direction-rtl > .ql-ui:before {
margin-left: 0.3em;
margin-right: -1.5em;
text-align: left;
}
.ql-editor table {
table-layout: fixed;
width: 100%;
}
.ql-editor table td {
outline: 0;
}
.ql-editor .ql-code-block-container {
font-family: monospace;
}
.ql-editor .ql-video {
display: block;
max-width: 100%;
}
.ql-editor .ql-video.ql-align-center {
margin: 0 auto;
}
.ql-editor .ql-video.ql-align-right {
margin: 0 0 0 auto;
}
.ql-editor .ql-bg-black {
background-color: #000;
}
.ql-editor .ql-bg-red {
background-color: #e60000;
}
.ql-editor .ql-bg-orange {
background-color: #f90;
}
.ql-editor .ql-bg-yellow {
background-color: #ff0;
}
.ql-editor .ql-bg-green {
background-color: #008a00;
}
.ql-editor .ql-bg-blue {
background-color: #06c;
}
.ql-editor .ql-bg-purple {
background-color: #93f;
}
.ql-editor .ql-color-white {
color: #fff;
}
.ql-editor .ql-color-red {
color: #e60000;
}
.ql-editor .ql-color-orange {
color: #f90;
}
.ql-editor .ql-color-yellow {
color: #ff0;
}
.ql-editor .ql-color-green {
color: #008a00;
}
.ql-editor .ql-color-blue {
color: #06c;
}
.ql-editor .ql-color-purple {
color: #93f;
}
.ql-editor .ql-font-serif {
font-family: Georgia, Times New Roman, serif;
}
.ql-editor .ql-font-monospace {
font-family: Monaco, Courier New, monospace;
}
.ql-editor .ql-size-small {
font-size: 0.75em;
}
.ql-editor .ql-size-large {
font-size: 1.5em;
}
.ql-editor .ql-size-huge {
font-size: 2.5em;
}
.ql-editor .ql-direction-rtl {
direction: rtl;
text-align: inherit;
}
.ql-editor .ql-align-center {
text-align: center;
}
.ql-editor .ql-align-justify {
text-align: justify;
}
.ql-editor .ql-align-right {
text-align: right;
}
.ql-editor .ql-ui {
position: absolute;
}
.ql-editor.ql-blank::before {
color: rgba(0, 0, 0, 0.6);
content: attr(data-placeholder);
font-style: italic;
left: 15px;
pointer-events: none;
position: absolute;
right: 15px;
}
.ql-snow .ql-toolbar:after,
.ql-snow.ql-toolbar:after {
clear: both;
content: "";
display: table;
}
.ql-snow .ql-toolbar button,
.ql-snow.ql-toolbar button {
background: 0 0;
border: none;
cursor: pointer;
display: inline-block;
float: left;
height: 24px;
padding: 3px 5px;
width: 28px;
}
.ql-snow .ql-toolbar button svg,
.ql-snow.ql-toolbar button svg {
float: left;
height: 100%;
}
.ql-snow .ql-toolbar button:active:hover,
.ql-snow.ql-toolbar button:active:hover {
outline: 0;
}
.ql-snow .ql-toolbar input.ql-image[type="file"],
.ql-snow.ql-toolbar input.ql-image[type="file"] {
display: none;
}
.ql-snow .ql-toolbar .ql-picker-item.ql-selected,
.ql-snow .ql-toolbar .ql-picker-item:hover,
.ql-snow .ql-toolbar .ql-picker-label.ql-active,
.ql-snow .ql-toolbar .ql-picker-label:hover,
.ql-snow .ql-toolbar button.ql-active,
.ql-snow .ql-toolbar button:focus,
.ql-snow .ql-toolbar button:hover,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected,
.ql-snow.ql-toolbar .ql-picker-item:hover,
.ql-snow.ql-toolbar .ql-picker-label.ql-active,
.ql-snow.ql-toolbar .ql-picker-label:hover,
.ql-snow.ql-toolbar button.ql-active,
.ql-snow.ql-toolbar button:focus,
.ql-snow.ql-toolbar button:hover {
color: #06c;
}
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-fill,
.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:focus .ql-fill,
.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow .ql-toolbar button:hover .ql-fill,
.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-fill,
.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:focus .ql-fill,
.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:hover .ql-fill,
.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill {
fill: #06c;
}
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow .ql-toolbar button.ql-active .ql-stroke,
.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow .ql-toolbar button:focus .ql-stroke,
.ql-snow .ql-toolbar button:focus .ql-stroke-miter,
.ql-snow .ql-toolbar button:hover .ql-stroke,
.ql-snow .ql-toolbar button:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke,
.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter,
.ql-snow.ql-toolbar button.ql-active .ql-stroke,
.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter,
.ql-snow.ql-toolbar button:focus .ql-stroke,
.ql-snow.ql-toolbar button:focus .ql-stroke-miter,
.ql-snow.ql-toolbar button:hover .ql-stroke,
.ql-snow.ql-toolbar button:hover .ql-stroke-miter {
stroke: #06c;
}
@media (pointer: coarse) {
.ql-snow .ql-toolbar button:hover:not(.ql-active),
.ql-snow.ql-toolbar button:hover:not(.ql-active) {
color: #444;
}
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill {
fill: #444;
}
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke,
.ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter {
stroke: #444;
}
}
.ql-snow {
box-sizing: border-box;
}
.ql-snow * {
box-sizing: border-box;
}
.ql-snow .ql-hidden {
display: none;
}
.ql-snow .ql-out-bottom,
.ql-snow .ql-out-top {
visibility: hidden;
}
.ql-snow .ql-tooltip {
position: absolute;
transform: translateY(10px);
}
.ql-snow .ql-tooltip a {
cursor: pointer;
text-decoration: none;
}
.ql-snow .ql-tooltip.ql-flip {
transform: translateY(-10px);
}
.ql-snow .ql-formats {
display: inline-block;
vertical-align: middle;
}
.ql-snow .ql-formats:after {
clear: both;
content: "";
display: table;
}
.ql-snow .ql-stroke {
fill: none;
stroke: #444;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 2;
}
.ql-snow .ql-stroke-miter {
fill: none;
stroke: #444;
stroke-miterlimit: 10;
stroke-width: 2;
}
.ql-snow .ql-fill,
.ql-snow .ql-stroke.ql-fill {
fill: #444;
}
.ql-snow .ql-empty {
fill: none;
}
.ql-snow .ql-even {
fill-rule: evenodd;
}
.ql-snow .ql-stroke.ql-thin,
.ql-snow .ql-thin {
stroke-width: 1;
}
.ql-snow .ql-transparent {
opacity: 0.4;
}
.ql-snow .ql-direction svg:last-child {
display: none;
}
.ql-snow .ql-direction.ql-active svg:last-child {
display: inline;
}
.ql-snow .ql-direction.ql-active svg:first-child {
display: none;
}
.ql-snow .ql-editor h1 {
font-size: 2em;
}
.ql-snow .ql-editor h2 {
font-size: 1.5em;
}
.ql-snow .ql-editor h3 {
font-size: 1.17em;
}
.ql-snow .ql-editor h4 {
font-size: 1em;
}
.ql-snow .ql-editor h5 {
font-size: 0.83em;
}
.ql-snow .ql-editor h6 {
font-size: 0.67em;
}
.ql-snow .ql-editor a {
text-decoration: underline;
}
.ql-snow .ql-editor blockquote {
border-left: 4px solid #ccc;
margin-bottom: 5px;
margin-top: 5px;
padding-left: 16px;
}
.ql-snow .ql-editor .ql-code-block-container,
.ql-snow .ql-editor code {
background-color: #f0f0f0;
border-radius: 3px;
}
.ql-snow .ql-editor .ql-code-block-container {
margin-bottom: 5px;
margin-top: 5px;
padding: 5px 10px;
}
.ql-snow .ql-editor code {
font-size: 85%;
padding: 2px 4px;
}
.ql-snow .ql-editor .ql-code-block-container {
background-color: #23241f;
color: #f8f8f2;
overflow: visible;
}
.ql-snow .ql-editor img {
max-width: 100%;
}
.ql-snow .ql-picker {
color: #444;
display: inline-block;
float: left;
font-size: 14px;
font-weight: 500;
height: 24px;
position: relative;
vertical-align: middle;
}
.ql-snow .ql-picker-label {
cursor: pointer;
display: inline-block;
height: 100%;
padding-left: 8px;
padding-right: 2px;
position: relative;
width: 100%;
}
.ql-snow .ql-picker-label::before {
display: inline-block;
line-height: 22px;
}
.ql-snow .ql-picker-options {
background-color: #fff;
display: none;
min-width: 100%;
padding: 4px 8px;
position: absolute;
white-space: nowrap;
}
.ql-snow .ql-picker-options .ql-picker-item {
cursor: pointer;
display: block;
padding-bottom: 5px;
padding-top: 5px;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label {
color: #ccc;
z-index: 2;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill {
fill: #ccc;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke {
stroke: #ccc;
}
.ql-snow .ql-picker.ql-expanded .ql-picker-options {
display: block;
margin-top: -1px;
top: 100%;
z-index: 1;
}
.ql-snow .ql-color-picker,
.ql-snow .ql-icon-picker {
width: 28px;
}
.ql-snow .ql-color-picker .ql-picker-label,
.ql-snow .ql-icon-picker .ql-picker-label {
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-label svg,
.ql-snow .ql-icon-picker .ql-picker-label svg {
right: 4px;
}
.ql-snow .ql-icon-picker .ql-picker-options {
padding: 4px 0;
}
.ql-snow .ql-icon-picker .ql-picker-item {
height: 24px;
width: 24px;
padding: 2px 4px;
}
.ql-snow .ql-color-picker .ql-picker-options {
padding: 3px 5px;
width: 152px;
}
.ql-snow .ql-color-picker .ql-picker-item {
border: 1px solid transparent;
float: left;
height: 16px;
margin: 2px;
padding: 0;
width: 16px;
}
.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg {
position: absolute;
margin-top: -9px;
right: 0;
top: 50%;
width: 18px;
}
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-header
.ql-picker-item[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-header
.ql-picker-label[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-size
.ql-picker-item[data-label]:not([data-label=""])::before,
.ql-snow
.ql-picker.ql-size
.ql-picker-label[data-label]:not([data-label=""])::before {
content: attr(data-label);
}
.ql-snow .ql-picker.ql-header {
width: 98px;
}
.ql-snow .ql-picker.ql-header .ql-picker-item::before,
.ql-snow .ql-picker.ql-header .ql-picker-label::before {
content: "Normal";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before {
content: "Heading 1";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before {
content: "Heading 2";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before {
content: "Heading 3";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before {
content: "Heading 4";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before {
content: "Heading 5";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before {
content: "Heading 6";
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
font-size: 2em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
font-size: 1.5em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
font-size: 1.17em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
font-size: 1em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
font-size: 0.83em;
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
font-size: 0.67em;
}
.ql-snow .ql-picker.ql-font {
width: 108px;
}
.ql-snow .ql-picker.ql-font .ql-picker-item::before,
.ql-snow .ql-picker.ql-font .ql-picker-label::before {
content: "Sans Serif";
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before {
content: "Serif";
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before {
content: "Monospace";
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
font-family: Georgia, Times New Roman, serif;
}
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
font-family: Monaco, Courier New, monospace;
}
.ql-snow .ql-picker.ql-size {
width: 98px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item::before,
.ql-snow .ql-picker.ql-size .ql-picker-label::before {
content: "Normal";
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before {
content: "Small";
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before {
content: "Large";
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before {
content: "Huge";
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
font-size: 10px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
font-size: 32px;
}
.ql-snow .ql-color-picker.ql-background .ql-picker-item {
background-color: #fff;
}
.ql-snow .ql-color-picker.ql-color .ql-picker-item {
background-color: #000;
}
.ql-code-block-container {
position: relative;
}
.ql-code-block-container .ql-ui {
right: 5px;
top: 5px;
}
.ql-toolbar.ql-snow {
border: 1px solid #ccc;
box-sizing: border-box;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 8px;
}
.ql-toolbar.ql-snow .ql-formats {
margin-right: 15px;
}
.ql-toolbar.ql-snow .ql-picker-label {
border: 1px solid transparent;
}
.ql-toolbar.ql-snow .ql-picker-options {
border: 1px solid transparent;
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 8px;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label {
border-color: #ccc;
}
.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options {
border-color: #ccc;
}
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected,
.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover {
border-color: #000;
}
.ql-toolbar.ql-snow + .ql-container.ql-snow {
border-top: 0;
}
.ql-snow .ql-tooltip {
background-color: #fff;
border: 1px solid #ccc;
box-shadow: 0 0 5px #ddd;
color: #444;
padding: 5px 12px;
white-space: nowrap;
}
.ql-snow .ql-tooltip::before {
content: "Visit URL:";
line-height: 26px;
margin-right: 8px;
}
.ql-snow .ql-tooltip input[type="text"] {
display: none;
border: 1px solid #ccc;
font-size: 13px;
height: 26px;
margin: 0;
padding: 3px 5px;
width: 170px;
}
.ql-snow .ql-tooltip a.ql-preview {
display: inline-block;
max-width: 200px;
overflow-x: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
.ql-snow .ql-tooltip a.ql-action::after {
border-right: 1px solid #ccc;
content: "Edit";
margin-left: 16px;
padding-right: 8px;
}
.ql-snow .ql-tooltip a.ql-remove::before {
content: "Remove";
margin-left: 8px;
}
.ql-snow .ql-tooltip a {
line-height: 26px;
}
.ql-snow .ql-tooltip.ql-editing a.ql-preview,
.ql-snow .ql-tooltip.ql-editing a.ql-remove {
display: none;
}
.ql-snow .ql-tooltip.ql-editing input[type="text"] {
display: inline-block;
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0;
content: "Save";
padding-right: 0;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
content: "Enter link:";
}
.ql-snow .ql-tooltip[data-mode="formula"]::before {
content: "Enter formula:";
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
content: "Enter video:";
}
.ql-snow a {
color: #06c;
}
.ql-container.ql-snow {
border: 1px solid #ccc;
}
/*# sourceMappingURL=quill.snow.min.css.map */

File diff suppressed because it is too large Load Diff

@ -13,24 +13,37 @@
v-if="this.type == 'url'" v-if="this.type == 'url'"
> >
</el-upload> </el-upload>
<div class="editor" ref="editor" :style="styles"></div> <div class="editor" ref="editor" :style="styles">
<div>
{{ this.currentValue }}
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import Quill from "quill"; import Quill from 'quill'
import "quill/dist/quill.core.css"; import 'quill/dist/quill.core.css'
import "quill/dist/quill.snow.css"; import 'quill/dist/quill.snow.css'
import "quill/dist/quill.bubble.css"; import 'quill/dist/quill.bubble.css'
import { getToken } from "@/utils/auth"; import { getToken } from '@/utils/auth'
import QuillBetterTable from 'quill-better-table'
import 'quill-better-table/dist/quill-better-table.css'
Quill.register(
{
'modules/better-table': QuillBetterTable,
},
true
)
export default { export default {
name: "Editor", name: 'Editor',
props: { props: {
/* 编辑器的内容 */ /* 编辑器的内容 */
value: { value: {
type: String, type: String,
default: "", default: '',
}, },
/* 高度 */ /* 高度 */
height: { height: {
@ -55,60 +68,81 @@ export default {
/* 类型base64格式、url格式 */ /* 类型base64格式、url格式 */
type: { type: {
type: String, type: String,
default: "url", default: 'url',
}
}, },
/* 私有ID 用于同一页面下的不同富文本的表格修改 */
tableName: {
type: String,
default: 'mytable',
},
},
data() { data() {
return { return {
uploadUrl: process.env.VUE_APP_BASE_API + "/file/upload", // uploadUrl: process.env.VUE_APP_BASE_API + '/file/upload', //
headers: { headers: {
Authorization: "Bearer " + getToken() Authorization: 'Bearer ' + getToken(),
}, },
Quill: null, Quill: null,
currentValue: "", currentValue: '',
options: { options: {
theme: "snow", theme: 'snow',
bounds: document.body, bounds: document.body,
debug: "warn", debug: 'warn',
modules: { modules: {
table: false, // disable table module
'better-table': {
operationMenu: {
items: {
unmergeCells: {
text: 'Another unmerge cells name',
},
},
},
},
keyboard: {
bindings: QuillBetterTable.keyboardBindings,
},
// //
toolbar: [ toolbar: [
["bold", "italic", "underline", "strike"], // 线 线 ['bold', 'italic', 'underline', 'strike'], // 线 线
["blockquote", "code-block"], // ['blockquote', 'code-block'], //
[{ list: "ordered" }, { list: "bullet" }], // [{ list: 'ordered' }, { list: 'bullet' }], //
[{ indent: "-1" }, { indent: "+1" }], // [{ indent: '-1' }, { indent: '+1' }], //
[{ size: ["small", false, "large", "huge"] }], // [{ size: ['small', false, 'large', 'huge'] }], //
[{ header: [1, 2, 3, 4, 5, 6, false] }], // [{ header: [1, 2, 3, 4, 5, 6, false] }], //
[{ color: [] }, { background: [] }], // [{ color: [] }, { background: [] }], //
[{ align: [] }], // [{ align: [] }], //
["clean"], // ['clean'], //
["link", "image", "video"] // ['table'],
['link', 'image', 'video'], //
], ],
}, },
placeholder: "请输入内容", placeholder: '请输入内容',
readOnly: this.readOnly, readOnly: this.readOnly,
}, },
}; }
}, },
computed: { computed: {
styles() { styles() {
let style = {}; let style = {}
if (this.minHeight) { if (this.minHeight) {
style.minHeight = `${this.minHeight}px`; style.minHeight = `${this.minHeight}px`
} }
if (this.height) { if (this.height) {
style.height = `${this.height}px`; style.height = `${this.height}px`
} }
return style; return style
}, },
}, },
watch: { watch: {
value: { value: {
handler(val) { handler(val) {
if (val !== this.currentValue) { if (val !== this.currentValue) {
this.currentValue = val === null ? "" : val; this.currentValue = val === null ? '' : val
if (this.Quill) { let ele = document.body.querySelector(`#${this.tableName} .editor`)
this.Quill.pasteHTML(this.currentValue); if (ele) {
ele.children[0].innerHTML = this.currentValue
} }
} }
}, },
@ -116,159 +150,177 @@ export default {
}, },
}, },
mounted() { mounted() {
this.init(); this.init()
// this.addTableButton()
}, },
beforeDestroy() { beforeDestroy() {
this.Quill = null; this.Quill = null
}, },
methods: { methods: {
init() { init() {
const editor = this.$refs.editor; const editor = this.$refs.editor
this.Quill = new Quill(editor, this.options); this.Quill = new Quill(editor, this.options)
// //
if (this.type == 'url') { if (this.type == 'url') {
let toolbar = this.Quill.getModule("toolbar"); let toolbar = this.Quill.getModule('toolbar')
toolbar.addHandler("image", (value) => { toolbar.addHandler('image', (value) => {
if (value) { if (value) {
this.$refs.upload.$children[0].$refs.input.click(); this.$refs.upload.$children[0].$refs.input.click()
} else { } else {
this.quill.format("image", false); this.quill.format('image', false)
} }
}); })
} }
this.Quill.pasteHTML(this.currentValue); // this.Quill.pasteHTML(this.currentValue)
this.Quill.on("text-change", (delta, oldDelta, source) => { // this.Quill.setText(this.currentValue)
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText(); let tableModule = this.Quill.getModule('better-table')
const quill = this.Quill; let ele = document.body.querySelector(`#${this.tableName} .ql-table`)
this.currentValue = html; if (ele) {
this.$emit("input", html); ele.onclick = () => {
this.$emit("on-change", { html, text, quill }); tableModule.insertTable(3, 3)
}); }
this.Quill.on("text-change", (delta, oldDelta, source) => { }
this.$emit("on-text-change", delta, oldDelta, source);
}); this.Quill.on('text-change', (delta, oldDelta, source) => {
this.Quill.on("selection-change", (range, oldRange, source) => { const html = this.$refs.editor.children[0].innerHTML
this.$emit("on-selection-change", range, oldRange, source); const text = this.Quill.getText()
}); const quill = this.Quill
this.Quill.on("editor-change", (eventName, ...args) => { this.currentValue = html
this.$emit("on-editor-change", eventName, ...args); this.$emit('input', html)
}); this.$emit('on-change', { html, text, quill })
})
this.Quill.on('text-change', (delta, oldDelta, source) => {
this.$emit('on-text-change', delta, oldDelta, source)
})
this.Quill.on('selection-change', (range, oldRange, source) => {
this.$emit('on-selection-change', range, oldRange, source)
})
this.Quill.on('editor-change', (eventName, ...args) => {
this.$emit('on-editor-change', eventName, ...args)
})
},
addTableButton() {
let ele = document.getElementsByClassName('.ql-better-table')
console.log('ADD table', ele)
}, },
// //
handleBeforeUpload(file) { handleBeforeUpload(file) {
const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; const type = ['image/jpeg', 'image/jpg', 'image/png', 'image/svg']
const isJPG = type.includes(file.type); const isJPG = type.includes(file.type)
// //
if (!isJPG) { if (!isJPG) {
this.$message.error(`图片格式错误!`); this.$message.error(`图片格式错误!`)
return false; return false
} }
// //
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`); this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
return true; return true
}, },
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
// //
if (res.code == 200) { if (res.code == 200) {
// //
let quill = this.Quill; let quill = this.Quill
// //
let length = quill.getSelection().index; let length = quill.getSelection().index
// res.url // res.url
quill.insertEmbed(length, "image", res.data.url); quill.insertEmbed(length, 'image', res.data.url)
// //
quill.setSelection(length + 1); quill.setSelection(length + 1)
} else { } else {
this.$message.error("图片插入失败"); this.$message.error('图片插入失败')
} }
}, },
handleUploadError() { handleUploadError() {
this.$message.error("图片插入失败"); this.$message.error('图片插入失败')
}, },
}, },
}; }
</script> </script>
<style> <style>
.editor, .ql-toolbar { .editor,
.ql-toolbar {
white-space: pre-wrap !important; white-space: pre-wrap !important;
line-height: normal !important; line-height: normal !important;
} }
.quill-img { .quill-img {
display: none; display: none;
} }
.ql-snow .ql-tooltip[data-mode="link"]::before { .ql-snow .ql-tooltip[data-mode='link']::before {
content: "请输入链接地址:"; content: '请输入链接地址:';
} }
.ql-snow .ql-tooltip.ql-editing a.ql-action::after { .ql-snow .ql-tooltip.ql-editing a.ql-action::after {
border-right: 0px; border-right: 0px;
content: "保存"; content: '保存';
padding-right: 0px; padding-right: 0px;
} }
.ql-snow .ql-tooltip[data-mode="video"]::before { .ql-snow .ql-tooltip[data-mode='video']::before {
content: "请输入视频地址:"; content: '请输入视频地址:';
} }
.ql-snow .ql-picker.ql-size .ql-picker-label::before, .ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before { .ql-snow .ql-picker.ql-size .ql-picker-item::before {
content: "14px"; content: '14px';
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='small']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='small']::before {
content: "10px"; content: '10px';
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='large']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='large']::before {
content: "18px"; content: '18px';
} }
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='huge']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='huge']::before {
content: "32px"; content: '32px';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label::before, .ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before { .ql-snow .ql-picker.ql-header .ql-picker-item::before {
content: "文本"; content: '文本';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='1']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='1']::before {
content: "标题1"; content: '标题1';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='2']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='2']::before {
content: "标题2"; content: '标题2';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='3']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='3']::before {
content: "标题3"; content: '标题3';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='4']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='4']::before {
content: "标题4"; content: '标题4';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='5']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='5']::before {
content: "标题5"; content: '标题5';
} }
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, .ql-snow .ql-picker.ql-header .ql-picker-label[data-value='6']::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { .ql-snow .ql-picker.ql-header .ql-picker-item[data-value='6']::before {
content: "标题6"; content: '标题6';
} }
.ql-snow .ql-picker.ql-font .ql-picker-label::before, .ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before { .ql-snow .ql-picker.ql-font .ql-picker-item::before {
content: "标准字体"; content: '标准字体';
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
content: "衬线字体"; content: '衬线字体';
} }
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
content: "等宽字体"; content: '等宽字体';
} }
</style> </style>

@ -1,56 +1,58 @@
import router from './router' import router from "./router";
import store from './store' import store from "./store";
import { Message } from 'element-ui' import { Message } from "element-ui";
import NProgress from 'nprogress' import NProgress from "nprogress";
import 'nprogress/nprogress.css' import "nprogress/nprogress.css";
import { getToken } from '@/utils/auth' import { getToken } from "@/utils/auth";
import { isRelogin } from '@/utils/request' import { isRelogin } from "@/utils/request";
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register'] const whiteList = ["/login", "/register"];
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.start() NProgress.start();
if (getToken()) { if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title) to.meta.title && store.dispatch("settings/setTitle", to.meta.title);
/* has token*/ /* has token*/
if (to.path === '/login') { if (to.path === "/login") {
next({ path: '/' }) next({ path: "/" });
NProgress.done() NProgress.done();
} else { } else {
if (store.getters.roles.length === 0) { if (store.getters.roles.length === 0) {
isRelogin.show = true isRelogin.show = true;
// 判断当前用户是否已拉取完user_info信息 // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => { store
isRelogin.show = false .dispatch("GetInfo")
store.dispatch('GenerateRoutes').then(accessRoutes => { .then(() => {
isRelogin.show = false;
store.dispatch("GenerateRoutes").then((accessRoutes) => {
// 根据roles权限生成可访问的路由表 // 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表 router.addRoutes(accessRoutes); // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
}) });
}).catch(err => {
store.dispatch('LogOut').then(() => {
Message.error(err)
next({ path: '/' })
})
}) })
.catch((err) => {
store.dispatch("LogOut").then(() => {
Message.error(err);
next({ path: "/" });
});
});
} else { } else {
next() next();
} }
} }
} else { } else {
// 没有token
if (whiteList.indexOf(to.path) !== -1) { if (whiteList.indexOf(to.path) !== -1) {
// 在免登录白名单,直接进入 // 在免登录白名单,直接进入
next() next();
} else { } else {
next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 否则全部重定向到登录页 next(`/login?redirect=${encodeURIComponent(to.fullPath)}`); // 否则全部重定向到登录页
NProgress.done() NProgress.done();
} }
} }
}) });
router.afterEach(() => { router.afterEach(() => {
NProgress.done() NProgress.done();
}) });

@ -1,10 +1,10 @@
import Vue from 'vue' import Vue from "vue";
import Router from 'vue-router' import Router from "vue-router";
Vue.use(Router) Vue.use(Router);
/* Layout */ /* Layout */
import Layout from '@/layout' import Layout from "@/layout";
/** /**
* Note: 路由配置项 * Note: 路由配置项
@ -31,153 +31,153 @@ import Layout from '@/layout'
// 公共路由 // 公共路由
export const constantRoutes = [ export const constantRoutes = [
{ {
path: '/redirect', path: "/redirect",
component: Layout, component: Layout,
hidden: true, hidden: true,
children: [ children: [
{ {
path: '/redirect/:path(.*)', path: "/redirect/:path(.*)",
component: () => import('@/views/redirect') component: () => import("@/views/redirect"),
} },
] ],
}, },
{ {
path: '/login', path: "/login",
component: () => import('@/views/login'), component: () => import("@/views/login"),
hidden: true hidden: true,
}, },
{ {
path: '/register', path: "/register",
component: () => import('@/views/register'), component: () => import("@/views/register"),
hidden: true hidden: true,
}, },
{ {
path: '/404', path: "/404",
component: () => import('@/views/error/404'), component: () => import("@/views/error/404"),
hidden: true hidden: true,
}, },
{ {
path: '/401', path: "/401",
component: () => import('@/views/error/401'), component: () => import("@/views/error/401"),
hidden: true hidden: true,
}, },
{ {
path: '', path: "",
component: Layout, component: Layout,
redirect: 'index', redirect: "index",
children: [ children: [
{ {
path: 'index', path: "index",
component: () => import('@/views/index'), component: () => import("@/views/index"),
name: 'Index', name: "Index",
meta: { title: '首页', icon: 'dashboard', affix: true } meta: { title: "首页", icon: "dashboard", affix: true },
} },
] ],
}, },
{ {
path: '/user', path: "/user",
component: Layout, component: Layout,
hidden: true, hidden: true,
redirect: 'noredirect', redirect: "noredirect",
children: [ children: [
{ {
path: 'profile', path: "profile",
component: () => import('@/views/system/user/profile/index'), component: () => import("@/views/system/user/profile/index"),
name: 'Profile', name: "Profile",
meta: { title: '个人中心', icon: 'user' } meta: { title: "个人中心", icon: "user" },
} },
] ],
} },
] ];
// 动态路由,基于用户权限动态去加载 // 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [ export const dynamicRoutes = [
{ {
path: '/system/user-auth', path: "/system/user-auth",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:user:edit'], permissions: ["system:user:edit"],
children: [ children: [
{ {
path: 'role/:userId(\\d+)', path: "role/:userId(\\d+)",
component: () => import('@/views/system/user/authRole'), component: () => import("@/views/system/user/authRole"),
name: 'AuthRole', name: "AuthRole",
meta: { title: '分配角色', activeMenu: '/system/user' } meta: { title: "分配角色", activeMenu: "/system/user" },
} },
] ],
}, },
{ {
path: '/system/role-auth', path: "/system/role-auth",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['system:role:edit'], permissions: ["system:role:edit"],
children: [ children: [
{ {
path: 'user/:roleId(\\d+)', path: "user/:roleId(\\d+)",
component: () => import('@/views/system/role/authUser'), component: () => import("@/views/system/role/authUser"),
name: 'AuthUser', name: "AuthUser",
meta: { title: '分配用户', activeMenu: '/system/role' } meta: { title: "分配用户", activeMenu: "/system/role" },
} },
] ],
}, },
{ {
path: '/system/dict-data', path: "/system/dict-data",
component: Layout, component: Layout,
hidden: true, hidden: false,
permissions: ['system:dict:list'], // permissions: ["system:dict:list"],
children: [ children: [
{ {
path: 'index/:dictId(\\d+)', path: "index/:dictId(\\d+)",
component: () => import('@/views/system/dict/data'), component: () => import("@/views/system/dict/data"),
name: 'Data', name: "Data",
meta: { title: '字典数据', activeMenu: '/system/dict' } meta: { title: "字典数据", activeMenu: "/system/dict" },
} },
] ],
}, },
{ {
path: '/monitor/job-log', path: "/monitor/job-log",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['monitor:job:list'], permissions: ["monitor:job:list"],
children: [ children: [
{ {
path: 'index/:jobId(\\d+)', path: "index/:jobId(\\d+)",
component: () => import('@/views/monitor/job/log'), component: () => import("@/views/monitor/job/log"),
name: 'JobLog', name: "JobLog",
meta: { title: '调度日志', activeMenu: '/monitor/job' } meta: { title: "调度日志", activeMenu: "/monitor/job" },
} },
] ],
}, },
{ {
path: '/tool/gen-edit', path: "/tool/gen-edit",
component: Layout, component: Layout,
hidden: true, hidden: true,
permissions: ['tool:gen:edit'], permissions: ["tool:gen:edit"],
children: [ children: [
{ {
path: 'index/:tableId(\\d+)', path: "index/:tableId(\\d+)",
component: () => import('@/views/tool/gen/editTable'), component: () => import("@/views/tool/gen/editTable"),
name: 'GenEdit', name: "GenEdit",
meta: { title: '修改生成配置', activeMenu: '/tool/gen' } meta: { title: "修改生成配置", activeMenu: "/tool/gen" },
} },
] ],
} },
] ];
// 防止连续点击多次路由报错 // 防止连续点击多次路由报错
let routerPush = Router.prototype.push; let routerPush = Router.prototype.push;
let routerReplace = Router.prototype.replace; let routerReplace = Router.prototype.replace;
// push // push
Router.prototype.push = function push(location) { Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(err => err) return routerPush.call(this, location).catch((err) => err);
} };
// replace // replace
Router.prototype.replace = function push(location) { Router.prototype.replace = function push(location) {
return routerReplace.call(this, location).catch(err => err) return routerReplace.call(this, location).catch((err) => err);
} };
export default new Router({ export default new Router({
mode: 'history', // 去掉url中的# mode: "history", // 去掉url中的#
scrollBehavior: () => ({ y: 0 }), scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes routes: constantRoutes,
}) });

@ -1,114 +1,148 @@
import axios from 'axios' import axios from "axios";
import { Notification, MessageBox, Message, Loading } from 'element-ui' import { Notification, MessageBox, Message, Loading } from "element-ui";
import store from '@/store' import store from "@/store";
import { getToken } from '@/utils/auth' import { getToken } from "@/utils/auth";
import errorCode from '@/utils/errorCode' import errorCode from "@/utils/errorCode";
import { tansParams, blobValidate } from "@/utils/ruoyi"; import { tansParams, blobValidate } from "@/utils/ruoyi";
import cache from '@/plugins/cache' import cache from "@/plugins/cache";
import { saveAs } from 'file-saver' import { saveAs } from "file-saver";
let downloadLoadingInstance; let downloadLoadingInstance;
// 是否显示重新登录 // 是否显示重新登录
export let isRelogin = { show: false }; export let isRelogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例 // 创建axios实例
const service = axios.create({ const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分 // axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API, baseURL: process.env.VUE_APP_BASE_API,
// 超时 // 超时
timeout: 10000 timeout: 10000,
}) });
// request拦截器 // request拦截器
service.interceptors.request.use(config => { service.interceptors.request.use(
(config) => {
// 是否需要设置 token // 是否需要设置 token
const isToken = (config.headers || {}).isToken === false const isToken = (config.headers || {}).isToken === false;
// 是否需要防止数据重复提交 // 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) { if (getToken() && !isToken) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 config.headers["Authorization"] = "Bearer " + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
} }
// get请求映射params参数 // get请求映射params参数
if (config.method === 'get' && config.params) { if (config.method === "get" && config.params) {
let url = config.url + '?' + tansParams(config.params); let url = config.url + "?" + tansParams(config.params);
url = url.slice(0, -1); url = url.slice(0, -1);
config.params = {}; config.params = {};
config.url = url; config.url = url;
} }
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { if (
!isRepeatSubmit &&
(config.method === "post" || config.method === "put")
) {
const requestObj = { const requestObj = {
url: config.url, url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, data:
time: new Date().getTime() typeof config.data === "object"
} ? JSON.stringify(config.data)
: config.data,
time: new Date().getTime(),
};
const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小 const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 请求数据大小
const limitSize = 5 * 1024 * 1024; // 限制存放数据5M const limitSize = 5 * 1024 * 1024; // 限制存放数据5M
if (requestSize >= limitSize) { if (requestSize >= limitSize) {
console.warn(`[${config.url}]: ` + '请求数据大小超出允许的5M限制无法进行防重复提交验证。') console.warn(
`[${config.url}]: ` +
"请求数据大小超出允许的5M限制无法进行防重复提交验证。"
);
return config; return config;
} }
const sessionObj = cache.session.getJSON('sessionObj') const sessionObj = cache.session.getJSON("sessionObj");
if (sessionObj === undefined || sessionObj === null || sessionObj === '') { if (
cache.session.setJSON('sessionObj', requestObj) sessionObj === undefined ||
sessionObj === null ||
sessionObj === ""
) {
cache.session.setJSON("sessionObj", requestObj);
} else { } else {
const s_url = sessionObj.url; // 请求地址 const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据 const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间 const s_time = sessionObj.time; // 请求时间
const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { if (
const message = '数据正在处理,请勿重复提交'; s_data === requestObj.data &&
console.warn(`[${s_url}]: ` + message) requestObj.time - s_time < interval &&
return Promise.reject(new Error(message)) s_url === requestObj.url
) {
const message = "数据正在处理,请勿重复提交";
console.warn(`[${s_url}]: ` + message);
return Promise.reject(new Error(message));
} else { } else {
cache.session.setJSON('sessionObj', requestObj) cache.session.setJSON("sessionObj", requestObj);
} }
} }
} }
return config return config;
}, error => { },
console.log(error) (error) => {
Promise.reject(error) console.log(error);
}) Promise.reject(error);
}
);
// 响应拦截器 // 响应拦截器
service.interceptors.response.use(res => { service.interceptors.response.use(
(res) => {
// 未设置状态码则默认成功状态 // 未设置状态码则默认成功状态
const code = res.data.code || 200; const code = res.data.code || 200;
// 获取错误信息 // 获取错误信息
const msg = errorCode[code] || res.data.msg || errorCode['default'] const msg = errorCode[code] || res.data.msg || errorCode["default"];
// 二进制数据则直接返回 // 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { if (
return res.data res.request.responseType === "blob" ||
res.request.responseType === "arraybuffer"
) {
return res.data;
} }
if (code === 401) { if (code === 401) {
if (!isRelogin.show) { if (!isRelogin.show) {
isRelogin.show = true; isRelogin.show = true;
MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { MessageBox.confirm(
"登录状态已过期,您可以继续留在该页面,或者重新登录",
"系统提示",
{
confirmButtonText: "重新登录",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
isRelogin.show = false; isRelogin.show = false;
store.dispatch('LogOut').then(() => { store.dispatch("LogOut").then(() => {
location.href = '/index'; location.href = "/index";
});
}) })
}).catch(() => { .catch(() => {
isRelogin.show = false; isRelogin.show = false;
}); });
} }
return Promise.reject('无效的会话,或者会话已过期,请重新登录。') return Promise.reject("无效的会话,或者会话已过期,请重新登录。");
} else if (code === 500) { } else if (code === 500) {
Message({ message: msg, type: 'error' }) Message({ message: msg, type: "error" });
return Promise.reject(new Error(msg)) return Promise.reject(new Error(msg));
} else if (code === 601) { } else if (code === 601) {
Message({ message: msg, type: 'warning' }) Message({ message: msg, type: "warning" });
return Promise.reject('error') return Promise.reject("error");
} else if (code !== 200) { } else if (code !== 200) {
Notification.error({ title: msg }) Notification.error({ title: msg });
return Promise.reject('error') return Promise.reject("error");
} else { } else {
return res.data return res.data;
} }
}, },
error => { (error) => {
console.log('err' + error) console.log("err" + error);
let { message } = error; let { message } = error;
if (message == "Network Error") { if (message == "Network Error") {
message = "后端接口连接异常"; message = "后端接口连接异常";
@ -117,36 +151,48 @@ service.interceptors.response.use(res => {
} else if (message.includes("Request failed with status code")) { } else if (message.includes("Request failed with status code")) {
message = "系统接口" + message.substr(message.length - 3) + "异常"; message = "系统接口" + message.substr(message.length - 3) + "异常";
} }
Message({ message: message, type: 'error', duration: 5 * 1000 }) Message({ message: message, type: "error", duration: 5 * 1000 });
return Promise.reject(error) return Promise.reject(error);
} }
) );
// 通用下载方法 // 通用下载方法
export function download(url, params, filename, config) { export function download(url, params, filename, config) {
downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) downloadLoadingInstance = Loading.service({
return service.post(url, params, { text: "正在下载数据,请稍候",
transformRequest: [(params) => { return tansParams(params) }], spinner: "el-icon-loading",
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, background: "rgba(0, 0, 0, 0.7)",
responseType: 'blob', });
...config return service
}).then(async (data) => { .post(url, params, {
transformRequest: [
(params) => {
return tansParams(params);
},
],
headers: { "Content-Type": "application/x-www-form-urlencoded" },
responseType: "blob",
...config,
})
.then(async (data) => {
const isBlob = blobValidate(data); const isBlob = blobValidate(data);
if (isBlob) { if (isBlob) {
const blob = new Blob([data]) const blob = new Blob([data]);
saveAs(blob, filename) saveAs(blob, filename);
} else { } else {
const resText = await data.text(); const resText = await data.text();
const rspObj = JSON.parse(resText); const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] const errMsg =
errorCode[rspObj.code] || rspObj.msg || errorCode["default"];
Message.error(errMsg); Message.error(errMsg);
} }
downloadLoadingInstance.close(); downloadLoadingInstance.close();
}).catch((r) => {
console.error(r)
Message.error('下载文件出现错误,请联系管理员!')
downloadLoadingInstance.close();
}) })
.catch((r) => {
console.error(r);
Message.error("下载文件出现错误,请联系管理员!");
downloadLoadingInstance.close();
});
} }
export default service export default service;

@ -1,6 +1,11 @@
<template> <template>
<div class="login"> <div class="login">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> <el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
>
<h3 class="title">花至后台管理系统</h3> <h3 class="title">花至后台管理系统</h3>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input
@ -9,7 +14,11 @@
auto-complete="off" auto-complete="off"
placeholder="账号" placeholder="账号"
> >
<svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> <svg-icon
slot="prefix"
icon-class="user"
class="el-input__icon input-icon"
/>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
@ -20,7 +29,11 @@
placeholder="密码" placeholder="密码"
@keyup.enter.native="handleLogin" @keyup.enter.native="handleLogin"
> >
<svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> <svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code" v-if="captchaEnabled"> <el-form-item prop="code" v-if="captchaEnabled">
@ -31,26 +44,36 @@
style="width: 63%" style="width: 63%"
@keyup.enter.native="handleLogin" @keyup.enter.native="handleLogin"
> >
<svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> <svg-icon
slot="prefix"
icon-class="validCode"
class="el-input__icon input-icon"
/>
</el-input> </el-input>
<div class="login-code"> <div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img" /> <img :src="codeUrl" @click="getCode" class="login-code-img" />
</div> </div>
</el-form-item> </el-form-item>
<el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;"></el-checkbox> <el-checkbox
<el-form-item style="width:100%;"> v-model="loginForm.rememberMe"
style="margin: 0px 0px 25px 0px"
>记住密码</el-checkbox
>
<el-form-item style="width: 100%">
<el-button <el-button
:loading="loading" :loading="loading"
size="medium" size="medium"
type="primary" type="primary"
style="width:100%;" style="width: 100%"
@click.native.prevent="handleLogin" @click.native.prevent="handleLogin"
> >
<span v-if="!loading"> </span> <span v-if="!loading"> </span>
<span v-else> ...</span> <span v-else> ...</span>
</el-button> </el-button>
<div style="float: right;" v-if="register"> <div style="float: right" v-if="register">
<router-link class="link-type" :to="'/register'">立即注册</router-link> <router-link class="link-type" :to="'/register'"
>立即注册</router-link
>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -62,97 +85,106 @@
</template> </template>
<script> <script>
import { getCodeImg } from "@/api/login"; import { getCodeImg } from '@/api/login'
import Cookies from "js-cookie"; import Cookies from 'js-cookie'
import { encrypt, decrypt } from '@/utils/jsencrypt' import { encrypt, decrypt } from '@/utils/jsencrypt'
export default { export default {
name: "Login", name: 'Login',
data() { data() {
return { return {
codeUrl: "", codeUrl: '',
loginForm: { loginForm: {
username: "admin", username: 'admin',
password: "admin123", password: 'admin123',
rememberMe: false, rememberMe: false,
code: "", code: '',
uuid: "" uuid: '',
}, },
loginRules: { loginRules: {
username: [ username: [
{ required: true, trigger: "blur", message: "请输入您的账号" } { required: true, trigger: 'blur', message: '请输入您的账号' },
], ],
password: [ password: [
{ required: true, trigger: "blur", message: "请输入您的密码" } { required: true, trigger: 'blur', message: '请输入您的密码' },
], ],
code: [{ required: true, trigger: "change", message: "请输入验证码" }] code: [{ required: true, trigger: 'change', message: '请输入验证码' }],
}, },
loading: false, loading: false,
// //
captchaEnabled: true, captchaEnabled: true,
// //
register: false, register: false,
redirect: undefined redirect: undefined,
}; }
}, },
watch: { watch: {
$route: { $route: {
handler: function (route) { handler: function (route) {
this.redirect = route.query && route.query.redirect; this.redirect = route.query && route.query.redirect
},
immediate: true,
}, },
immediate: true
}
}, },
created() { created() {
this.getCode(); this.getCode()
this.getCookie(); this.getCookie()
}, },
methods: { methods: {
getCode() { getCode() {
getCodeImg().then(res => { getCodeImg().then((res) => {
this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; this.captchaEnabled =
res.captchaEnabled === undefined ? true : res.captchaEnabled
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.codeUrl = "data:image/gif;base64," + res.img; this.codeUrl = 'data:image/gif;base64,' + res.img
this.loginForm.uuid = res.uuid; this.loginForm.uuid = res.uuid
} }
}); })
}, },
getCookie() { getCookie() {
const username = Cookies.get("username"); const username = Cookies.get('username')
const password = Cookies.get("password"); const password = Cookies.get('password')
const rememberMe = Cookies.get('rememberMe') const rememberMe = Cookies.get('rememberMe')
this.loginForm = { this.loginForm = {
username: username === undefined ? this.loginForm.username : username, username: username === undefined ? this.loginForm.username : username,
password: password === undefined ? this.loginForm.password : decrypt(password), password:
rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) password === undefined ? this.loginForm.password : decrypt(password),
}; rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
}
}, },
handleLogin() { handleLogin() {
this.$refs.loginForm.validate(valid => { this.$refs.loginForm.validate((valid) => {
if (valid) { if (valid) {
this.loading = true; this.loading = true
if (this.loginForm.rememberMe) { if (this.loginForm.rememberMe) {
Cookies.set("username", this.loginForm.username, { expires: 30 }); Cookies.set('username', this.loginForm.username, { expires: 30 })
Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }); Cookies.set('password', encrypt(this.loginForm.password), {
Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }); expires: 30,
})
Cookies.set('rememberMe', this.loginForm.rememberMe, {
expires: 30,
})
} else { } else {
Cookies.remove("username"); Cookies.remove('username')
Cookies.remove("password"); Cookies.remove('password')
Cookies.remove('rememberMe'); Cookies.remove('rememberMe')
} }
this.$store.dispatch("Login", this.loginForm).then(() => { this.$store
this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); .dispatch('Login', this.loginForm)
}).catch(() => { .then(() => {
this.loading = false; this.$router.push({ path: this.redirect || '/' }).catch(() => {})
})
.catch(() => {
this.loading = false
if (this.captchaEnabled) { if (this.captchaEnabled) {
this.getCode(); this.getCode()
}
});
} }
}); })
} }
})
},
},
} }
};
</script> </script>
<style rel="stylesheet/scss" lang="scss"> <style rel="stylesheet/scss" lang="scss">
@ -161,7 +193,7 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 100%; height: 100%;
background-image: url("../assets/images/login-background.jpg"); background-image: url('../assets/images/login-background.jpg');
background-size: cover; background-size: cover;
} }
.title { .title {

@ -5,7 +5,12 @@
<el-form ref="form" :model="userAgreementFrom" label-width="80px"> <el-form ref="form" :model="userAgreementFrom" label-width="80px">
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="userAgreementFrom.userAgreement" :min-height="580"/> <editor
id="editor1"
tableName="editor1"
v-model="userAgreementFrom.userAgreement"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
@ -14,7 +19,12 @@
<el-form ref="form" :model="privacyAgreementFrom" label-width="80px"> <el-form ref="form" :model="privacyAgreementFrom" label-width="80px">
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="privacyAgreementFrom.privacyAgreement" :min-height="580"/> <editor
id="editor2"
tableName="editor2"
v-model="privacyAgreementFrom.privacyAgreement"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
@ -23,7 +33,12 @@
<el-form ref="form" :model="integralRuleFrom" label-width="80px"> <el-form ref="form" :model="integralRuleFrom" label-width="80px">
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="integralRuleFrom.integralRule" :min-height="580"/> <editor
id="editor3"
tableName="editor3"
v-model="integralRuleFrom.integralRule"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
@ -32,37 +47,68 @@
<el-form ref="form" :model="aboutUsFrom" label-width="80px"> <el-form ref="form" :model="aboutUsFrom" label-width="80px">
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="aboutUsFrom.aboutUs" :min-height="580"/> <editor
id="editor4"
tableName="editor4"
v-model="aboutUsFrom.aboutUs"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="蓝牙指引权限" name="bluetoothGuidancePermissions"> <el-tab-pane label="蓝牙指引权限" name="bluetoothGuidancePermissions">
<el-form ref="form" :model="bluetoothGuidancePermissionsFrom" label-width="80px"> <el-form
ref="form"
:model="bluetoothGuidancePermissionsFrom"
label-width="80px"
>
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions" :min-height="580"/> <editor
id="editor5"
tableName="editor5"
v-model="
bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions
"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="定位指引权限" name="locationGuidancePermissions"> <el-tab-pane label="定位指引权限" name="locationGuidancePermissions">
<el-form ref="form" :model="locationGuidancePermissionsFrom" label-width="80px"> <el-form
ref="form"
:model="locationGuidancePermissionsFrom"
label-width="80px"
>
<el-row> <el-row>
<el-col :span="20"> <el-col :span="20">
<editor v-model="locationGuidancePermissionsFrom.locationGuidancePermissions" :min-height="580"/> <editor
id="editor6"
tableName="editor6"
v-model="
locationGuidancePermissionsFrom.locationGuidancePermissions
"
:min-height="580"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="联系客服" name="contactWorker"> <el-tab-pane label="联系客服" name="contactWorker">
<div class="block" style="float: left; margin-left: 3%; margin-top: 3%"> <div class="block" style="float: left; margin-left: 3%; margin-top: 3%">
<el-image :src="contactWorkerFrom.contactWorkerSrc" style="width: 330px;height: 461px;"> <el-image
<div slot="placeholder" class="image-slot"><span class="dot"></span> :src="contactWorkerFrom.contactWorkerSrc"
style="width: 330px; height: 461px"
>
<div slot="placeholder" class="image-slot">
<span class="dot"></span>
</div> </div>
</el-image> </el-image>
</div> </div>
<div style="float: left;margin-left: 10%;margin-top: 10%;"> <div style="float: left; margin-left: 10%; margin-top: 10%">
<el-upload <el-upload
ref="upload" ref="upload"
:limit="1" :limit="1"
@ -75,41 +121,72 @@
drag drag
> >
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">
<div class="el-upload__tip" slot="tip">请上传联系客服页面图片建议尺寸为330px*461px</div> 将文件拖到此处<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
请上传联系客服页面图片建议尺寸为330px*461px
</div>
</el-upload> </el-upload>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="商城链接/版本管理" name="otherSetting"> <el-tab-pane label="商城链接/版本管理" name="otherSetting">
<el-form ref="form" :model="otherForm" :rules="rules" label-width="150px" style="margin-top: 1%"> <el-form
ref="form"
:model="otherForm"
:rules="rules"
label-width="150px"
style="margin-top: 1%"
>
<el-divider content-position="left">商城设置</el-divider> <el-divider content-position="left">商城设置</el-divider>
<el-form-item label="跳转商城appid" prop="skipAppid"> <el-form-item label="跳转商城appid" prop="skipAppid">
<el-input v-model="otherForm.skipAppid" style="width: 70%"></el-input> <el-input
v-model="otherForm.skipAppid"
style="width: 70%"
></el-input>
</el-form-item> </el-form-item>
<el-form-item label="跳转商城路径:" prop="skipPath"> <el-form-item label="跳转商城路径:" prop="skipPath">
<el-input v-model="otherForm.skipPath" style="width: 70%"></el-input> <el-input
v-model="otherForm.skipPath"
style="width: 70%"
></el-input>
</el-form-item> </el-form-item>
<el-divider content-position="left">版本管理设置</el-divider> <el-divider content-position="left">版本管理设置</el-divider>
<el-form-item label="当前版本:" prop="sysVersion"> <el-form-item label="当前版本:" prop="sysVersion">
<el-input v-model="otherForm.sysVersion" style="width: 70%"></el-input> <el-input
v-model="otherForm.sysVersion"
style="width: 70%"
></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<div style="margin-left: 76%;margin-top: 2%" v-show="this.activeName != 'contactWorker'"> <div
style="margin-left: 76%; margin-top: 2%"
v-show="this.activeName != 'contactWorker'"
>
<el-button type="primary" @click="submitForm"> </el-button> <el-button type="primary" @click="submitForm"> </el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { listSetting, getSetting, delSetting, addSetting, updateSetting } from "@/api/system/systemSetting"; import {
import { listOtherSetting, addOtherSetting, updateOtherSetting} from "@/api/system/otherSetting"; listSetting,
import {getToken} from "@/utils/auth"; getSetting,
delSetting,
addSetting,
updateSetting,
} from '@/api/system/systemSetting'
import {
listOtherSetting,
addOtherSetting,
updateOtherSetting,
} from '@/api/system/otherSetting'
import { getToken } from '@/utils/auth'
export default { export default {
name: "Setting", name: 'Setting',
data() { data() {
return { return {
// //
@ -128,7 +205,7 @@ export default {
// //
settingList: [], settingList: [],
// //
title: "", title: '',
activeName: 'userAgreement', activeName: 'userAgreement',
// //
open: false, open: false,
@ -137,15 +214,15 @@ export default {
// //
open: false, open: false,
// //
title: "", title: '',
// //
isUploading: false, isUploading: false,
// //
updateSupport: 0, updateSupport: 0,
// //
headers: { Authorization: "Bearer " + getToken() }, headers: { Authorization: 'Bearer ' + getToken() },
// //
url: process.env.VUE_APP_BASE_API + "/file/upload" url: process.env.VUE_APP_BASE_API + '/file/upload',
}, },
// //
queryParams: { queryParams: {
@ -165,15 +242,11 @@ export default {
status: null, status: null,
}, },
// //
form: { form: {},
otherForm: {},
},
otherForm: {
},
userAgreementFrom: { userAgreementFrom: {
userAgreement: null, userAgreement: null,
userAgreementId: null userAgreementId: null,
}, },
privacyAgreementFrom: { privacyAgreementFrom: {
privacyAgreement: null, privacyAgreement: null,
@ -193,11 +266,11 @@ export default {
}, },
locationGuidancePermissionsFrom: { locationGuidancePermissionsFrom: {
locationGuidancePermissions: null, locationGuidancePermissions: null,
locationGuidancePermissionsId: null locationGuidancePermissionsId: null,
}, },
contactWorkerFrom: { contactWorkerFrom: {
contactWorkerSrc: null, contactWorkerSrc: null,
contactWorkerId: null contactWorkerId: null,
}, },
// //
rules: { rules: {
@ -210,176 +283,197 @@ export default {
sysVersion: [ sysVersion: [
{ required: true, message: '请输入当前版本', trigger: 'blur' }, { required: true, message: '请输入当前版本', trigger: 'blur' },
], ],
},
} }
};
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
handleClick(tab, event) { handleClick(tab, event) {
console.log(tab, event); console.log(tab, event)
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
if (this.activeName == 'userAgreement') { if (this.activeName == 'userAgreement') {
if (this.userAgreementFrom.userAgreementId != null) { if (this.userAgreementFrom.userAgreementId != null) {
this.form.id = this.userAgreementFrom.userAgreementId; this.form.id = this.userAgreementFrom.userAgreementId
} }
this.form.key = 'USER_AGREEMENT'; this.form.key = 'USER_AGREEMENT'
if (!this.userAgreementFrom.userAgreement) { if (!this.userAgreementFrom.userAgreement) {
this.$modal.msgError('用户协议内容不能为空'); this.$modal.msgError('用户协议内容不能为空')
return ; return
} }
this.form.value = this.userAgreementFrom.userAgreement; this.form.value = this.userAgreementFrom.userAgreement
this.form.instructions = '用户协议'; this.form.instructions = '用户协议'
} }
if (this.activeName == 'privacyAgreement') { if (this.activeName == 'privacyAgreement') {
if (this.privacyAgreementFrom.privacyAgreementId != null) { if (this.privacyAgreementFrom.privacyAgreementId != null) {
this.form.id = this.privacyAgreementFrom.privacyAgreementId; this.form.id = this.privacyAgreementFrom.privacyAgreementId
} }
this.form.key = 'PRIVACY_AGREEMENT'; this.form.key = 'PRIVACY_AGREEMENT'
if (!this.privacyAgreementFrom.privacyAgreement) { if (!this.privacyAgreementFrom.privacyAgreement) {
this.$modal.msgError('隐私协议内容不能为空'); this.$modal.msgError('隐私协议内容不能为空')
return ; return
} }
this.form.instructions = '隐私协议'; this.form.instructions = '隐私协议'
this.form.value = this.privacyAgreementFrom.privacyAgreement; this.form.value = this.privacyAgreementFrom.privacyAgreement
} }
if (this.activeName == 'integralRule') { if (this.activeName == 'integralRule') {
if (this.integralRuleFrom.integralRuleId != null) { if (this.integralRuleFrom.integralRuleId != null) {
this.form.id = this.integralRuleFrom.integralRuleId; this.form.id = this.integralRuleFrom.integralRuleId
} }
this.form.key = 'INTEGRAL_RULE'; this.form.key = 'INTEGRAL_RULE'
if (!this.integralRuleFrom.integralRule) { if (!this.integralRuleFrom.integralRule) {
this.$modal.msgError('积分规则内容不能为空'); this.$modal.msgError('积分规则内容不能为空')
return ; return
} }
this.form.instructions = '积分规则'; this.form.instructions = '积分规则'
this.form.value = this.integralRuleFrom.integralRule; this.form.value = this.integralRuleFrom.integralRule
} }
if (this.activeName == 'aboutUs') { if (this.activeName == 'aboutUs') {
if (this.aboutUsFrom.aboutUsId != null) { if (this.aboutUsFrom.aboutUsId != null) {
this.form.id = this.aboutUsFrom.aboutUsId; this.form.id = this.aboutUsFrom.aboutUsId
} }
this.form.key = 'ABOUT_US'; this.form.key = 'ABOUT_US'
if (!this.aboutUsFrom.aboutUs) { if (!this.aboutUsFrom.aboutUs) {
this.$modal.msgError('关于我们内容不能为空'); this.$modal.msgError('关于我们内容不能为空')
return ; return
} }
this.form.instructions = '关于我们'; this.form.instructions = '关于我们'
this.form.value = this.aboutUsFrom.aboutUs; this.form.value = this.aboutUsFrom.aboutUs
} }
if (this.activeName == 'bluetoothGuidancePermissions') { if (this.activeName == 'bluetoothGuidancePermissions') {
if (this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissionsId != null) { if (
this.form.id = this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissionsId; this.bluetoothGuidancePermissionsFrom
} .bluetoothGuidancePermissionsId != null
this.form.key = 'BLUETOOTH_GUIDANCE_PERMISSIONS'; ) {
if (!this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions) { this.form.id =
this.$modal.msgError('蓝牙指引权限内容不能为空'); this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissionsId
return ; }
} this.form.key = 'BLUETOOTH_GUIDANCE_PERMISSIONS'
this.form.instructions = '蓝牙指引权限'; if (
this.form.value = this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions; !this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions
) {
this.$modal.msgError('蓝牙指引权限内容不能为空')
return
}
this.form.instructions = '蓝牙指引权限'
this.form.value =
this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions
} }
if (this.activeName == 'locationGuidancePermissions') { if (this.activeName == 'locationGuidancePermissions') {
if (this.locationGuidancePermissionsFrom.locationGuidancePermissionsId != null) { if (
this.form.id = this.locationGuidancePermissionsFrom.locationGuidancePermissionsId; this.locationGuidancePermissionsFrom.locationGuidancePermissionsId !=
} null
this.form.key = 'LOCATION_GUIDANCE_PERMISSIONS'; ) {
this.form.id =
this.locationGuidancePermissionsFrom.locationGuidancePermissionsId
}
this.form.key = 'LOCATION_GUIDANCE_PERMISSIONS'
if (!this.locationGuidancePermissionsFrom.locationGuidancePermissions) { if (!this.locationGuidancePermissionsFrom.locationGuidancePermissions) {
this.$modal.msgError('定位指引权限内容不能为空'); this.$modal.msgError('定位指引权限内容不能为空')
return ; return
} }
this.form.instructions = '定位指引权限'; this.form.instructions = '定位指引权限'
this.form.value = this.locationGuidancePermissionsFrom.locationGuidancePermissions; this.form.value =
this.locationGuidancePermissionsFrom.locationGuidancePermissions
} }
if (this.form.value) {
this.form.value = this.form.value.replace(/\\/g, '') //
console.log(" this.form.value", this.form.value)
}
if (this.activeName != 'otherSetting') { if (this.activeName != 'otherSetting') {
if (this.form.id != null) { if (this.form.id != null) {
updateSetting(this.form).then(response => { updateSetting(this.form).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess('修改成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
addSetting(this.form).then(response => { addSetting(this.form).then((response) => {
this.$modal.msgSuccess("保存成功"); this.$modal.msgSuccess('保存成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
this.form.id = null; this.form.id = null
this.form.value = null; this.form.value = null
} else { } else {
this.$refs["form"].validate(valid => { this.$refs['form'].validate((valid) => {
if (valid) { if (valid) {
// //
if (this.otherForm.id != null) { if (this.otherForm.id != null) {
updateOtherSetting(this.otherForm).then(response => { updateOtherSetting(this.otherForm).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess('修改成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
addOtherSetting(this.otherForm).then(response => { addOtherSetting(this.otherForm).then((response) => {
this.$modal.msgSuccess("保存成功"); this.$modal.msgSuccess('保存成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
} }
}); })
} }
}, },
/** 查询平台参数设置列表 */ /** 查询平台参数设置列表 */
/** USER_AGREEMENT-用户协议 PRIVACY_AGREEMENT-隐私协议 INTEGRAL_RULE-积分规则 ABOUT_US-关于我们 BLUETOOTH_GUIDANCE_PERMISSIONS-蓝牙指引权限 LOCATION_GUIDANCE_PERMISSIONS - 定位指引权限 CONTACT_WORKER-联系客服 */ /** USER_AGREEMENT-用户协议 PRIVACY_AGREEMENT-隐私协议 INTEGRAL_RULE-积分规则 ABOUT_US-关于我们 BLUETOOTH_GUIDANCE_PERMISSIONS-蓝牙指引权限 LOCATION_GUIDANCE_PERMISSIONS - 定位指引权限 CONTACT_WORKER-联系客服 */
getList() { getList() {
this.loading = true; this.loading = true
listSetting(this.queryParams).then(response => { listSetting(this.queryParams).then((response) => {
this.settingList = response.rows; this.settingList = JSON.parse(JSON.stringify(response.rows))
this.total = response.total; this.total = response.total
this.loading = false; this.loading = false
// //
this.settingList.forEach((item) => { this.settingList.forEach((item) => {
if (item.key == 'USER_AGREEMENT') { if (item.key == 'USER_AGREEMENT') {
this.userAgreementFrom.userAgreement = item.value; this.userAgreementFrom.userAgreement = item.value
this.userAgreementFrom.userAgreementId = item.id; this.userAgreementFrom.userAgreementId = item.id
} }
if (item.key == 'PRIVACY_AGREEMENT') { if (item.key == 'PRIVACY_AGREEMENT') {
this.privacyAgreementFrom.privacyAgreement = item.value; this.privacyAgreementFrom.privacyAgreement = item.value
this.privacyAgreementFrom.privacyAgreementId = item.id; this.privacyAgreementFrom.privacyAgreementId = item.id
} }
if (item.key == 'INTEGRAL_RULE') { if (item.key == 'INTEGRAL_RULE') {
this.integralRuleFrom.integralRule = item.value; this.integralRuleFrom.integralRule = item.value
this.integralRuleFrom.integralRuleId = item.id; this.integralRuleFrom.integralRuleId = item.id
} }
if (item.key == 'ABOUT_US') { if (item.key == 'ABOUT_US') {
this.aboutUsFrom.aboutUs = item.value; this.aboutUsFrom.aboutUs = item.value
this.aboutUsFrom.aboutUsId = item.id; this.aboutUsFrom.aboutUsId = item.id
} }
if (item.key == 'BLUETOOTH_GUIDANCE_PERMISSIONS') { if (item.key == 'BLUETOOTH_GUIDANCE_PERMISSIONS') {
this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions = item.value; this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissions =
this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissionsId = item.id; item.value
this.bluetoothGuidancePermissionsFrom.bluetoothGuidancePermissionsId =
item.id
} }
if (item.key == 'LOCATION_GUIDANCE_PERMISSIONS') { if (item.key == 'LOCATION_GUIDANCE_PERMISSIONS') {
this.locationGuidancePermissionsFrom.locationGuidancePermissions = item.value; this.locationGuidancePermissionsFrom.locationGuidancePermissions =
this.locationGuidancePermissionsFrom.locationGuidancePermissionsId = item.id; item.value
this.locationGuidancePermissionsFrom.locationGuidancePermissionsId =
item.id
} }
if (item.key == 'CONTACT_WORKER') { if (item.key == 'CONTACT_WORKER') {
this.contactWorkerFrom.contactWorkerSrc = item.pictureUrl; this.contactWorkerFrom.contactWorkerSrc = item.pictureUrl
this.contactWorkerFrom.contactWorkerId = item.id; this.contactWorkerFrom.contactWorkerId = item.id
} }
}) })
}); })
listOtherSetting(this.otherQueryParams).then(response => { listOtherSetting(this.otherQueryParams).then((response) => {
this.otherForm = response.rows.length >0 ? response.rows[0]: {}; this.otherForm = response.rows.length > 0 ? response.rows[0] : {}
this.loading = false; this.loading = false
}); })
}, },
// //
cancel() { cancel() {
this.open = false; this.open = false
this.reset(); this.reset()
}, },
// //
reset() { reset() {
@ -393,41 +487,41 @@ export default {
createTime: null, createTime: null,
updateBy: null, updateBy: null,
updateTime: null, updateTime: null,
remark: null remark: null,
}; }
this.resetForm("form"); this.resetForm('form')
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1
this.getList(); this.getList()
}, },
/** 重置按钮操作 */ /** 重置按钮操作 */
resetQuery() { resetQuery() {
this.resetForm("queryForm"); this.resetForm('queryForm')
this.handleQuery(); this.handleQuery()
}, },
// //
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.ids = selection.map(item => item.id) this.ids = selection.map((item) => item.id)
this.single = selection.length !== 1 this.single = selection.length !== 1
this.multiple = !selection.length this.multiple = !selection.length
}, },
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset(); this.reset()
this.open = true; this.open = true
this.title = "添加平台参数设置"; this.title = '添加平台参数设置'
}, },
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset(); this.reset()
const id = row.id || this.ids const id = row.id || this.ids
getSetting(id).then(response => { getSetting(id).then((response) => {
this.form = response.data; this.form = response.data
this.open = true; this.open = true
this.title = "修改平台参数设置"; this.title = '修改平台参数设置'
}); })
}, },
// //
handleFileUploadProgress(event, file, fileList) { handleFileUploadProgress(event, file, fileList) {
@ -438,29 +532,29 @@ export default {
handleFileSuccess(response, file, fileList) { handleFileSuccess(response, file, fileList) {
console.log('上传后的结果==>', JSON.stringify(response)) console.log('上传后的结果==>', JSON.stringify(response))
if (response.code == '200') { if (response.code == '200') {
this.contactWorkerFrom.contactWorkerSrc = response.data.url; this.contactWorkerFrom.contactWorkerSrc = response.data.url
this.form.key = 'CONTACT_WORKER'; this.form.key = 'CONTACT_WORKER'
this.form.instructions = '联系客服'; this.form.instructions = '联系客服'
this.form.pictureUrl = this.contactWorkerFrom.contactWorkerSrc; this.form.pictureUrl = this.contactWorkerFrom.contactWorkerSrc
if (this.contactWorkerFrom.contactWorkerId != null) { if (this.contactWorkerFrom.contactWorkerId != null) {
this.form.id = this.contactWorkerFrom.contactWorkerId; this.form.id = this.contactWorkerFrom.contactWorkerId
} }
// //
if (this.form.id != null) { if (this.form.id != null) {
updateSetting(this.form).then(response => { updateSetting(this.form).then((response) => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess('修改成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} else { } else {
addSetting(this.form).then(response => { addSetting(this.form).then((response) => {
this.$modal.msgSuccess("保存成功"); this.$modal.msgSuccess('保存成功')
this.open = false; this.open = false
this.getList(); this.getList()
}); })
} }
this.form.id = null; this.form.id = null
this.form.pictureUrl = null; this.form.pictureUrl = null
} }
// this.upload.open = false; // this.upload.open = false;
// this.upload.isUploading = false; // this.upload.isUploading = false;
@ -470,20 +564,28 @@ export default {
}, },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const ids = row.id || this.ids; const ids = row.id || this.ids
this.$modal.confirm('是否确认删除平台参数设置编号为"' + ids + '"的数据项?').then(function() { this.$modal
return delSetting(ids); .confirm('是否确认删除平台参数设置编号为"' + ids + '"的数据项?')
}).then(() => { .then(function () {
this.getList(); return delSetting(ids)
this.$modal.msgSuccess("删除成功"); })
}).catch(() => {}); .then(() => {
this.getList()
this.$modal.msgSuccess('删除成功')
})
.catch(() => {})
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
this.download('system/setting/export', { this.download(
...this.queryParams 'system/setting/export',
}, `setting_${new Date().getTime()}.xlsx`) {
} ...this.queryParams,
},
`setting_${new Date().getTime()}.xlsx`
)
},
},
} }
};
</script> </script>

@ -1,15 +1,23 @@
'use strict' "use strict";
const path = require('path') const path = require("path");
function resolve(dir) { function resolve(dir) {
return path.join(__dirname, dir) return path.join(__dirname, dir);
} }
const CompressionPlugin = require('compression-webpack-plugin') const CompressionPlugin = require("compression-webpack-plugin");
const name = process.env.VUE_APP_TITLE || '花至管理系统' // 网页标题 const name = process.env.VUE_APP_TITLE || "花至管理系统"; // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口 const port = process.env.port || process.env.npm_config_port || 80; // 端口
function getTargetUrl() {
if (process.env.NODE_ENV === "local") {
return "http://110.41.134.131:8080";
} else {
return `http://localhost:8080`;
}
}
// vue.config.js 配置说明 // vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions //官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions
@ -20,115 +28,116 @@ module.exports = {
// 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
publicPath: process.env.NODE_ENV === "production" ? "/" : "/", publicPath: process.env.NODE_ENV === "production" ? "/" : "/",
// 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist // 在npm run build 或 yarn build 时 生成文件的目录名称要和baseUrl的生产环境路径一致默认dist
outputDir: 'dist', outputDir: "dist",
// 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
assetsDir: 'static', assetsDir: "static",
// 是否开启eslint保存检测有效值ture | false | 'error' // 是否开启eslint保存检测有效值ture | false | 'error'
lintOnSave: process.env.NODE_ENV === 'development', lintOnSave: process.env.NODE_ENV === "development",
// 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。 // 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。
productionSourceMap: false, productionSourceMap: false,
// webpack-dev-server 相关配置 // webpack-dev-server 相关配置
devServer: { devServer: {
host: '0.0.0.0', host: "0.0.0.0",
port: port, port: port,
open: true, open: true,
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: { [process.env.VUE_APP_BASE_API]: {
target: `http://localhost:8080`, // target: `http://110.41.134.131:8080`,
target: `http://192.168.10.147:8080`,
changeOrigin: true, changeOrigin: true,
pathRewrite: { pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '' ["^" + process.env.VUE_APP_BASE_API]: "",
} },
} },
}, },
disableHostCheck: true disableHostCheck: true,
}, },
css: { css: {
loaderOptions: { loaderOptions: {
sass: { sass: {
sassOptions: { outputStyle: "expanded" } sassOptions: { outputStyle: "expanded" },
} },
} },
}, },
configureWebpack: { configureWebpack: {
name: name, name: name,
resolve: { resolve: {
alias: { alias: {
'@': resolve('src') "@": resolve("src"),
} },
}, },
plugins: [ plugins: [
// http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
new CompressionPlugin({ new CompressionPlugin({
cache: false, // 不启用文件缓存 cache: false, // 不启用文件缓存
test: /\.(js|css|html)?$/i, // 压缩文件格式 test: /\.(js|css|html)?$/i, // 压缩文件格式
filename: '[path].gz[query]', // 压缩后的文件名 filename: "[path].gz[query]", // 压缩后的文件名
algorithm: 'gzip', // 使用gzip压缩 algorithm: "gzip", // 使用gzip压缩
minRatio: 0.8 // 压缩率小于1才会压缩 minRatio: 0.8, // 压缩率小于1才会压缩
}) }),
], ],
}, },
chainWebpack(config) { chainWebpack(config) {
config.plugins.delete('preload') // TODO: need test config.plugins.delete("preload"); // TODO: need test
config.plugins.delete('prefetch') // TODO: need test config.plugins.delete("prefetch"); // TODO: need test
// set svg-sprite-loader // set svg-sprite-loader
config.module.rule("svg").exclude.add(resolve("src/assets/icons")).end();
config.module config.module
.rule('svg') .rule("icons")
.exclude.add(resolve('src/assets/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/) .test(/\.svg$/)
.include.add(resolve('src/assets/icons')) .include.add(resolve("src/assets/icons"))
.end() .end()
.use('svg-sprite-loader') .use("svg-sprite-loader")
.loader('svg-sprite-loader') .loader("svg-sprite-loader")
.options({ .options({
symbolId: 'icon-[name]' symbolId: "icon-[name]",
}) })
.end() .end();
config.when(process.env.NODE_ENV !== 'development', config => { config.when(process.env.NODE_ENV !== "development", (config) => {
config config
.plugin('ScriptExtHtmlWebpackPlugin') .plugin("ScriptExtHtmlWebpackPlugin")
.after('html') .after("html")
.use('script-ext-html-webpack-plugin', [{ .use("script-ext-html-webpack-plugin", [
{
// `runtime` must same as runtimeChunk name. default is `runtime` // `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/ inline: /runtime\..*\.js$/,
}]) },
.end() ])
.end();
config.optimization.splitChunks({ config.optimization.splitChunks({
chunks: 'all', chunks: "all",
cacheGroups: { cacheGroups: {
libs: { libs: {
name: 'chunk-libs', name: "chunk-libs",
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
priority: 10, priority: 10,
chunks: 'initial' // only package third parties that are initially dependent chunks: "initial", // only package third parties that are initially dependent
}, },
elementUI: { elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package name: "chunk-elementUI", // split elementUI into a single package
test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm
priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
}, },
commons: { commons: {
name: 'chunk-commons', name: "chunk-commons",
test: resolve('src/components'), // can customize your rules test: resolve("src/components"), // can customize your rules
minChunks: 3, // minimum common number minChunks: 3, // minimum common number
priority: 5, priority: 5,
reuseExistingChunk: true reuseExistingChunk: true,
} },
} },
}) });
config.optimization.runtimeChunk('single'), config.optimization.runtimeChunk("single"),
{ {
from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件 from: path.resolve(__dirname, "./public/robots.txt"), //防爬虫文件
to: './' //到根目录下 to: "./", //到根目录下
} };
}) });
} },
} };

Loading…
Cancel
Save