This commit is contained in:
zhangyanan 2025-09-03 17:05:34 +08:00
commit cb64990550
298 changed files with 41845 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.browserslistrc Normal file
View File

@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 10

39
.editorconfig Normal file
View File

@ -0,0 +1,39 @@
[*]
charset=utf-8
end_of_line=lf
insert_final_newline=false
indent_style=space
indent_size=2
[{*.ng,*.sht,*.html,*.shtm,*.shtml,*.htm}]
indent_style=space
indent_size=2
[{*.jhm,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.tld,*.fxml,*.jrxml,*.xml,*.jnlp,*.wsdl}]
indent_style=space
indent_size=2
[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]
indent_style=space
indent_size=2
[*.svg]
indent_style=space
indent_size=2
[*.js.map]
indent_style=space
indent_size=2
[*.less]
indent_style=space
indent_size=2
[*.vue]
indent_style=space
indent_size=2
[{.analysis_options,*.yml,*.yaml}]
indent_style=space
indent_size=2

3
.env Normal file
View File

@ -0,0 +1,3 @@
NODE_ENV=production
VUE_APP_PREVIEW=true
VUE_APP_API_BASE_URL=http://localhost:82

3
.env.development Normal file
View File

@ -0,0 +1,3 @@
NODE_ENV=development
VUE_APP_PREVIEW=true
VUE_APP_API_BASE_URL=http://localhost:82

3
.env.preview Normal file
View File

@ -0,0 +1,3 @@
NODE_ENV=production
VUE_APP_PREVIEW=false
VUE_APP_API_BASE_URL=http://localhost:82

77
.eslintrc.js Normal file
View File

@ -0,0 +1,77 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/strongly-recommended',
'@vue/standard'
],
rules: {
'no-console': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'generator-star-spacing': 'off',
'no-mixed-operators': 0,
'vue/max-attributes-per-line': [
2,
{
'singleline': 5,
'multiline': {
'max': 1,
'allowFirstLine': false
}
}
],
'vue/attribute-hyphenation': 0,
'vue/html-self-closing': 0,
'vue/component-name-in-template-casing': 0,
'vue/html-closing-bracket-spacing': 0,
'vue/singleline-html-element-content-newline': 0,
'vue/no-unused-components': 0,
'vue/multiline-html-element-content-newline': 0,
'vue/no-use-v-if-with-v-for': 0,
'vue/html-closing-bracket-newline': 0,
'vue/no-parsing-error': 0,
'no-tabs': 0,
'quotes': [
2,
'single',
{
'avoidEscape': true,
'allowTemplateLiterals': true
}
],
'semi': [
2,
'never',
{
'beforeStatementContinuationChars': 'never'
}
],
'no-delete-var': 2,
'prefer-const': [
2,
{
'ignoreReadBeforeAssign': false
}
],
'template-curly-spacing': 'off',
'indent': 'off',
"space-before-function-paren": 0,
'no-multi-spaces': 2, //不能用多余的空格
},
parserOptions: {
parser: 'babel-eslint'
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
node_modules/
dist/
.idea/

5
.prettierrc Normal file
View File

@ -0,0 +1,5 @@
{
"printWidth": 120,
"semi": false,
"singleQuote": true
}

7
.travis.yml Normal file
View File

@ -0,0 +1,7 @@
language: node_js
node_js:
- 10.15.0
cache: yarn
script:
- yarn
- yarn run lint --no-fix && yarn run build

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Anan Yang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

28
babel.config.js Normal file
View File

@ -0,0 +1,28 @@
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
const plugins = []
if (IS_PROD) {
plugins.push('transform-remove-console')
}
// lazy load ant-design-vue
// if your use import on Demand, Use this code
plugins.push(['import', {
'libraryName': 'ant-design-vue',
'libraryDirectory': 'es',
'style': true // `style: true` 会加载 less 文件
}])
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
[
'@babel/preset-env',
{
'useBuiltIns': 'entry',
'corejs': 3
}
]
],
plugins
}

46
config/plugin.config.js Normal file
View File

@ -0,0 +1,46 @@
const ThemeColorReplacer = require('webpack-theme-color-replacer')
const generate = require('@ant-design/colors/lib/generate').default
const getAntdSerials = (color) => {
// 淡化即less的tint
const lightens = new Array(9).fill().map((t, i) => {
return ThemeColorReplacer.varyColor.lighten(color, i / 10)
})
const colorPalettes = generate(color)
const rgb = ThemeColorReplacer.varyColor.toNum3(color.replace('#', '')).join(',')
return lightens.concat(colorPalettes).concat(rgb)
}
const themePluginOption = {
fileName: 'css/theme-colors-[contenthash:8].css',
matchColors: getAntdSerials('#1890ff'), // 主色系列
// 改变样式选择器,解决样式覆盖问题
changeSelector (selector) {
switch (selector) {
case '.ant-calendar-today .ant-calendar-date':
return ':not(.ant-calendar-selected-date):not(.ant-calendar-selected-day)' + selector
case '.ant-btn:focus,.ant-btn:hover':
return '.ant-btn:focus:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:hover:not(.ant-btn-primary):not(.ant-btn-danger)'
case '.ant-btn.active,.ant-btn:active':
return '.ant-btn.active:not(.ant-btn-primary):not(.ant-btn-danger),.ant-btn:active:not(.ant-btn-primary):not(.ant-btn-danger)'
case '.ant-steps-item-process .ant-steps-item-icon > .ant-steps-icon':
case '.ant-steps-item-process .ant-steps-item-icon>.ant-steps-icon':
return ':not(.ant-steps-item-process)' + selector
case '.ant-menu-horizontal>.ant-menu-item-active,.ant-menu-horizontal>.ant-menu-item-open,.ant-menu-horizontal>.ant-menu-item-selected,.ant-menu-horizontal>.ant-menu-item:hover,.ant-menu-horizontal>.ant-menu-submenu-active,.ant-menu-horizontal>.ant-menu-submenu-open,.ant-menu-horizontal>.ant-menu-submenu-selected,.ant-menu-horizontal>.ant-menu-submenu:hover':
case '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal > .ant-menu-submenu-selected,.ant-menu-horizontal > .ant-menu-submenu:hover':
return '.ant-menu-horizontal > .ant-menu-item-active,.ant-menu-horizontal > .ant-menu-item-open,.ant-menu-horizontal > .ant-menu-item-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-item:hover,.ant-menu-horizontal > .ant-menu-submenu-active,.ant-menu-horizontal > .ant-menu-submenu-open,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu-selected,.ant-menu-horizontal:not(.ant-menu-dark) > .ant-menu-submenu:hover'
case '.ant-menu-horizontal > .ant-menu-item-selected > a':
case '.ant-menu-horizontal>.ant-menu-item-selected>a':
return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item-selected > a'
case '.ant-menu-horizontal > .ant-menu-item > a:hover':
case '.ant-menu-horizontal>.ant-menu-item>a:hover':
return '.ant-menu-horizontal:not(ant-menu-light):not(.ant-menu-dark) > .ant-menu-item > a:hover'
default :
return selector
}
}
}
const createThemeColorReplacerPlugin = () => new ThemeColorReplacer(themePluginOption)
module.exports = createThemeColorReplacerPlugin

23
jest.config.js Normal file
View File

@ -0,0 +1,23 @@
module.exports = {
moduleFileExtensions: [
'js',
'jsx',
'json',
'vue'
],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: [
'jest-serializer-vue'
],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
testURL: 'http://localhost/'
}

11
jsconfig.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "es6",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"],
"include": ["src/**/*"]
}

88
package.json Normal file
View File

@ -0,0 +1,88 @@
{
"name": "vue-antd-pro",
"version": "2.1.0",
"private": true,
"scripts": {
"yarn ": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"build:preview": "vue-cli-service build --mode preview",
"postinstall": "opencollective-postinstall"
},
"dependencies": {
"@antv/data-set": "^0.10.2",
"ant-design-vue": "1.5.0-rc.6",
"axios": "^0.19.0",
"babel-polyfill": "^6.26.0",
"clipboard": "^2.0.6",
"compression-webpack-plugin": "5.0.1",
"core-js": "^3.1.2",
"crypto-js": "^4.0.0",
"default-passive-events": "^1.0.10",
"enquire.js": "^2.1.6",
"font-awesome": "^4.7.0",
"jquery": "^3.5.1",
"lodash.clonedeep": "^4.5.0",
"lodash.get": "^4.4.2",
"lodash.pick": "^4.4.0",
"md5": "^2.2.1",
"mockjs2": "1.0.8",
"moment": "^2.24.0",
"nprogress": "^0.2.0",
"print-js": "^1.0.63",
"raphael": "^2.3.0",
"screenfull": "^5.1.0",
"sm-crypto": "^0.3.6",
"viser-vue": "^2.4.6",
"vue": "2.6.10",
"vue-clipboard2": "^0.2.1",
"vue-codemirror-lite": "^1.0.4",
"vue-cropper": "0.4.9",
"vue-ls": "^3.2.1",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.1.2",
"vue-svg-component-runtime": "^1.0.1",
"vuedraggable": "^2.23.2",
"vuex": "^3.1.1",
"wangeditor": "^3.1.1"
},
"devDependencies": {
"@ant-design/colors": "^3.2.1",
"@vue/cli-plugin-babel": "^4.0.4",
"@vue/cli-plugin-eslint": "^4.0.4",
"@vue/cli-plugin-router": "^4.0.4",
"@vue/cli-plugin-unit-jest": "^4.0.4",
"@vue/cli-plugin-vuex": "^4.0.4",
"@vue/cli-service": "^4.0.4",
"@vue/eslint-config-prettier": "^5.0.0",
"@vue/eslint-config-standard": "^4.0.0",
"@vue/test-utils": "^1.0.0-beta.29",
"babel-eslint": "^10.0.1",
"babel-plugin-import": "^1.13.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"eslint": "^6.8.0",
"eslint-plugin-html": "^5.0.0",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-vue": "^5.2.3",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.2",
"prettier": "^1.18.2",
"vue-svg-icon-loader": "^2.1.1",
"vue-template-compiler": "2.6.10",
"webpack-theme-color-replacer": "1.3.18"
},
"collective": {
"type": "opencollective",
"url": "https://opencollective.com/ant-design-pro-vue"
},
"main": ".eslintrc.js",
"directories": {
"test": "tests"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": ""
}

5
postcss.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

BIN
public/avatar2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

37
public/index.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>logo.png">
<title>Snowy快速开发平台</title>
<style>.first-loading-wrp{display:flex;justify-content:center;align-items:center;flex-direction:column;min-height:420px;height:100%}.first-loading-wrp>h1{font-size:128px}.first-loading-wrp .loading-wrp{padding:98px;display:flex;justify-content:center;align-items:center}.dot{animation:antRotate 1.2s infinite linear;transform:rotate(45deg);position:relative;display:inline-block;font-size:32px;width:32px;height:32px;box-sizing:border-box}.dot i{width:14px;height:14px;position:absolute;display:block;background-color:#1890ff;border-radius:100%;transform:scale(.75);transform-origin:50% 50%;opacity:.3;animation:antSpinMove 1s infinite linear alternate}.dot i:nth-child(1){top:0;left:0}.dot i:nth-child(2){top:0;right:0;-webkit-animation-delay:.4s;animation-delay:.4s}.dot i:nth-child(3){right:0;bottom:0;-webkit-animation-delay:.8s;animation-delay:.8s}.dot i:nth-child(4){bottom:0;left:0;-webkit-animation-delay:1.2s;animation-delay:1.2s}@keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@-webkit-keyframes antRotate{to{-webkit-transform:rotate(405deg);transform:rotate(405deg)}}@keyframes antSpinMove{to{opacity:1}}@-webkit-keyframes antSpinMove{to{opacity:1}}</style>
<!-- <script type="text/javascript" src="https://onlyoffice.xiaonuo.vip/web-apps/apps/api/documents/api.js"></script> -->
<!-- require cdn assets css -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" />
<% } %>
</head>
<body>
<noscript>
<strong>We're sorry but vue-antd-pro doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<div class="first-loading-wrp">
<h1>Snowy</h1>
<div class="loading-wrp">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
<div style="display: flex; justify-content: center; align-items: center;">Snowy快速开发平台</div>
</div>
</div>
<!-- require cdn assets js -->
<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -0,0 +1 @@
#preloadingAnimation{position:fixed;left:0;top:0;height:100%;width:100%;background:#ffffff;user-select:none;z-index: 9999;overflow: hidden}.lds-roller{display:inline-block;position:relative;left:50%;top:50%;transform:translate(-50%,-50%);width:64px;height:64px;}.lds-roller div{animation:lds-roller 1.2s cubic-bezier(0.5,0,0.5,1) infinite;transform-origin:32px 32px;}.lds-roller div:after{content:" ";display:block;position:absolute;width:6px;height:6px;border-radius:50%;background:#13c2c2;margin:-3px 0 0 -3px;}.lds-roller div:nth-child(1){animation-delay:-0.036s;}.lds-roller div:nth-child(1):after{top:50px;left:50px;}.lds-roller div:nth-child(2){animation-delay:-0.072s;}.lds-roller div:nth-child(2):after{top:54px;left:45px;}.lds-roller div:nth-child(3){animation-delay:-0.108s;}.lds-roller div:nth-child(3):after{top:57px;left:39px;}.lds-roller div:nth-child(4){animation-delay:-0.144s;}.lds-roller div:nth-child(4):after{top:58px;left:32px;}.lds-roller div:nth-child(5){animation-delay:-0.18s;}.lds-roller div:nth-child(5):after{top:57px;left:25px;}.lds-roller div:nth-child(6){animation-delay:-0.216s;}.lds-roller div:nth-child(6):after{top:54px;left:19px;}.lds-roller div:nth-child(7){animation-delay:-0.252s;}.lds-roller div:nth-child(7):after{top:50px;left:14px;}.lds-roller div:nth-child(8){animation-delay:-0.288s;}.lds-roller div:nth-child(8):after{top:45px;left:10px;}#preloadingAnimation .load-tips{color: #13c2c2;font-size:2rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);margin-top:80px;text-align:center;width:400px;height:64px;} @keyframes lds-roller{0%{transform:rotate(0deg);} 100%{transform:rotate(360deg);}}

View File

@ -0,0 +1 @@
<div id="preloadingAnimation"><div class=lds-roller><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div><div class=load-tips>Loading</div></div>

View File

@ -0,0 +1,5 @@
<div class="preloading-animate">
<div class="preloading-wrapper">
<svg class="preloading-balls" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"><circle cx="67.802" cy="59.907" r="6" fill="#51CACC"><animate attributeName="cx" values="75;57.72542485937369" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="50;73.77641290737884" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#51CACC;#9DF871" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="46.079" cy="69.992" r="6" fill="#9DF871"><animate attributeName="cx" values="57.72542485937369;29.774575140626318" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="73.77641290737884;64.69463130731182" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#9DF871;#E0FF77" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="29.775" cy="52.449" r="6" fill="#E0FF77"><animate attributeName="cx" values="29.774575140626318;29.774575140626315" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="64.69463130731182;35.30536869268818" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#E0FF77;#DE9DD6" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="41.421" cy="31.521" r="6" fill="#DE9DD6"><animate attributeName="cx" values="29.774575140626315;57.72542485937368" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="35.30536869268818;26.22358709262116" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#DE9DD6;#FF708E" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="64.923" cy="36.13" r="6" fill="#FF708E"><animate attributeName="cx" values="57.72542485937368;75" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="26.22358709262116;49.99999999999999" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#FF708E;#51CACC" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle></svg>
</div>
</div>

View File

@ -0,0 +1 @@
.preloading-animate{background:#ffffff;width:100%;height:100%;position:fixed;left:0;top:0;z-index:299;}.preloading-animate .preloading-wrapper{position:absolute;width:5rem;height:5rem;left:50%;top:50%;transform:translate(-50%,-50%);}.preloading-animate .preloading-wrapper .preloading-balls{font-size:5rem;}

View File

@ -0,0 +1 @@
<svg class="preloading-balls" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"><circle cx="67.802" cy="59.907" r="6" fill="#51CACC"><animate attributeName="cx" values="75;57.72542485937369" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="50;73.77641290737884" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#51CACC;#9DF871" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="46.079" cy="69.992" r="6" fill="#9DF871"><animate attributeName="cx" values="57.72542485937369;29.774575140626318" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="73.77641290737884;64.69463130731182" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#9DF871;#E0FF77" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="29.775" cy="52.449" r="6" fill="#E0FF77"><animate attributeName="cx" values="29.774575140626318;29.774575140626315" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="64.69463130731182;35.30536869268818" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#E0FF77;#DE9DD6" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="41.421" cy="31.521" r="6" fill="#DE9DD6"><animate attributeName="cx" values="29.774575140626315;57.72542485937368" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="35.30536869268818;26.22358709262116" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#DE9DD6;#FF708E" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle><circle cx="64.923" cy="36.13" r="6" fill="#FF708E"><animate attributeName="cx" values="57.72542485937368;75" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="cy" values="26.22358709262116;49.99999999999999" keyTimes="0;1" dur="1s" repeatCount="indefinite"/><animate attributeName="fill" values="#FF708E;#51CACC" keyTimes="0;1" dur="1s" repeatCount="indefinite"/></circle></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

47
src/App.vue Normal file
View File

@ -0,0 +1,47 @@
<template>
<a-config-provider :locale="locale">
<div id="app" class="app app1">
<router-view class="scrollbar"/>
</div>
</a-config-provider>
</template>
<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN'
import { AppDeviceEnquire } from '@/utils/mixin'
export default {
mixins: [AppDeviceEnquire],
data () {
return {
locale: zhCN
}
},
mounted () {
}
}
</script>
<style>
.app {
overflow: auto;
border : none;
}
.scrollbar {
margin: 0 auto;
}
.app1::-webkit-scrollbar {
/*滚动条整体样式*/
width : 8px; /*高宽分别对应横竖滚动条的尺寸*/
}
.app1::-webkit-scrollbar-thumb {
/*滚动条里面小方块*/
border-radius: 6px;
background : #aaa;
}
.app1::-webkit-scrollbar-track {
/*滚动条里面轨道*/
border-radius: 8px;
background : #FFFFFF;
}
</style>

View File

@ -0,0 +1,106 @@
/**
* 代码生成
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
import { axios } from '@/utils/request'
/**
* 查询列表
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGeneratePage (parameter) {
return axios({
url: '/codeGenerate/page',
method: 'get',
params: parameter
})
}
/**
* 增加
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateAdd (parameter) {
return axios({
url: '/codeGenerate/add',
method: 'post',
data: parameter
})
}
/**
* 编辑
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateEdit (parameter) {
return axios({
url: '/codeGenerate/edit',
method: 'post',
data: parameter
})
}
/**
* 删除
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateDelete (parameter) {
return axios({
url: '/codeGenerate/delete',
method: 'post',
data: parameter
})
}
/**
* 查询当前数据库用户下的所有表
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateInformationList (parameter) {
return axios({
url: '/codeGenerate/InformationList',
method: 'get',
params: parameter
})
}
/**
* 本地生成
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateRunLocal (parameter) {
return axios({
url: '/codeGenerate/runLocal',
method: 'post',
data: parameter
})
}
/**
* 压缩包方式下载
*
* @author yubaoshan
* @date 2020/12/23 15:00
*/
export function codeGenerateRunDown (parameter) {
return axios({
url: '/codeGenerate/runDown',
method: 'get',
params: parameter,
responseType: 'blob'
})
}

View File

@ -0,0 +1,29 @@
import { axios } from '@/utils/request'
/**
* 代码生成详细配置列表
*
* @author yubaoshan
* @date 2021-02-06 20:19:49
*/
export function sysCodeGenerateConfigList (parameter) {
return axios({
url: '/sysCodeGenerateConfig/list',
method: 'get',
params: parameter
})
}
/**
* 编辑代码生成详细配置
*
* @author yubaoshan
* @date 2021-02-06 20:19:49
*/
export function sysCodeGenerateConfigEdit (parameter) {
return axios({
url: '/sysCodeGenerateConfig/edit',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1 @@
/** 您的业务接口文件全写在此文件夹下面,升级底座直接迁移代码即可 **/

View File

@ -0,0 +1 @@
/** 此文件夹下代码尽量不要动,底座升级直接覆盖替换 **/

View File

@ -0,0 +1,92 @@
/**
* 系统应用
*
* @author yubaoshan
* @date 2020年4月23日12:10:57
*/
import { axios } from '@/utils/request'
/**
* 系统应用列表
*
* @author yubaoshan
* @date 2020年7月9日15:05:01
*/
export function getAppPage (parameter) {
return axios({
url: '/sysApp/page',
method: 'get',
params: parameter
})
}
/**
* 系统应用列表
*
* @author yubaoshan
* @date 2020年7月9日15:05:01
*/
export function getAppList (parameter) {
return axios({
url: '/sysApp/list',
method: 'get',
params: parameter
})
}
/**
* 新增系统应用
*
* @author yubaoshan
* @date 2020年7月9日15:05:01
*/
export function sysAppAdd (parameter) {
return axios({
url: '/sysApp/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统应用
*
* @author yubaoshan
* @param parameter
* @returns {*}
*/
export function sysAppEdit (parameter) {
return axios({
url: '/sysApp/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统应用
*
* @author yubaoshan
* @date 2020年7月9日15:05:01
*/
export function sysAppDelete (parameter) {
return axios({
url: '/sysApp/delete',
method: 'post',
data: parameter
})
}
/**
* 设为默认应用
*
* @author yubaoshan
* @date 2020年7月9日15:05:01
*/
export function sysAppSetAsDefault (parameter) {
return axios({
url: '/sysApp/setAsDefault',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,16 @@
import { axios } from '@/utils/request'
/**
* 获取区域列表
*
* @author xuyuxiang
* @param parameter
* @returns {*}
*/
export function getAreaList (parameter) {
return axios({
url: '/sysArea/list',
method: 'get',
params: parameter
})
}

View File

@ -0,0 +1,85 @@
import { axios } from '@/utils/request'
/**
* 分页查询配置列表
*
* @author yubaoshan
* @date 2020/5/25 01:57
*/
export function sysConfigPage (parameter) {
return axios({
url: '/sysConfig/page',
method: 'get',
params: parameter
})
}
/**
* 添加系统参数配置
*
* @author yubaoshan
* @date 2020/5/25 01:57
*/
export function sysConfigAdd (parameter) {
return axios({
url: '/sysConfig/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统参数配置
*
* @author yubaoshan
* @date 2020/5/25 01:57
*/
export function sysConfigEdit (parameter) {
return axios({
url: '/sysConfig/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统参数配置
*
* @author yubaoshan
* @date 2020/5/25 01:57
*/
export function sysConfigDelete (parameter) {
return axios({
url: '/sysConfig/delete',
method: 'post',
data: parameter
})
}
/**
* 获取字典类型下所有字典举例返回格式为[{code:"M",value:"男"},{code:"F",value:"女"}]
*
* @author yubaoshan
* @date 2020/5/25 02:06
*/
export function sysDictTypeDropDown (parameter) {
return axios({
url: '/sysDictType/dropDown',
method: 'get',
params: parameter
})
}
/**
* 获取系统的所有任务列表
*
* @author yubaoshan
* @date 2020/7/8 20:46
*/
export function sysTimersGetActionClasses (parameter) {
return axios({
url: '/sysTimers/getActionClasses',
method: 'get',
params: parameter
})
}

View File

@ -0,0 +1,57 @@
import { axios } from '@/utils/request'
/**
* 查询系统字典值
*
* @author yubaoshan
* @date 2020/5/17 02:24
*/
export function sysDictDataPage (parameter) {
return axios({
url: '/sysDictData/page',
method: 'get',
params: parameter
})
}
/**
* 添加系统字典值
*
* @author yubaoshan
* @date 2020/5/17 02:24
*/
export function sysDictDataAdd (parameter) {
return axios({
url: '/sysDictData/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统字典值
*
* @author yubaoshan
* @date 2020/5/17 02:25
*/
export function sysDictDataEdit (parameter) {
return axios({
url: '/sysDictData/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统字典值
*
* @author yubaoshan
* @date 2020/5/17 02:25
*/
export function sysDictDataDelete (parameter) {
return axios({
url: '/sysDictData/delete',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,85 @@
import { axios } from '@/utils/request'
/**
* 分页查询系统字典类型
*
* @author yubaoshan
* @date 2020/5/17 01:46
*/
export function sysDictTypePage (parameter) {
return axios({
url: '/sysDictType/page',
method: 'get',
params: parameter
})
}
/**
* 添加系统字典类型
*
* @author yubaoshan
* @date 2020/5/17 01:46
*/
export function sysDictTypeAdd (parameter) {
return axios({
url: '/sysDictType/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统字典类型
*
* @author yubaoshan
* @date 2020/5/17 01:50
*/
export function sysDictTypeEdit (parameter) {
return axios({
url: '/sysDictType/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统字典类型
*
* @author yubaoshan
* @date 2020/5/17 01:50
*/
export function sysDictTypeDelete (parameter) {
return axios({
url: '/sysDictType/delete',
method: 'post',
data: parameter
})
}
/**
* 获取字典类型下所有字典举例返回格式为[{code:"M",value:"男"},{code:"F",value:"女"}]
*
* @author yubaoshan
* @date 2020/6/10 00:10
*/
export function sysDictTypeDropDown (parameter) {
return axios({
url: '/sysDictType/dropDown',
method: 'get',
params: parameter
})
}
/**
* 获取所有字典启动时加入缓存使用
*
* @author yubaoshan
* @date 2020/6/10 00:10
*/
export function sysDictTypeTree (parameter) {
return axios({
url: '/sysDictType/tree',
method: 'get',
params: parameter
})
}

View File

@ -0,0 +1,29 @@
import { axios } from '@/utils/request'
/**
* 发送邮件
*
* @author yubaoshan
* @date 2020/7/3 23:22
*/
export function emailSendEmail (parameter) {
return axios({
url: '/email/sendEmail',
method: 'post',
data: parameter
})
}
/**
* 发送html邮件
*
* @author yubaoshan
* @date 2020/7/3 23:23
*/
export function emailSendEmailHtml (parameter) {
return axios({
url: '/email/sendEmailHtml',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,115 @@
import { axios } from '@/utils/request'
/**
* 分页查询文件信息表
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoPage (parameter) {
return axios({
url: '/sysFileInfo/page',
method: 'get',
params: parameter
})
}
/**
* 获取全部文件信息表
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoList (parameter) {
return axios({
url: '/sysFileInfo/list',
method: 'get',
params: parameter
})
}
/**
* 上传文件
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoUpload (parameter) {
return axios({
url: '/sysFileInfo/upload',
method: 'post',
data: parameter
})
}
/**
* 下载文件
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoDownload (parameter) {
return axios({
url: '/sysFileInfo/download',
method: 'get',
params: parameter,
responseType: 'blob'
})
}
/**
* 查看图片
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoPreview (parameter) {
return axios({
url: '/sysFileInfo/preview',
method: 'get',
params: parameter,
responseType: 'arraybuffer'
})
}
/**
* 查看详情文件信息表
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoDetail (parameter) {
return axios({
url: '/sysFileInfo/detail',
method: 'get',
params: parameter
})
}
/**
* 删除文件信息表
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoDelete (parameter) {
return axios({
url: '/sysFileInfo/delete',
method: 'post',
data: parameter
})
}
/**
* 获取在线文档配置
*
* @author yubaoshan
* @date 2020/6/30 00:20
*/
export function sysFileInfoGetOnlineConfig (parameter) {
return axios({
url: '/sysFileInfo/getOnlineFileConfig',
method: 'get',
params: parameter
})
}

View File

@ -0,0 +1,87 @@
import { axios } from '@/utils/request'
/**
* 查询访问日志
*
* @author yubaoshan
* @date 2020/5/19 11:57
*/
export function sysVisLogPage (parameter) {
return axios({
url: '/sysVisLog/page',
method: 'get',
params: parameter
})
}
/**
* 查询操作日志
*
* @author yubaoshan
* @date 2020/5/19 11:57
*/
export function sysOpLogPage (parameter) {
return axios({
url: '/sysOpLog/page',
method: 'get',
params: parameter
})
}
/**
* 清空访问日志
*
* @author yubaoshan
* @date 2020/6/23 23:09
*/
export function sysVisLogDelete (parameter) {
return axios({
url: '/sysVisLog/delete',
method: 'post',
data: parameter
})
}
/**
* 清空登录日志
*
* @author yubaoshan
* @date 2020/6/23 23:09
*/
export function sysOpLogDelete (parameter) {
return axios({
url: '/sysOpLog/delete',
method: 'post',
data: parameter
})
}
/**
* 导出登录日志
*
* @author yubaoshan
* @date 2021/5/30 18:03
*/
export function sysVisLogExport (parameter) {
return axios({
url: '/sysVisLog/export',
method: 'get',
params: parameter,
responseType: 'blob'
})
}
/**
* 导出操作日志
*
* @author yubaoshan
* @date 2021/5/30 18:03
*/
export function sysOpLogExport (parameter) {
return axios({
url: '/sysOpLog/export',
method: 'get',
params: parameter,
responseType: 'blob'
})
}

View File

@ -0,0 +1,125 @@
/**
* 系统应用
*
* @author yubaoshan
* @date 2020/5/26 19:06
*/
import { axios } from '@/utils/request'
/**
* 登录
*
* @author yubaoshan
* @date 2020/5/26 19:06
*/
export function login (parameter) {
// 密码采用sm2加密传输密码
const sm2 = require('sm-crypto').sm2
const publicKey = '04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54'
const encryptData = sm2.doEncrypt(parameter.password, publicKey, 1)
parameter.password = encryptData
return axios({
url: '/login',
method: 'post',
data: parameter
})
}
/**
* 登出
*
* @author yubaoshan
* @date 2020/5/26 19:07
*/
export function logout (parameter) {
return axios({
url: '/logout',
method: 'get',
params: parameter
})
}
/**
* 获取登录用户信息
*
* @author yubaoshan
* @date 2020/5/26 19:08
*/
export function getLoginUser (parameter) {
return axios({
url: '/getLoginUser',
method: 'get',
params: parameter
})
}
/**
* 获取租户开关
*
* @author yubaoshan
* @date 2020/9/5 1:24
*/
export function getTenantOpen (parameter) {
return axios({
url: '/getTenantOpen',
method: 'get',
params: parameter
})
}
/**
* 获取短信验证码
*
* @author yubaoshan
* @date 2020/5/26 19:29
*/
export function getSmsCaptcha (parameter) {
return axios({
url: '/getSmsCaptcha',
method: 'get',
params: parameter
})
}
/**
* 获取验证码开关
*
* @author Jax
* @date 2021/1/22 00:00
*/
export function getCaptchaOpen (parameter) {
return axios({
url: '/getCaptchaOpen',
method: 'get',
params: parameter
})
}
/**
* 获取验证图片 以及token
*
* @author Jax
* @date 2021/1/22 00:00
*/
export function reqGet(data) {
return axios({
url: '/captcha/get',
method: 'post',
data
})
}
/**
* 滑动或者点选验证
*
* @author Jax
* @date 2021/1/22 00:00
*/
export function reqCheck(data) {
return axios({
url: '/captcha/check',
method: 'post',
data
})
}

View File

@ -0,0 +1,15 @@
import { axios } from '@/utils/request'
/**
* 系统属性监控
*
* @author yubaoshan
* @date 2020/6/8 19:47
*/
export function sysMachineQuery (parameter) {
return axios({
url: '/sysMachine/query',
method: 'get',
params: parameter
})
}

View File

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

View File

@ -0,0 +1,85 @@
import { axios } from '@/utils/request'
/**
* 查询系统通知公告
*
* @author yubaoshan
* @date 2020/6/30 01:56
*/
export function sysNoticePage (parameter) {
return axios({
url: '/sysNotice/page',
method: 'get',
params: parameter
})
}
/**
* 添加系统通知公告
*
* @author yubaoshan
* @date 2020/6/30 01:56
*/
export function sysNoticeAdd (parameter) {
return axios({
url: '/sysNotice/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统通知公告
*
* @author yubaoshan
* @date 2020/6/30 01:56
*/
export function sysNoticeEdit (parameter) {
return axios({
url: '/sysNotice/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统通知公告
*
* @author yubaoshan
* @date 2020/6/30 01:56
*/
export function sysNoticeDelete (parameter) {
return axios({
url: '/sysNotice/delete',
method: 'post',
data: parameter
})
}
/**
* 通知公告详情
*
* @author yubaoshan
* @date 2020/6/30 01:56
*/
export function sysNoticeDetail (parameter) {
return axios({
url: '/sysNotice/detail',
method: 'get',
params: parameter
})
}
/**
* 修改状态
*
* @author yubaoshan
* @date 2020/7/30 02:23
*/
export function sysNoticeChangeStatus (parameter) {
return axios({
url: '/sysNotice/changeStatus',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,15 @@
import { axios } from '@/utils/request'
/**
* 查询我收到的系统通知公告
*
* @author yubaoshan
* @date 2020/7/3 03:02
*/
export function sysNoticeReceived (parameter) {
return axios({
url: '/sysNotice/received',
method: 'get',
params: parameter
})
}

View File

@ -0,0 +1,29 @@
import { axios } from '@/utils/request'
/**
* 在线用户列表
*
* @author yubaoshan
* @date 2020/6/8 11:11
*/
export function sysOnlineUserList (parameter) {
return axios({
url: '/sysOnlineUser/list',
method: 'get',
params: parameter
})
}
/**
* 强制下线
*
* @author yubaoshan
* @date 2020/6/8 11:11
*/
export function sysOnlineUserForceExist (parameter) {
return axios({
url: '/sysOnlineUser/forceExist',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,100 @@
import { axios } from '@/utils/request'
/**
* 获取机构树
*
* @author yubaoshan
* @date 2020/4/26 12:08
*/
export function getOrgTree (parameter) {
return axios({
url: '/sysOrg/tree',
method: 'get',
params: parameter
})
}
/**
* 获取机构列表
*
* @author yubaoshan
* @date 2020/5/11 12:59
*/
export function getOrgList (parameter) {
return axios({
url: '/sysOrg/list',
method: 'get',
params: parameter
})
}
/**
* 获取机构列表
*
* @author yubaoshan
* @date 2020/5/11 16:17
*/
export function getOrgPage (parameter) {
return axios({
url: '/sysOrg/page',
method: 'get',
params: parameter
})
}
/**
* 新增机构
*
* @author yubaoshan
* @date 2020/5/11 13:56
*/
export function sysOrgAdd (parameter) {
return axios({
url: '/sysOrg/add',
method: 'post',
data: parameter
})
}
/**
* 编辑机构
*
* @author yubaoshan
* @date 2020/5/11 13:56
*/
export function sysOrgEdit (parameter) {
return axios({
url: '/sysOrg/edit',
method: 'post',
data: parameter
})
}
/**
* 删除机构
*
* @author yubaoshan
* @date 2020/5/11 12:59
*/
export function sysOrgDelete (parameter) {
return axios({
url: '/sysOrg/delete',
method: 'post',
data: parameter
})
}
/**
* 导出系统机构
*
* @author yubaoshan
* @date 2021/5/30 12:58
*/
export function sysOrgExport (parameter) {
return axios({
url: '/sysOrg/export',
method: 'get',
params: parameter,
responseType: 'blob'
})
}

View File

@ -0,0 +1,86 @@
import { axios } from '@/utils/request'
/**
* 查询系统职位
*
* @author yubaoshan
* @date 2020/5/25 01:31
*/
export function sysPosPage (parameter) {
return axios({
url: '/sysPos/page',
method: 'get',
params: parameter
})
}
/**
* 系统职位列表
*
* @author yubaoshan
* @date 2020/6/21 23:50
*/
export function sysPosList (parameter) {
return axios({
url: '/sysPos/list',
method: 'get',
params: parameter
})
}
/**
* 添加系统职位
*
* @author yubaoshan
* @date 2020/5/25 01:31
*/
export function sysPosAdd (parameter) {
return axios({
url: '/sysPos/add',
method: 'post',
data: parameter
})
}
/**
* 编辑系统职位
*
* @author yubaoshan
* @date 2020/5/25 01:31
*/
export function sysPosEdit (parameter) {
return axios({
url: '/sysPos/edit',
method: 'post',
data: parameter
})
}
/**
* 删除系统职位
*
* @author yubaoshan
* @date 2020/5/25 01:31
*/
export function sysPosDelete (parameter) {
return axios({
url: '/sysPos/delete',
method: 'post',
data: parameter
})
}
/**
* 导出系统职位
*
* @author yubaoshan
* @date 2021/5/29 16:19
*/
export function sysPosExport (parameter) {
return axios({
url: '/sysPos/export',
method: 'get',
params: parameter,
responseType: 'blob'
})
}

View File

@ -0,0 +1,141 @@
import { axios } from '@/utils/request'
/**
* 获取角色列表
*
* @author yubaoshan
* @date 2020/5/6 11:44
*/
export function getRolePage (parameter) {
return axios({
url: '/sysRole/page',
method: 'get',
params: parameter
})
}
/**
* 增加角色
*
* @author yubaoshan
* @date 2020/5/6 11:44
*/
export function sysRoleAdd (parameter) {
return axios({
url: '/sysRole/add',
method: 'post',
data: parameter
})
}
/**
* 编辑角色
*
* @author yubaoshan
* @date 2020/5/6 11:44
*/
export function sysRoleEdit (parameter) {
return axios({
url: '/sysRole/edit',
method: 'post',
data: parameter
})
}
/**
* 删除角色
*
* @author yubaoshan
* @date 2020/5/6 17:51
*/
export function sysRoleDelete (parameter) {
return axios({
url: '/sysRole/delete',
method: 'post',
data: parameter
})
}
/**
* 删除角色
*
* @author yubaoshan
* @date 2020/5/7 11:28
*/
export function sysRoleDeteil (parameter) {
return axios({
url: '/sysRole/detail',
method: 'get',
params: parameter
})
}
/**
* 获取授权角色列表
*
* @author yubaoshan
* @date 2020/5/26 23:59
*/
export function sysRoleDropDown (parameter) {
return axios({
url: '/sysRole/dropDown',
method: 'get',
params: parameter
})
}
/**
* 拥有菜单
*
* @author yubaoshan
* @date 2020/6/02 19:02
*/
export function sysRoleOwnMenu (parameter) {
return axios({
url: '/sysRole/ownMenu',
method: 'get',
params: parameter
})
}
/**
* 授权菜单
*
* @author yubaoshan
* @date 2020/6/2 21:10
*/
export function sysRoleGrantMenu (parameter) {
return axios({
url: '/sysRole/grantMenu',
method: 'post',
data: parameter
})
}
/**
* 拥有数据
*
* @author yubaoshan
* @date 2020/6/02 21:40
*/
export function sysRoleOwnData (parameter) {
return axios({
url: '/sysRole/ownData',
method: 'get',
params: parameter
})
}
/**
* 授权数据
*
* @author yubaoshan
* @date 2020/6/2 21:50
*/
export function sysRoleGrantData (parameter) {
return axios({
url: '/sysRole/grantData',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,43 @@
import { axios } from '@/utils/request'
/**
* 发送记录查询
*
* @author yubaoshan
* @date 2020/7/3 22:11
*/
export function smsPage (parameter) {
return axios({
url: '/sms/page',
method: 'get',
params: parameter
})
}
/**
* 验证短信验证码
*
* @author yubaoshan
* @date 2020/7/3 22:12
*/
export function sysSendLoginMessage (parameter) {
return axios({
url: '/sms/sendLoginMessage',
method: 'post',
data: parameter
})
}
/**
* 验证短信验证码
*
* @author yubaoshan
* @date 2020/7/3 22:12
*/
export function sysValidateMessage (parameter) {
return axios({
url: '/sms/validateMessage',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,127 @@
import { axios } from '@/utils/request'
/**
* 分页查询定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:13
*/
export function sysTimersPage (parameter) {
return axios({
url: '/sysTimers/page',
method: 'get',
params: parameter
})
}
/**
* 获取全部定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersList (parameter) {
return axios({
url: '/sysTimers/list',
method: 'get',
params: parameter
})
}
/**
* 查看详情定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersDetail (parameter) {
return axios({
url: '/sysTimers/detail',
method: 'get',
params: parameter
})
}
/**
* 添加定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersAdd (parameter) {
return axios({
url: '/sysTimers/add',
method: 'post',
data: parameter
})
}
/**
* 删除定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersDelete (parameter) {
return axios({
url: '/sysTimers/delete',
method: 'post',
data: parameter
})
}
/**
* 编辑定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersEdit (parameter) {
return axios({
url: '/sysTimers/edit',
method: 'post',
data: parameter
})
}
/**
* 获取系统的所有任务列表
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersGetActionClasses (parameter) {
return axios({
url: '/sysTimers/getActionClasses',
method: 'post',
data: parameter
})
}
/**
* 启动定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersStart (parameter) {
return axios({
url: '/sysTimers/start',
method: 'post',
data: parameter
})
}
/**
* 停止定时任务
*
* @author yubaoshan
* @date 2020/7/3 03:23
*/
export function sysTimersStop (parameter) {
return axios({
url: '/sysTimers/stop',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1,226 @@
import { axios } from '@/utils/request'
/**
* 获取用户列表
*
* @author yubaoshan
* @date 2020/4/26 12:08
*/
export function getUserPage (parameter) {
return axios({
url: '/sysUser/page',
method: 'get',
params: parameter
})
}
/**
* 增加用户
*
* @author yubaoshan
* @date 2020/5/5 02:08
*/
export function sysUserAdd (parameter) {
return axios({
url: '/sysUser/add',
method: 'post',
data: parameter
})
}
/**
* 编辑用户
*
* @author yubaoshan
* @date 2020/5/5 02:08
*/
export function sysUserEdit (parameter) {
return axios({
url: '/sysUser/edit',
method: 'post',
data: parameter
})
}
/**
* 获取用户详情
*
* @author yubaoshan
* @date 2020/5/5 19:55
*/
export function sysUserDetail (parameter) {
return axios({
url: '/sysUser/detail',
method: 'get',
params: parameter
})
}
/**
* 删除用户
*
* @author yubaoshan
* @date 2020/5/7 19:31
*/
export function sysUserDelete (parameter) {
return axios({
url: '/sysUser/delete',
method: 'post',
data: parameter
})
}
/**
* 导出用户
*
* @author yubaoshan
* @date 2021/5/30 00:23
*/
export function sysUserExport (parameter) {
return axios({
url: '/sysUser/export',
method: 'get',
params: parameter,
responseType: 'blob'
})
}
/**
* 拥有角色
*
* @author yubaoshan
* @date 2020/6/3 11:58
*/
export function sysUserOwnRole (parameter) {
return axios({
url: '/sysUser/ownRole',
method: 'get',
params: parameter
})
}
/**
* 授权角色
*
* @author yubaoshan
* @date 2020/5/26 23:59
*/
export function sysUserGrantRole (parameter) {
return axios({
url: '/sysUser/grantRole',
method: 'post',
data: parameter
})
}
/**
* 拥有数据
*
* @author yubaoshan
* @date 2020/6/2 23:14
*/
export function sysUserOwnData (parameter) {
return axios({
url: '/sysUser/ownData',
method: 'get',
params: parameter
})
}
/**
* 授权数据
*
* @author yubaoshan
* @date 2020/6/2 23:15
*/
export function sysUserGrantData (parameter) {
return axios({
url: '/sysUser/grantData',
method: 'post',
data: parameter
})
}
/**
* 修改状态
*
* @author yubaoshan
* @date 2020/6/23 21:36
*/
export function sysUserChangeStatus (parameter) {
return axios({
url: '/sysUser/changeStatus',
method: 'post',
data: parameter
})
}
/**
* 重置密码
*
* @author yubaoshan
* @date 2020/6/23 22:04
*/
export function sysUserResetPwd (parameter) {
return axios({
url: '/sysUser/resetPwd',
method: 'post',
data: parameter
})
}
/**
* 修改密码
*
* @author yubaoshan
* @date 2020/6/25 00:25
*/
export function sysUserUpdatePwd (parameter) {
return axios({
url: '/sysUser/updatePwd',
method: 'post',
data: parameter
})
}
/**
* 用户选择器
*
* @author yubaoshan
* @date 2020/6/25 00:25
*/
export function sysUserSelector (parameter) {
return axios({
url: '/sysUser/selector',
method: 'get',
params: parameter
})
}
/**
* 修改头像
*
* @author yubaoshan
* @date 2020/9/20 2:21
*/
export function sysUserUpdateAvatar (parameter) {
return axios({
url: '/sysUser/updateAvatar',
method: 'post',
data: parameter
})
}
/**
* 更新基本信息
*
* @author yubaoshan
* @date 2020/9/20 03:12
*/
export function sysUserUpdateInfo (parameter) {
return axios({
url: '/sysUser/updateInfo',
method: 'post',
data: parameter
})
}

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1551058675966" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7872" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M85.333333 512h85.333334a340.736 340.736 0 0 1 99.712-241.621333 337.493333 337.493333 0 0 1 108.458666-72.96 346.453333 346.453333 0 0 1 261.546667-1.749334A106.154667 106.154667 0 0 0 746.666667 298.666667C805.802667 298.666667 853.333333 251.136 853.333333 192S805.802667 85.333333 746.666667 85.333333c-29.397333 0-55.978667 11.776-75.221334 30.933334-103.722667-41.514667-222.848-40.874667-325.76 2.517333a423.594667 423.594667 0 0 0-135.68 91.264 423.253333 423.253333 0 0 0-91.306666 135.637333A426.88 426.88 0 0 0 85.333333 512z m741.248 133.205333c-17.109333 40.618667-41.685333 77.141333-72.96 108.416s-67.797333 55.850667-108.458666 72.96a346.453333 346.453333 0 0 1-261.546667 1.749334A106.154667 106.154667 0 0 0 277.333333 725.333333C218.197333 725.333333 170.666667 772.864 170.666667 832S218.197333 938.666667 277.333333 938.666667c29.397333 0 55.978667-11.776 75.221334-30.933334A425.173333 425.173333 0 0 0 512 938.666667a425.941333 425.941333 0 0 0 393.258667-260.352A426.325333 426.325333 0 0 0 938.666667 512h-85.333334a341.034667 341.034667 0 0 1-26.752 133.205333z" p-id="7873"></path><path d="M512 318.378667c-106.752 0-193.621333 86.869333-193.621333 193.621333S405.248 705.621333 512 705.621333s193.621333-86.869333 193.621333-193.621333S618.752 318.378667 512 318.378667z m0 301.909333c-59.690667 0-108.288-48.597333-108.288-108.288S452.309333 403.712 512 403.712s108.288 48.597333 108.288 108.288-48.597333 108.288-108.288 108.288z" p-id="7874"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

203
src/assets/logo.svg Normal file
View File

@ -0,0 +1,203 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve"> <image id="image0" width="500" height="500" x="0" y="0"
href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAMAAAD8CC+4AAAABGdBTUEAALGPC/xhBQAAACBjSFJN
AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAADAFBMVEX////X7v+w3//L6f/U
7v8ao/+64//i8/8lqP+v3//Z8P8HnP/S7f/v+f87sf8Amf8Onv8tq//n9f/5/f9Vu//R7f8Lnf9G
tf/z+v9txf/Q7P8Mnv9dvv/8/v+Dzf+75P/M6/8Jnf94yf+a1/+85P/I6f+T1P+04f8Bmf/F6P8E
m/8Tof8Cmv+95f/C5/8Qn//G6P/X7/8ip//A5v8Dmv8hpv/a8P/l9f8yrf83r//r9/+24v9Mt//2
+/9ev/9kwf/9/v9yx/++5f+BzP+Iz/+d2P+i2v+r3f+54//B5v+k2/8Xov/K6v8mqP/f8v/c8f8k
p/89sf/w+f/s9/+e2P9Tuv/7/f/4/P9NuP8Fm/+Z1v9pw/9iwP+Fzv97yv8Gm//L6v+W1f+Q0/+s
3v8InP/O6/+M0f8Yo/8SoP/P7P+Hz//h8//W7/8epf8Knf8+sv/x+f/m9f8vrP9XvP9Bs/9/zP9x
xv/6/f+K0P9vxf+p3f91yP+c1//T7f+y4P/J6f9lwf92yP9gv/9avf9Wu/8RoP/E5//Y7/+g2f9Q
uf80rv9OuP/b8f9jwf/e8v8oqf9Cs/99y/8Uof/d8f/3/P/1+/8jp//0+/8pqf86sP/t+P/y+v9r
xP8Vof/g8//o9v/u+P/H6f/j9P/k9P/p9v81rv8bpP9Jtv/q9/90x/+P0v9sxP9DtP9Zvf8sqv9Y
vP9mwv9qw//q9v84pv8Akv9Itv8Ck//g8v8qqv8Bkv+J0P8wrP+S0/+m2/9Puf95yf+95P+o3P+t
3v/V7v85sP+n3P+i2f9hwP9kwP98y/9PuP9Es/8/sf87sP+/5v8Alf/v+P9EtP/H6P8Mnf8Im/8E
mv+x4P8Dmf8cpP8AmP+r3v+S1P9vxv9bvv9Ouf////88sv8zqf8tpf8ppP8kov/0+v9txP8gof8b
nv8Wm/8Sm/8Omf8Kl/8Glf/d8v9ZvP8Ak/9jwP8jpP8VnP/l9P88r/84q/82qv8Bk//R7P8wp/8q
of9Suf9Js/81rP+Y1f/HFJ4WAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAHdElNRQflAwMC
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
D5OidHPCce5xV2HoNy3XZLbDvBrni+tuDT0VM90xme3KOoOrYMwY/JpTKgr9TJ/oYrfXmvkG18AY
M8Gl7jstev88e6tD+xv4z9iQ5rA3Qt/e+xTa2szd0jZ0SFoCE6yPrv6UtJllm8xW9ryB54w9abYF
Hukls9W97Czu5A+1uHHD7sn+LGlwXczG3sqkr+ObULxlVY1kNGnvgE3btystuFZQGJ6xWKDbQlqz
6JK4akUPA3cZCIPNF+i2kcZOGndmOzHVwFcGxnXT6akQ3XCtL+fd46GvvqXyluFrPP1MLzVrx1fW
18BLBkx0Sxg90UcYdWa72WxbmycHG0xe4+nbew+DJl0rOWctONf138G60Fb0G0csaGEl2hOTs911
9TpNG1mgaSKDP9QShGuaC3SLaBOajSNKikJfK1PLWr1v9h20Ba3GEelLjmq7xPhH61DN4/Tf6zwi
yibq+8PEg+kaso2k/1wjmW3UBn1vmDgxOfI1vjv9x+9G/W3xdX1PmPixNmqy76L/Nqo24dwW0zKv
2TG+2FZ0dTLb7s8LQl8aQ6JejVfc3pW1CUu49F9iM7nYSvT36L9afog/1BKdtO42ot9H/tGQQfpj
M8EYT73GK57pZHWTRXP0B2YCQn2zX6b/5Cv5X+TfCH0tjDbXpAt0Heg/kJe02cQfas2Js7KOjXPp
38tqHvRr4W0SmyF7mz7Z99G/HtO05sFm/lBrfhxo8mR/lf7xm4WNfrt+LKeiNkuuNfpmH07/tHFe
01Wu0d5cWdvwyX6R/uVDGfV/mNtldmjXGXvGv1NPy0707/bH6n+ofRXabcaJA5e1RJ9RrzPbprWh
nWZcub31phA9LbX2R4cfC+0wAyDtw+hn+oXarIlOnIqaJOwtjhJ9dk1e0/KeR0L7yqA4UD3Zr9A/
OL6x6gdcMyi5qJrsimf60SFCZHPNoGRjxi4xi/6/R4aKad+GdpHB8w8v0U1ut/7+3LdC+8f4oC3d
8nTrm5yjxjAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAM
wzAMwzAMwzAMwzAMwzAMwzAMwzAMwzAMwzDJyf8H/RgaDtLOxBkAAAAldEVYdGRhdGU6Y3JlYXRl
ADIwMjEtMDMtMDJUMTg6MDA6MDArMDg6MDA9+rsMAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTAz
LTAyVDE4OjAwOjAwKzA4OjAwTKcDsAAAACB0RVh0c29mdHdhcmUAaHR0cHM6Ly9pbWFnZW1hZ2lj
ay5vcme8zx2dAAAAGHRFWHRUaHVtYjo6RG9jdW1lbnQ6OlBhZ2VzADGn/7svAAAAGHRFWHRUaHVt
Yjo6SW1hZ2U6OkhlaWdodAA1MDB4mAPsAAAAF3RFWHRUaHVtYjo6SW1hZ2U6OldpZHRoADUwMOtp
U7EAAAAZdEVYdFRodW1iOjpNaW1ldHlwZQBpbWFnZS9wbmc/slZOAAAAF3RFWHRUaHVtYjo6TVRp
bWUAMTYxNDY3OTIwMCAf/wcAAAATdEVYdFRodW1iOjpTaXplADExMjczQkI7FGLOAAAARnRFWHRU
aHVtYjo6VVJJAGZpbGU6Ly8vYXBwL3RtcC9pbWFnZWxjL2ltZ3ZpZXcyXzlfMTYwOTkwMzUxMTcy
MzMzODZfOTJfWzBdRG9xdgAAAABJRU5ErkJggg==" ></image>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/assets/welcome.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,89 @@
<template>
<div class="antd-pro-components-article-list-content-index-listContent">
<div class="description">
<slot>
{{ description }}
</slot>
</div>
<div class="extra">
<a-avatar :src="avatar" size="small" />
<a :href="href">{{ owner }}</a> 发布在 <a :href="href">{{ href }}</a>
<em>{{ updateAt | moment }}</em>
</div>
</div>
</template>
<script>
export default {
name: 'ArticleListContent',
props: {
prefixCls: {
type: String,
default: 'antd-pro-components-article-list-content-index-listContent'
},
description: {
type: String,
default: ''
},
owner: {
type: String,
required: true
},
avatar: {
type: String,
required: true
},
href: {
type: String,
required: true
},
updateAt: {
type: String,
required: true
}
}
}
</script>
<style lang="less" scoped>
@import '../index.less';
.antd-pro-components-article-list-content-index-listContent {
.description {
max-width: 720px;
line-height: 22px;
}
.extra {
margin-top: 16px;
color: @text-color-secondary;
line-height: 22px;
& /deep/ .ant-avatar {
position: relative;
top: 1px;
width: 20px;
height: 20px;
margin-right: 8px;
vertical-align: top;
}
& > em {
margin-left: 16px;
color: @disabled-color;
font-style: normal;
}
}
}
@media screen and (max-width: @screen-xs) {
.antd-pro-components-article-list-content-index-listContent {
.extra {
& > em {
display: block;
margin-top: 8px;
margin-left: 0;
}
}
}
}
</style>

View File

@ -0,0 +1,3 @@
import ArticleListContent from './ArticleListContent'
export default ArticleListContent

View File

@ -0,0 +1,46 @@
<template>
<tooltip v-if="tips !== ''">
<template slot="title">{{ tips }}</template>
<avatar :size="avatarSize" :src="src" />
</tooltip>
<avatar v-else :size="avatarSize" :src="src" />
</template>
<script>
import Avatar from 'ant-design-vue/es/avatar'
import Tooltip from 'ant-design-vue/es/tooltip'
export default {
name: 'AvatarItem',
components: {
Avatar,
Tooltip
},
props: {
tips: {
type: String,
default: '',
required: false
},
src: {
type: String,
default: ''
}
},
data () {
return {
size: this.$parent.size
}
},
computed: {
avatarSize () {
return this.size !== 'mini' && this.size || 20
}
},
watch: {
'$parent.size' (val) {
this.size = val
}
}
}
</script>

View File

@ -0,0 +1,99 @@
<!--
<template>
<div :class="[prefixCls]">
<ul>
<slot></slot>
<template v-for="item in filterEmpty($slots.default).slice(0, 3)"></template>
<template v-if="maxLength > 0 && filterEmpty($slots.default).length > maxLength">
<avatar-item :size="size">
<avatar :size="size !== 'mini' && size || 20" :style="excessItemsStyle">{{ `+${maxLength}` }}</avatar>
</avatar-item>
</template>
</ul>
</div>
</template>
-->
<script>
import Avatar from 'ant-design-vue/es/avatar'
import AvatarItem from './Item'
import { filterEmpty } from '@/components/_util/util'
export default {
AvatarItem,
name: 'AvatarList',
components: {
Avatar,
AvatarItem
},
props: {
prefixCls: {
type: String,
default: 'ant-pro-avatar-list'
},
/**
* 头像大小 类型: largesmall mini, default
* 默认值: default
*/
size: {
type: [String, Number],
default: 'default'
},
/**
* 要显示的最大项目
*/
maxLength: {
type: Number,
default: 0
},
/**
* 多余的项目风格
*/
excessItemsStyle: {
type: Object,
default: () => {
return {
color: '#f56a00',
backgroundColor: '#fde3cf'
}
}
}
},
data () {
return {}
},
methods: {
getItems (items) {
const classString = {
[`${this.prefixCls}-item`]: true,
[`${this.size}`]: true
}
if (this.maxLength > 0) {
items = items.slice(0, this.maxLength)
items.push((<Avatar size={ this.size } style={ this.excessItemsStyle }>{`+${this.maxLength}`}</Avatar>))
}
const itemList = items.map((item) => (
<li class={ classString }>{ item }</li>
))
return itemList
}
},
render () {
const { prefixCls, size } = this.$props
const classString = {
[`${prefixCls}`]: true,
[`${size}`]: true
}
const items = filterEmpty(this.$slots.default)
const itemsDom = items && items.length ? <ul class={`${prefixCls}-items`}>{ this.getItems(items) }</ul> : null
return (
<div class={ classString }>
{ itemsDom }
</div>
)
}
}
</script>

View File

@ -0,0 +1,4 @@
import AvatarList from './List'
import './index.less'
export default AvatarList

View File

@ -0,0 +1,60 @@
@import "../index";
@avatar-list-prefix-cls: ~"@{ant-pro-prefix}-avatar-list";
@avatar-list-item-prefix-cls: ~"@{ant-pro-prefix}-avatar-list-item";
.@{avatar-list-prefix-cls} {
display: inline-block;
ul {
list-style: none;
display: inline-block;
padding: 0;
margin: 0 0 0 8px;
font-size: 0;
}
}
.@{avatar-list-item-prefix-cls} {
display: inline-block;
font-size: @font-size-base;
margin-left: -8px;
width: @avatar-size-base;
height: @avatar-size-base;
:global {
.ant-avatar {
border: 1px solid #fff;
cursor: pointer;
}
}
&.large {
width: @avatar-size-lg;
height: @avatar-size-lg;
}
&.small {
width: @avatar-size-sm;
height: @avatar-size-sm;
}
&.mini {
width: 20px;
height: 20px;
:global {
.ant-avatar {
width: 20px;
height: 20px;
line-height: 20px;
.ant-avatar-string {
font-size: 12px;
line-height: 18px;
}
}
}
}
}

View File

@ -0,0 +1,64 @@
# AvatarList 用户头像列表
一组用户头像,常用在项目/团队成员列表。可通过设置 `size` 属性来指定头像大小。
引用方式:
```javascript
import AvatarList from '@/components/AvatarList'
const AvatarListItem = AvatarList.AvatarItem
export default {
components: {
AvatarList,
AvatarListItem
}
}
```
## 代码演示 [demo](https://pro.loacg.com/test/home)
```html
<avatar-list size="mini">
<avatar-list-item tips="Jake" src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png" />
<avatar-list-item tips="Andy" src="https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
</avatar-list>
```
```html
<avatar-list :max-length="3">
<avatar-list-item tips="Jake" src="https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png" />
<avatar-list-item tips="Andy" src="https://gw.alipayobjects.com/zos/rmsportal/sfjbOqnsXXJgNCjCzDBL.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
<avatar-list-item tips="Niko" src="https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png" />
</avatar-list>
```
## API
### AvatarList
| 参数 | 说明 | 类型 | 默认值 |
| ---------------- | -------- | ---------------------------------- | --------- |
| size | 头像大小 | `large`、`small` 、`mini`, `default` | `default` |
| maxLength | 要显示的最大项目 | number | - |
| excessItemsStyle | 多余的项目风格 | CSSProperties | - |
### AvatarList.Item
| 参数 | 说明 | 类型 | 默认值 |
| ---- | ------ | --------- | --- |
| tips | 头像展示文案 | string | - |
| src | 头像图片连接 | string | - |

View File

@ -0,0 +1,62 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart
height="254"
:data="data"
:forceFit="true"
:padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-bar position="x*y"/>
</v-chart>
</div>
</template>
<script>
export default {
name: 'Bar',
props: {
title: {
type: String,
default: ''
},
data: {
type: Array,
default: () => {
return []
}
},
scale: {
type: Array,
default: () => {
return [{
dataKey: 'x',
min: 2
}, {
dataKey: 'y',
title: '时间',
min: 1,
max: 22
}]
}
},
tooltip: {
type: Array,
default: () => {
return [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
}
}
},
data () {
return {
}
}
}
</script>

View File

@ -0,0 +1,120 @@
<template>
<a-card :loading="loading" :body-style="{ padding: '20px 24px 8px' }" :bordered="false">
<div class="chart-card-header">
<div class="meta">
<span class="chart-card-title">
<slot name="title">
{{ title }}
</slot>
</span>
<span class="chart-card-action">
<slot name="action"></slot>
</span>
</div>
<div class="total">
<slot name="total">
<span>{{ typeof total === 'function' && total() || total }}</span>
</slot>
</div>
</div>
<div class="chart-card-content">
<div class="content-fix">
<slot></slot>
</div>
</div>
<div class="chart-card-footer">
<div class="field">
<slot name="footer"></slot>
</div>
</div>
</a-card>
</template>
<script>
export default {
name: 'ChartCard',
props: {
title: {
type: String,
default: ''
},
total: {
type: [Function, Number, String],
required: false,
default: null
},
loading: {
type: Boolean,
default: false
}
}
}
</script>
<style lang="less" scoped>
.chart-card-header {
position: relative;
overflow: hidden;
width: 100%;
.meta {
position: relative;
overflow: hidden;
width: 100%;
color: rgba(0, 0, 0, .45);
font-size: 14px;
line-height: 22px;
}
}
.chart-card-action {
cursor: pointer;
position: absolute;
top: 0;
right: 0;
}
.chart-card-footer {
border-top: 1px solid #e8e8e8;
padding-top: 9px;
margin-top: 8px;
> * {
position: relative;
}
.field {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
}
}
.chart-card-content {
margin-bottom: 12px;
position: relative;
height: 46px;
width: 100%;
.content-fix {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
}
}
.total {
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
color: #000;
margin-top: 4px;
margin-bottom: 0;
font-size: 30px;
line-height: 38px;
height: 38px;
}
</style>

View File

@ -0,0 +1,67 @@
<template>
<div>
<v-chart
:forceFit="true"
:height="height"
:width="width"
:data="data"
:scale="scale"
:padding="0">
<v-tooltip />
<v-interval
:shape="['liquid-fill-gauge']"
position="transfer*value"
color=""
:v-style="{
lineWidth: 10,
opacity: 0.75
}"
:tooltip="[
'transfer*value',
(transfer, value) => {
return {
name: transfer,
value,
};
},
]"
></v-interval>
<v-guide
v-for="(row, index) in data"
:key="index"
type="text"
:top="true"
:position="{
gender: row.transfer,
value: 45
}"
:content="row.value + '%'"
:v-style="{
fontSize: 100,
textAlign: 'center',
opacity: 0.75,
}"
/>
</v-chart>
</div>
</template>
<script>
export default {
name: 'Liquid',
props: {
height: {
type: Number,
default: 0
},
width: {
type: Number,
default: 0
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="antv-chart-mini">
<div class="chart-wrapper" :style="{ height: 46 }">
<v-chart :force-fit="true" :height="height" :data="data" :padding="[36, 0, 18, 0]">
<v-tooltip />
<v-smooth-area position="x*y" />
</v-chart>
</div>
</div>
</template>
<script>
import moment from 'moment'
const data = []
const beginDay = new Date().getTime()
for (let i = 0; i < 10; i++) {
data.push({
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
y: Math.round(Math.random() * 10)
})
}
const tooltip = [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
const scale = [{
dataKey: 'x',
min: 2
}, {
dataKey: 'y',
title: '时间',
min: 1,
max: 22
}]
export default {
name: 'MiniArea',
data () {
return {
data,
tooltip,
scale,
height: 100
}
}
}
</script>
<style lang="less" scoped>
@import "chart";
</style>

View File

@ -0,0 +1,57 @@
<template>
<div class="antv-chart-mini">
<div class="chart-wrapper" :style="{ height: 46 }">
<v-chart :force-fit="true" :height="height" :data="data" :padding="[36, 5, 18, 5]">
<v-tooltip />
<v-bar position="x*y" />
</v-chart>
</div>
</div>
</template>
<script>
import moment from 'moment'
const data = []
const beginDay = new Date().getTime()
for (let i = 0; i < 10; i++) {
data.push({
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
y: Math.round(Math.random() * 10)
})
}
const tooltip = [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
const scale = [{
dataKey: 'x',
min: 2
}, {
dataKey: 'y',
title: '时间',
min: 1,
max: 30
}]
export default {
name: 'MiniBar',
data () {
return {
data,
tooltip,
scale,
height: 100
}
}
}
</script>
<style lang="less" scoped>
@import "chart";
</style>

View File

@ -0,0 +1,75 @@
<template>
<div class="chart-mini-progress">
<div class="target" :style="{ left: target + '%'}">
<span :style="{ backgroundColor: color }" />
<span :style="{ backgroundColor: color }"/>
</div>
<div class="progress-wrapper">
<div class="progress" :style="{ backgroundColor: color, width: percentage + '%', height: height }"></div>
</div>
</div>
</template>
<script>
export default {
name: 'MiniProgress',
props: {
target: {
type: Number,
default: 0
},
height: {
type: String,
default: '10px'
},
color: {
type: String,
default: '#13C2C2'
},
percentage: {
type: Number,
default: 0
}
}
}
</script>
<style lang="less" scoped>
.chart-mini-progress {
padding: 5px 0;
position: relative;
width: 100%;
.target {
position: absolute;
top: 0;
bottom: 0;
span {
border-radius: 100px;
position: absolute;
top: 0;
left: 0;
height: 4px;
width: 2px;
&:last-child {
top: auto;
bottom: 0;
}
}
}
.progress-wrapper {
background-color: #f5f5f5;
position: relative;
.progress {
transition: all .4s cubic-bezier(.08,.82,.17,1) 0s;
border-radius: 1px 0 0 1px;
background-color: #1890ff;
width: 0;
height: 100%;
}
}
}
</style>

View File

@ -0,0 +1,40 @@
<template>
<div :class="prefixCls">
<div class="chart-wrapper" :style="{ height: 46 }">
<v-chart :force-fit="true" :height="100" :data="dataSource" :scale="scale" :padding="[36, 0, 18, 0]">
<v-tooltip />
<v-smooth-line position="x*y" :size="2" />
<v-smooth-area position="x*y" />
</v-chart>
</div>
</div>
</template>
<script>
export default {
name: 'MiniSmoothArea',
props: {
prefixCls: {
type: String,
default: 'ant-pro-smooth-area'
},
scale: {
type: [Object, Array],
required: true
},
dataSource: {
type: Array,
required: true
}
},
data () {
return {
height: 100
}
}
}
</script>
<style lang="less" scoped>
@import "smooth.area.less";
</style>

View File

@ -0,0 +1,68 @@
<template>
<v-chart :forceFit="true" height="400" :data="data" :padding="[20, 20, 95, 20]" :scale="scale">
<v-tooltip></v-tooltip>
<v-axis :dataKey="axis1Opts.dataKey" :line="axis1Opts.line" :tickLine="axis1Opts.tickLine" :grid="axis1Opts.grid" />
<v-axis :dataKey="axis2Opts.dataKey" :line="axis2Opts.line" :tickLine="axis2Opts.tickLine" :grid="axis2Opts.grid" />
<v-legend dataKey="user" marker="circle" :offset="30" />
<v-coord type="polar" radius="0.8" />
<v-line position="item*score" color="user" :size="2" />
<v-point position="item*score" color="user" :size="4" shape="circle" />
</v-chart>
</template>
<script>
const axis1Opts = {
dataKey: 'item',
line: null,
tickLine: null,
grid: {
lineStyle: {
lineDash: null
},
hideFirstLine: false
}
}
const axis2Opts = {
dataKey: 'score',
line: null,
tickLine: null,
grid: {
type: 'polygon',
lineStyle: {
lineDash: null
}
}
}
const scale = [
{
dataKey: 'score',
min: 0,
max: 80
}, {
dataKey: 'user',
alias: '类型'
}
]
export default {
name: 'Radar',
props: {
data: {
type: Array,
default: null
}
},
data () {
return {
axis1Opts,
axis2Opts,
scale
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,77 @@
<template>
<div class="rank">
<h4 class="title">{{ title }}</h4>
<ul class="list">
<li :key="index" v-for="(item, index) in list">
<span :class="index < 3 ? 'active' : null">{{ index + 1 }}</span>
<span>{{ item.name }}</span>
<span>{{ item.total }}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'RankList',
// ['title', 'list']
props: {
title: {
type: String,
default: ''
},
list: {
type: Array,
default: null
}
}
}
</script>
<style lang="less" scoped>
.rank {
padding: 0 32px 32px 72px;
.list {
margin: 25px 0 0;
padding: 0;
list-style: none;
li {
margin-top: 16px;
span {
color: rgba(0, 0, 0, .65);
font-size: 14px;
line-height: 22px;
&:first-child {
background-color: #f5f5f5;
border-radius: 20px;
display: inline-block;
font-size: 12px;
font-weight: 600;
margin-right: 24px;
height: 20px;
line-height: 20px;
width: 20px;
text-align: center;
}
&.active {
background-color: #314659;
color: #fff;
}
&:last-child {
float: right;
}
}
}
}
}
.mobile .rank {
padding: 0 32px 32px 32px;
}
</style>

View File

@ -0,0 +1,113 @@
<template>
<v-chart :width="width" :height="height" :padding="[0]" :data="data" :scale="scale">
<v-tooltip :show-title="false" />
<v-coord type="rect" direction="TL" />
<v-point position="x*y" color="category" shape="cloud" tooltip="value*category" />
</v-chart>
</template>
<script>
import { registerShape } from 'viser-vue'
const DataSet = require('@antv/data-set')
const imgUrl = 'https://gw.alipayobjects.com/zos/rmsportal/gWyeGLCdFFRavBGIDzWk.png'
const scale = [
{ dataKey: 'x', nice: false },
{ dataKey: 'y', nice: false }
]
registerShape('point', 'cloud', {
draw (cfg, container) {
return container.addShape('text', {
attrs: {
fillOpacity: cfg.opacity,
fontSize: cfg.origin._origin.size,
rotate: cfg.origin._origin.rotate,
text: cfg.origin._origin.text,
textAlign: 'center',
fontFamily: cfg.origin._origin.font,
fill: cfg.color,
textBaseline: 'Alphabetic',
...cfg.style,
x: cfg.x,
y: cfg.y
}
})
}
})
export default {
name: 'TagCloud',
props: {
tagList: {
type: Array,
required: true
},
height: {
type: Number,
default: 400
},
width: {
type: Number,
default: 640
}
},
data () {
return {
data: [],
scale
}
},
watch: {
tagList: function (val) {
if (val.length > 0) {
this.initTagCloud(val)
}
}
},
mounted () {
if (this.tagList.length > 0) {
this.initTagCloud(this.tagList)
}
},
methods: {
initTagCloud (dataSource) {
const { height, width } = this
const dv = new DataSet.View().source(dataSource)
const range = dv.range('value')
const min = range[0]
const max = range[1]
const imageMask = new Image()
imageMask.crossOrigin = ''
imageMask.src = imgUrl
imageMask.onload = () => {
dv.transform({
type: 'tag-cloud',
fields: ['name', 'value'],
size: [width, height],
imageMask,
font: 'Verdana',
padding: 0,
timeInterval: 5000, // max execute time
rotate () {
let random = ~~(Math.random() * 4) % 4
if (random === 2) {
random = 0
}
return random * 90 // 0, 90, 270
},
fontSize (d) {
if (d.value) {
return ((d.value - min) / (max - min)) * (32 - 8) + 8
}
return 0
}
})
this.data = dv.rows
}
}
}
}
</script>

View File

@ -0,0 +1,64 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart
height="254"
:data="data"
:scale="scale"
:forceFit="true"
:padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-bar position="x*y"/>
</v-chart>
</div>
</template>
<script>
const tooltip = [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
const scale = [{
dataKey: 'x',
title: '日期(天)',
alias: '日期(天)',
min: 2
}, {
dataKey: 'y',
title: '流量(Gb)',
alias: '流量(Gb)',
min: 1
}]
export default {
name: 'Bar',
props: {
title: {
type: String,
default: ''
}
},
data () {
return {
data: [],
scale,
tooltip
}
},
created () {
this.getMonthBar()
},
methods: {
getMonthBar () {
this.$http.get('/analysis/month-bar')
.then(res => {
this.data = res.result
})
}
}
}
</script>

View File

@ -0,0 +1,82 @@
<template>
<div class="chart-trend">
{{ term }}
<span>{{ rate }}%</span>
<span :class="['trend-icon', trend]"><a-icon :type="'caret-' + trend"/></span>
</div>
</template>
<script>
export default {
name: 'Trend',
props: {
term: {
type: String,
default: '',
required: true
},
percentage: {
type: Number,
default: null
},
type: {
type: Boolean,
default: null
},
target: {
type: Number,
default: 0
},
value: {
type: Number,
default: 0
},
fixed: {
type: Number,
default: 2
}
},
data () {
return {
trend: this.type && 'up' || 'down',
rate: this.percentage
}
},
created () {
const type = this.type === null ? this.value >= this.target : this.type
this.trend = type ? 'up' : 'down'
this.rate = (this.percentage === null ? Math.abs(this.value - this.target) * 100 / this.target : this.percentage).toFixed(this.fixed)
}
}
</script>
<style lang="less" scoped>
.chart-trend {
display: inline-block;
font-size: 14px;
line-height: 22px;
.trend-icon {
font-size: 12px;
&.up, &.down {
margin-left: 4px;
position: relative;
top: 1px;
i {
font-size: 12px;
transform: scale(.83);
}
}
&.up {
color: #f5222d;
}
&.down {
color: #52c41a;
top: -1px;
}
}
}
</style>

View File

@ -0,0 +1,13 @@
.antv-chart-mini {
position: relative;
width: 100%;
.chart-wrapper {
position: absolute;
bottom: -28px;
width: 100%;
/* margin: 0 -5px;
overflow: hidden;*/
}
}

View File

@ -0,0 +1,14 @@
@import "../index";
@smoothArea-prefix-cls: ~"@{ant-pro-prefix}-smooth-area";
.@{smoothArea-prefix-cls} {
position: relative;
width: 100%;
.chart-wrapper {
position: absolute;
bottom: -28px;
width: 100%;
}
}

View File

@ -0,0 +1,102 @@
<template>
<span>
{{ lastTime | format }}
</span>
</template>
<script>
function fixedZero (val) {
return val * 1 < 10 ? `0${val}` : val
}
export default {
name: 'CountDown',
props: {
format: {
type: Function,
default: undefined
},
target: {
type: [Date, Number],
required: true
},
onEnd: {
type: Function,
default: () => ({})
}
},
data () {
return {
dateTime: '0',
originTargetTime: 0,
lastTime: 0,
timer: 0,
interval: 1000
}
},
filters: {
format (time) {
const hours = 60 * 60 * 1000
const minutes = 60 * 1000
const h = Math.floor(time / hours)
const m = Math.floor((time - h * hours) / minutes)
const s = Math.floor((time - h * hours - m * minutes) / 1000)
return `${fixedZero(h)}:${fixedZero(m)}:${fixedZero(s)}`
}
},
created () {
this.initTime()
this.tick()
},
methods: {
initTime () {
let lastTime = 0
let targetTime = 0
this.originTargetTime = this.target
try {
if (Object.prototype.toString.call(this.target) === '[object Date]') {
targetTime = this.target
} else {
targetTime = new Date(this.target).getTime()
}
} catch (e) {
throw new Error('invalid target prop')
}
lastTime = targetTime - new Date().getTime()
this.lastTime = lastTime < 0 ? 0 : lastTime
},
tick () {
const { onEnd } = this
this.timer = setTimeout(() => {
if (this.lastTime < this.interval) {
clearTimeout(this.timer)
this.lastTime = 0
if (typeof onEnd === 'function') {
onEnd()
}
} else {
this.lastTime -= this.interval
this.tick()
}
}, this.interval)
}
},
beforeUpdate () {
if (this.originTargetTime !== this.target) {
this.initTime()
}
},
beforeDestroy () {
clearTimeout(this.timer)
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,3 @@
import CountDown from './CountDown'
export default CountDown

View File

@ -0,0 +1,34 @@
# CountDown 倒计时
倒计时组件。
引用方式:
```javascript
import CountDown from '@/components/CountDown/CountDown'
export default {
components: {
CountDown
}
}
```
## 代码演示 [demo](https://pro.loacg.com/test/home)
```html
<count-down :target="new Date().getTime() + 3000000" :on-end="onEndHandle" />
```
## API
| 参数 | 说明 | 类型 | 默认值 |
|----------|------------------------------------------|-------------|-------|
| target | 目标时间 | Date | - |
| onEnd | 倒计时结束回调 | funtion | -|

View File

@ -0,0 +1,48 @@
<template>
<a-tree-select
:dropdownStyle="{ maxHeight: '300px', overflow: 'auto' }"
allowClear
:treeData="orgTree"
:placeholder="placeholder"
treeDefaultExpandAll
@change="onchange"
>
<span slot="title" slot-scope="{ id }">{{ id }}</span>
</a-tree-select>
</template>
<script>
import { getOrgTree } from '@/api/modular/system/orgManage'
export default {
name: 'DepartSelect',
props: {
placeholder: {
type: String
},
value: {
type: String
}
},
data() {
return {
orgTree: []
}
},
created() {
this.getOrgData()
},
methods: {
getOrgData() {
getOrgTree().then((res) => {
this.orgTree = res
})
},
/**
* 选择树机构初始化机构名称于表单中
*/
onchange (value) {
this.$emit('change', value)
}
}
}
</script>

View File

@ -0,0 +1,3 @@
import DepartmentSelect from './DepartmentSelect'
export default DepartmentSelect

View File

@ -0,0 +1,153 @@
<template>
<div :class="['description-list', size, layout === 'vertical' ? 'vertical': 'horizontal']">
<div v-if="title" class="title">{{ title }}</div>
<a-row>
<slot></slot>
</a-row>
</div>
</template>
<script>
import { Col } from 'ant-design-vue/es/grid/'
const Item = {
name: 'DetailListItem',
props: {
term: {
type: String,
default: '',
required: false
}
},
inject: {
col: {
type: Number
}
},
render () {
return (
<Col {...{ props: responsive[this.col] }}>
<div class="term">{this.$props.term}</div>
<div class="content">{this.$slots.default}</div>
</Col>
)
}
}
const responsive = {
1: { xs: 24 },
2: { xs: 24, sm: 12 },
3: { xs: 24, sm: 12, md: 8 },
4: { xs: 24, sm: 12, md: 6 }
}
export default {
name: 'DetailList',
Item: Item,
components: {
Col
},
props: {
title: {
type: String,
default: '',
required: false
},
col: {
type: Number,
required: false,
default: 3
},
size: {
type: String,
required: false,
default: 'large'
},
layout: {
type: String,
required: false,
default: 'horizontal'
}
},
provide () {
return {
col: this.col > 4 ? 4 : this.col
}
}
}
</script>
<style lang="less" scoped>
.description-list {
.title {
color: rgba(0,0,0,.85);
font-size: 14px;
font-weight: 500;
margin-bottom: 16px;
}
/deep/ .term {
color: rgba(0,0,0,.85);
display: table-cell;
line-height: 20px;
margin-right: 8px;
padding-bottom: 16px;
white-space: nowrap;
&:not(:empty):after {
content: ":";
margin: 0 8px 0 2px;
position: relative;
top: -.5px;
}
}
/deep/ .content {
color: rgba(0,0,0,.65);
display: table-cell;
min-height: 22px;
line-height: 22px;
padding-bottom: 16px;
width: 100%;
&:empty {
content: ' ';
height: 38px;
padding-bottom: 16px;
}
}
&.small {
.title {
font-size: 14px;
color: rgba(0, 0, 0, .65);
font-weight: normal;
margin-bottom: 12px;
}
/deep/ .term, .content {
padding-bottom: 8px;
}
}
&.large {
/deep/ .term, .content {
padding-bottom: 16px;
}
.title {
font-size: 16px;
}
}
&.vertical {
.term {
padding-bottom: 8px;
}
/deep/ .term, .content {
display: block;
}
}
}
</style>

View File

@ -0,0 +1,2 @@
import DescriptionList from './DescriptionList'
export default DescriptionList

113
src/components/Dialog.js Normal file
View File

@ -0,0 +1,113 @@
import Modal from 'ant-design-vue/es/modal'
export default (Vue) => {
function dialog (component, componentProps, modalProps) {
const _vm = this
modalProps = modalProps || {}
if (!_vm || !_vm._isVue) {
return
}
let dialogDiv = document.querySelector('body>div[type=dialog]')
if (!dialogDiv) {
dialogDiv = document.createElement('div')
dialogDiv.setAttribute('type', 'dialog')
document.body.appendChild(dialogDiv)
}
const handle = function (checkFunction, afterHandel) {
if (checkFunction instanceof Function) {
const res = checkFunction()
if (res instanceof Promise) {
res.then(c => {
c && afterHandel()
})
} else {
res && afterHandel()
}
} else {
// checkFunction && afterHandel()
checkFunction || afterHandel()
}
}
const dialogInstance = new Vue({
data () {
return {
visible: true
}
},
router: _vm.$router,
store: _vm.$store,
mounted () {
this.$on('close', (v) => {
this.handleClose()
})
},
methods: {
handleClose () {
handle(this.$refs._component.onCancel, () => {
this.visible = false
this.$refs._component.$emit('close')
this.$refs._component.$emit('cancel')
dialogInstance.$destroy()
})
},
handleOk () {
handle(this.$refs._component.onOK || this.$refs._component.onOk, () => {
this.visible = false
this.$refs._component.$emit('close')
this.$refs._component.$emit('ok')
dialogInstance.$destroy()
})
}
},
render: function (h) {
const that = this
const modalModel = modalProps && modalProps.model
if (modalModel) {
delete modalProps.model
}
const ModalProps = Object.assign({}, modalModel && { model: modalModel } || {}, {
attrs: Object.assign({}, {
...(modalProps.attrs || modalProps)
}, {
visible: this.visible
}),
on: Object.assign({}, {
...(modalProps.on || modalProps)
}, {
ok: () => {
that.handleOk()
},
cancel: () => {
that.handleClose()
}
})
})
const componentModel = componentProps && componentProps.model
if (componentModel) {
delete componentProps.model
}
const ComponentProps = Object.assign({}, componentModel && { model: componentModel } || {}, {
ref: '_component',
attrs: Object.assign({}, {
...((componentProps && componentProps.attrs) || componentProps)
}),
on: Object.assign({}, {
...((componentProps && componentProps.on) || componentProps)
})
})
return h(Modal, ModalProps, [h(component, ComponentProps)])
}
}).$mount(dialogDiv)
}
Object.defineProperty(Vue.prototype, '$dialog', {
get: () => {
return function () {
dialog.apply(this, arguments)
}
}
})
}

View File

@ -0,0 +1,82 @@
<template>
<div :class="prefixCls">
<quill-editor
v-model="content"
ref="myQuillEditor"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@ready="onEditorReady($event)"
@change="onEditorChange($event)">
</quill-editor>
</div>
</template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'
export default {
name: 'QuillEditor',
components: {
quillEditor
},
props: {
prefixCls: {
type: String,
default: 'ant-editor-quill'
},
//
// eslint-disable-next-line
value: {
type: String
}
},
data () {
return {
content: null,
editorOption: {
// some quill options
}
}
},
methods: {
onEditorBlur (quill) {
console.log('editor blur!', quill)
},
onEditorFocus (quill) {
console.log('editor focus!', quill)
},
onEditorReady (quill) {
console.log('editor ready!', quill)
},
onEditorChange ({ quill, html, text }) {
console.log('editor change!', quill, html, text)
this.$emit('change', html)
}
},
watch: {
value (val) {
this.content = val
}
}
}
</script>
<style lang="less" scoped>
@import url('../index.less');
/* 覆盖 quill 默认边框圆角为 ant 默认圆角,用于统一 ant 组件风格 */
.ant-editor-quill {
/deep/ .ql-toolbar.ql-snow {
border-radius: @border-radius-base @border-radius-base 0 0;
}
/deep/ .ql-container.ql-snow {
border-radius: 0 0 @border-radius-base @border-radius-base;
}
}
</style>

View File

@ -0,0 +1,126 @@
<template>
<div>
<div id="editor" ref="myEditor"></div>
<slot></slot>
</div>
</template>
<script>
import WangEditor from 'wangeditor'
export default {
name: 'ComponentWangeditor',
data () {
return {
edit: ''
}
},
props: {
value: {
type: String,
default: ''
},
config: {
type: Object,
default: () => {
return {}
}
},
uploadConfig: {
type: Object,
default: () => {
return {
method: 'http', // custom(objurl)http()base64
url: '/'
}
}
}
},
computed: {
customConfig () {
return {
pasteFilterStyle: false, //
pasteIgnoreImg: false, //
...this.config
}
}
},
watch: {
},
components: {
},
methods: {
readBlobAsDataURL (blob, callback) {
var a = new FileReader()
a.onload = function (e) { callback(e.target.result) }
a.readAsDataURL(blob)
},
initEditor () {
var self = this
this.editor = new WangEditor(this.$refs.myEditor)
// onchange
this.editor.customConfig = this.customConfig
this.editor.customConfig.uploadImgMaxLength = 5
this.editor.change = function () { //
self.$emit('input', this.txt.html())
self.$emit('onchange', this.txt.html(), this.txt)
// editor.txt.html('.....') //
// editor.txt.clear() //
// editor.txt.append('<p></p>')//
// editor.txt.text() // text
// editor.txt.getJSON() // JSON
}
this.editor.customConfig.customUploadImg = function (files, insert) {
if (self.uploadConfig.method === 'custom') {
files.forEach(file => {
var fileUrl = URL.createObjectURL(file)
insert(fileUrl)
})
}
if (self.uploadConfig.method === 'base64') {
files.forEach(file => {
self.readBlobAsDataURL(file, function (dataurl) {
insert(dataurl)
})
})
}
if (self.uploadConfig.method === 'http') {
if (self.uploadConfig.callback) {
self.uploadConfig.callback(files, insert)
} else {
var formData = new FormData()
files.forEach(file => {
formData.append('file', file)
})
self.$axios.post(self.uploadConfig.url, formData).then(({ data }) => {
if (data.status === 'success') {
insert(data.url)
}
})
}
}
}
this.editor.create() //
this.editor.txt.text(this.value) //
this.$emit('oninit', this.editor)
}
},
beforeCreate () {
},
created () {
},
beforeMount () {
},
mounted () {
this.initEditor()
}
}
</script>
<style >
.w-e-toolbar{
flex-wrap:wrap;
}
</style>

View File

@ -0,0 +1,64 @@
<script>
import Tooltip from 'ant-design-vue/es/tooltip'
import { cutStrByFullLength, getStrFullLength } from '@/components/_util/util'
/*
const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined;
const TooltipOverlayStyle = {
overflowWrap: 'break-word',
wordWrap: 'break-word',
};
*/
export default {
name: 'Ellipsis',
components: {
Tooltip
},
props: {
prefixCls: {
type: String,
default: 'ant-pro-ellipsis'
},
tooltip: {
type: Boolean
},
length: {
type: Number,
required: true
},
lines: {
type: Number,
default: 1
},
fullWidthRecognition: {
type: Boolean,
default: false
}
},
methods: {
getStrDom (str, fullLength) {
return (
<span>{ cutStrByFullLength(str, this.length) + (fullLength > this.length ? '...' : '') }</span>
)
},
getTooltip (fullStr, fullLength) {
return (
<Tooltip>
<template slot="title">{ fullStr }</template>
{ this.getStrDom(fullStr, fullLength) }
</Tooltip>
)
}
},
render () {
const { tooltip, length } = this.$props
const str = this.$slots.default.map(vNode => vNode.text).join('')
const fullLength = getStrFullLength(str)
const strDom = tooltip && fullLength > length ? this.getTooltip(str, fullLength) : this.getStrDom(str, fullLength)
return (
strDom
)
}
}
</script>

View File

@ -0,0 +1,3 @@
import Ellipsis from './Ellipsis'
export default Ellipsis

View File

@ -0,0 +1,38 @@
# Ellipsis 文本自动省略号
文本过长自动处理省略号,支持按照文本长度和最大行数两种方式截取。
引用方式:
```javascript
import Ellipsis from '@/components/Ellipsis'
export default {
components: {
Ellipsis
}
}
```
## 代码演示 [demo](https://pro.loacg.com/test/home)
```html
<ellipsis :length="100" tooltip>
There were injuries alleged in three cases in 2015, and a
fourth incident in September, according to the safety recall report. After meeting with US regulators in October, the firm decided to issue a voluntary recall.
</ellipsis>
```
## API
参数 | 说明 | 类型 | 默认值
----|------|-----|------
tooltip | 移动到文本展示完整内容的提示 | boolean | -
length | 在按照长度截取下的文本最大字符数,超过则截取省略 | number | -

View File

@ -0,0 +1,130 @@
<template>
<div class="exception">
<div class="imgBlock">
<div class="imgEle" :style="{backgroundImage: `url(${config[type].img})`}">
</div>
</div>
<div class="content">
<h1>{{ config[type].title }}</h1>
<div class="desc">{{ config[type].desc }}</div>
<div class="actions">
<a-button type="primary" @click="handleToHome">返回首页</a-button>
</div>
</div>
</div>
</template>
<script>
import types from './type'
export default {
name: 'Exception',
props: {
type: {
type: String,
default: '404'
}
},
data () {
return {
config: types
}
},
methods: {
handleToHome () {
this.$router.push({ name: 'Console' })
}
}
}
</script>
<style lang="less">
@import "~ant-design-vue/lib/style/index";
.exception {
display: flex;
align-items: center;
height: 80%;
min-height: 500px;
.imgBlock {
flex: 0 0 62.5%;
width: 62.5%;
padding-right: 152px;
zoom: 1;
&::before,
&::after {
content: ' ';
display: table;
}
&::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
}
.imgEle {
float: right;
width: 100%;
max-width: 430px;
height: 360px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
}
.content {
flex: auto;
h1 {
margin-bottom: 24px;
color: #434e59;
font-weight: 600;
font-size: 72px;
line-height: 72px;
}
.desc {
margin-bottom: 16px;
color: @text-color-secondary;
font-size: 20px;
line-height: 28px;
}
.actions {
button:not(:last-child) {
margin-right: 8px;
}
}
}
}
@media screen and (max-width: @screen-xl) {
.exception {
.imgBlock {
padding-right: 88px;
}
}
}
@media screen and (max-width: @screen-sm) {
.exception {
display: block;
text-align: center;
.imgBlock {
margin: 0 auto 24px;
padding-right: 0;
}
}
}
@media screen and (max-width: @screen-xs) {
.exception {
.imgBlock {
margin-bottom: -24px;
overflow: hidden;
}
}
}
</style>

View File

@ -0,0 +1,2 @@
import ExceptionPage from './ExceptionPage.vue'
export default ExceptionPage

View File

@ -0,0 +1,19 @@
const types = {
403: {
img: 'https://gw.alipayobjects.com/zos/rmsportal/wZcnGqRDyhPOEYFcZDnb.svg',
title: '403',
desc: '抱歉,你无权访问该页面'
},
404: {
img: 'https://gw.alipayobjects.com/zos/rmsportal/KpnpchXsobRgLElEozzI.svg',
title: '404',
desc: '抱歉,你访问的页面不存在或仍在开发中'
},
500: {
img: 'https://gw.alipayobjects.com/zos/rmsportal/RVRUAYdCGeYNBWoKiIwB.svg',
title: '500',
desc: '抱歉,服务器出错了'
}
}
export default types

View File

@ -0,0 +1,30 @@
<template>
<div :class="prefixCls">
<div style="float: left">
<slot name="extra">{{ extra }}</slot>
</div>
<div style="float: right">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'FooterToolBar',
props: {
prefixCls: {
type: String,
default: 'ant-pro-footer-toolbar'
},
extra: {
type: [String, Object],
default: ''
}
}
}
</script>
<style lang="less" scoped>
</style>

View File

@ -0,0 +1,4 @@
import FooterToolBar from './FooterToolBar'
import './index.less'
export default FooterToolBar

View File

@ -0,0 +1,23 @@
@import "../index";
@footer-toolbar-prefix-cls: ~"@{ant-pro-prefix}-footer-toolbar";
.@{footer-toolbar-prefix-cls} {
position: fixed;
width: 100%;
bottom: 0;
right: 0;
height: 56px;
line-height: 56px;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03);
background: #fff;
border-top: 1px solid #e8e8e8;
padding: 0 24px;
z-index: 9;
&:after {
content: "";
display: block;
clear: both;
}
}

View File

@ -0,0 +1,48 @@
# FooterToolbar 底部工具栏
固定在底部的工具栏。
## 何时使用
固定在内容区域的底部,不随滚动条移动,常用于长页面的数据搜集和提交工作。
引用方式:
```javascript
import FooterToolBar from '@/components/FooterToolbar'
export default {
components: {
FooterToolBar
}
}
```
## 代码演示
```html
<footer-tool-bar>
<a-button type="primary" @click="validate" :loading="loading">提交</a-button>
</footer-tool-bar>
```
```html
<footer-tool-bar extra="扩展信息提示">
<a-button type="primary" @click="validate" :loading="loading">提交</a-button>
</footer-tool-bar>
```
## API
参数 | 说明 | 类型 | 默认值
----|------|-----|------
children (slot) | 工具栏内容,向右对齐 | - | -
extra | 额外信息,向左对齐 | String, Object | -

View File

@ -0,0 +1,46 @@
<template>
<div class="footer">
<div class="links">
</div>
<div class="copyright">
Copyright © 2020 <a target="_blank" href="https://www.xiaonuo.vip/">小诺开源技术</a> All rights reserved. Snowy 1.8
</div>
</div>
</template>
<script>
export default {
name: 'GlobalFooter',
data () {
return {}
}
}
</script>
<style lang="less" scoped>
.footer {
padding: 0 16px;
margin: 48px 0 24px;
text-align: center;
.links {
margin-bottom: 8px;
a {
color: rgba(0, 0, 0, 0.45);
&:hover {
color: rgba(0, 0, 0, 0.65);
}
&:not(:last-child) {
margin-right: 40px;
}
}
}
.copyright {
color: rgba(0, 0, 0, 0.45);
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,2 @@
import GlobalFooter from './GlobalFooter'
export default GlobalFooter

View File

@ -0,0 +1,165 @@
<template>
<transition name="showHeader">
<div v-if="visible" class="header-animat">
<a-layout-header
v-if="visible"
:class="[fixedHeader && 'ant-header-fixedHeader', sidebarOpened ? 'ant-header-side-opened' : 'ant-header-side-closed', ]"
:style="{ padding: '0', height: '55px' }">
<div v-if="mode === 'sidemenu'" class="header">
<a-menu
style="height: 55px; border-bottom: 0px;"
mode="horizontal"
:default-selected-keys="this.defApp"
>
<a-icon v-if="device==='mobile'" class="trigger" :type="collapsed ? 'menu-fold' : 'menu-unfold'" @click="toggle"/>
<a-icon v-else class="trigger" :type="collapsed ? 'menu-unfold' : 'menu-fold'" @click="toggle" style="padding-left: 20px; padding-right: 20px;"/>
<a-menu-item v-for="(item) in userInfo.apps" :key="item.code" style="top:0px; line-height: 55px; padding-left: 10px; padding-right: 10px" @click="switchApp(item.code)">
{{ item.name }}
</a-menu-item>
<user-menu></user-menu>
</a-menu>
</div>
<div v-else :class="['top-nav-header-index', theme]">
<div class="header-index-wide">
<div class="header-index-left">
<logo class="top-nav-header" :show-title="device !== 'mobile'"/>
<s-menu v-if="device !== 'mobile'" mode="horizontal" :menu="menus" :theme="theme" />
<a-icon v-else class="trigger" :type="collapsed ? 'menu-fold' : 'menu-unfold'" @click="toggle" />
</div>
<user-menu class="header-index-right"></user-menu>
</div>
</div>
</a-layout-header>
</div>
</transition>
</template>
<script>
import UserMenu from '../tools/UserMenu'
import SMenu from '../Menu/'
import Logo from '../tools/Logo'
import { mixin } from '@/utils/mixin'
import { mapActions, mapGetters } from 'vuex'
import { ALL_APPS_MENU } from '@/store/mutation-types'
import Vue from 'vue'
import { message } from 'ant-design-vue/es'
export default {
name: 'GlobalHeader',
components: {
UserMenu,
SMenu,
Logo
},
computed: {
...mapGetters(['userInfo'])
},
created () {
this.defApp.push(Vue.ls.get(ALL_APPS_MENU)[0].code)
},
mixins: [mixin],
props: {
mode: {
type: String,
// sidemenu, topmenu
default: 'sidemenu'
},
menus: {
type: Array,
required: true
},
theme: {
type: String,
required: false,
default: 'dark'
},
collapsed: {
type: Boolean,
required: false,
default: false
},
device: {
type: String,
required: false,
default: 'desktop'
}
},
data () {
return {
visible: true,
oldScrollTop: 0,
defApp: []
}
},
mounted () {
document.addEventListener('scroll', this.handleScroll, { passive: true })
},
methods: {
...mapActions(['MenuChange']),
/**
* 应用切换
*/
switchApp (appCode) {
this.defApp = []
const applicationData = this.userInfo.apps.filter(item => item.code === appCode)
const hideMessage = message.loading('正在切换应用!', 0)
this.MenuChange(applicationData[0]).then((res) => {
hideMessage()
// eslint-disable-next-line handle-callback-err
}).catch((err) => {
message.error('应用切换异常')
})
},
handleScroll () {
if (!this.autoHideHeader) {
return
}
const scrollTop = document.body.scrollTop + document.documentElement.scrollTop
if (!this.ticking) {
this.ticking = true
requestAnimationFrame(() => {
if (this.oldScrollTop > scrollTop) {
this.visible = true
} else if (scrollTop > 300 && this.visible) {
this.visible = false
} else if (scrollTop < 300 && !this.visible) {
this.visible = true
}
this.oldScrollTop = scrollTop
this.ticking = false
})
}
},
toggle () {
this.$emit('toggle')
}
},
beforeDestroy () {
document.body.removeEventListener('scroll', this.handleScroll, true)
}
}
</script>
<style lang="less">
@import '../index.less';
.header-animat{
position: relative;
z-index: @ant-global-header-zindex;
}
.showHeader-enter-active {
transition: all 0.25s ease;
}
.showHeader-leave-active {
transition: all 0.5s ease;
}
.showHeader-enter, .showHeader-leave-to {
opacity: 0;
}
</style>

View File

@ -0,0 +1,2 @@
import GlobalHeader from './GlobalHeader'
export default GlobalHeader

View File

@ -0,0 +1,86 @@
<template>
<div :class="prefixCls">
<a-tabs v-model="currentTab" @change="handleTabChange">
<a-tab-pane v-for="v in icons" :tab="v.title" :key="v.key">
<ul>
<li v-for="(icon, key) in v.icons" :key="`${v.key}-${key}`" :class="{ 'active': selectedIcon==icon }" @click="handleSelectedIcon(icon)" >
<a-icon :type="icon" :style="{ fontSize: '36px' }" />
</li>
</ul>
</a-tab-pane>
</a-tabs>
</div>
</template>
<script>
import icons from './icons'
export default {
name: 'IconSelect',
props: {
prefixCls: {
type: String,
default: 'ant-pro-icon-selector'
},
// eslint-disable-next-line
value: {
type: String
}
},
data () {
return {
selectedIcon: this.value || '',
currentTab: 'directional',
icons
}
},
watch: {
value (val) {
this.selectedIcon = val
this.autoSwitchTab()
}
},
created () {
if (this.value) {
this.autoSwitchTab()
}
},
methods: {
handleSelectedIcon (icon) {
this.selectedIcon = icon
this.$emit('change', icon)
},
handleTabChange (activeKey) {
this.currentTab = activeKey
},
autoSwitchTab () {
icons.some(item => item.icons.some(icon => icon === this.value) && (this.currentTab = item.key))
}
}
}
</script>
<style lang="less" scoped>
@import "../index.less";
ul{
list-style: none;
padding: 0;
overflow-y: scroll;
height: 250px;
li{
display: inline-block;
padding: @padding-sm;
margin: 3px 0;
border-radius: @border-radius-base;
&:hover, &.active{
// box-shadow: 0px 0px 5px 2px @primary-color;
cursor: pointer;
color: @white;
background-color: @primary-color;
}
}
}
</style>

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