This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
VUE_APP_BASE_URL=http://localhost:60161
|
VUE_APP_NODE_ENV=development
|
||||||
|
VUE_APP_BASE_URL=http://localhost:5566
|
||||||
VUE_APP_DEV_KEY=CJm9dFWx4IIGXHm^R1e@Y&mp*n8MQXfDKjDYP6ZVGqEAZQiC9LvX9jq8@uaMTT@T
|
VUE_APP_DEV_KEY=CJm9dFWx4IIGXHm^R1e@Y&mp*n8MQXfDKjDYP6ZVGqEAZQiC9LvX9jq8@uaMTT@T
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
|
VUE_APP_NODE_ENV=production
|
||||||
VUE_APP_BASE_URL=http://localhost:60161
|
VUE_APP_BASE_URL=http://localhost:60161
|
||||||
VUE_APP_DEV_KEY=%0!qF2BpcVorlNceu#kP4SVS1bPiMUqI71%rITatPIosNOCrot@mV7PJ&br$CVvF
|
VUE_APP_DEV_KEY=%0!qF2BpcVorlNceu#kP4SVS1bPiMUqI71%rITatPIosNOCrot@mV7PJ&br$CVvF
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@import '~ant-design-vue/dist/antd.less';
|
@import './extend.less';
|
||||||
@import './lib/visibility.less';
|
@import './lib/visibility.less';
|
||||||
@import './lib/container.less';
|
@import './lib/container.less';
|
||||||
@import './lib/align.less';
|
@import './lib/align.less';
|
||||||
@@ -19,4 +19,4 @@
|
|||||||
@import './lib/form.less';
|
@import './lib/form.less';
|
||||||
@import './lib/select.less';
|
@import './lib/select.less';
|
||||||
@import './theme/primary.less';
|
@import './theme/primary.less';
|
||||||
@import './lib/font-weight.less';
|
// @import './lib/font-weight.less';
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
@import '~ant-design-vue/dist/antd.less';
|
||||||
|
@padding-xxs: 4px;
|
||||||
|
@padding-xl: 32px;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
.ant-card {
|
.ant-card {
|
||||||
margin-bottom: @padding-md;
|
margin-bottom: @padding-md;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
@container-width: 1200px;
|
@container-width: 1200px;
|
||||||
.container {
|
.container {
|
||||||
width: @container-width;
|
width: @container-width;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
body {
|
body {
|
||||||
font-weight: 100;
|
font-weight: 100;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
.yo-form {
|
.yo-form {
|
||||||
|
&--fixed {
|
||||||
width: 660px;
|
width: 660px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
}
|
||||||
.yo-form-group {
|
.yo-form-group {
|
||||||
margin-bottom: @padding-md;
|
margin-bottom: @padding-md;
|
||||||
}
|
}
|
||||||
@@ -14,24 +16,123 @@
|
|||||||
|
|
||||||
border: @border-width-base @border-style-base @border-color-split;
|
border: @border-width-base @border-style-base @border-color-split;
|
||||||
background-color: @white;
|
background-color: @white;
|
||||||
|
|
||||||
|
@box-shadow-focused: 0 0 0 2px fade(@primary-color, 50%);
|
||||||
&::before,
|
&::before,
|
||||||
&::after {
|
&::after {
|
||||||
content: none;
|
content: none;
|
||||||
}
|
}
|
||||||
|
.ant-form-item-control {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
.ant-input,
|
.ant-input,
|
||||||
.ant-select-selection {
|
.ant-input-number,
|
||||||
border-color: transparent;
|
.ant-mentions,
|
||||||
background-color: #f1f3f4;
|
.ant-select-selection,
|
||||||
|
.ant-input-group-addon {
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
color: lighten(@black, 10%);
|
||||||
|
border: 0;
|
||||||
|
background-color: lighten(@black, 95%);
|
||||||
|
}
|
||||||
|
.ant-mentions {
|
||||||
|
textarea {
|
||||||
|
background-color: lighten(@black, 95%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.focus {
|
||||||
|
z-index: 2 !important;
|
||||||
|
|
||||||
|
box-shadow: @box-shadow-focused;
|
||||||
|
}
|
||||||
|
.ant-input {
|
||||||
|
&:focus {
|
||||||
|
.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-input-number-focused,
|
||||||
|
.ant-mentions-focused {
|
||||||
|
.focus();
|
||||||
}
|
}
|
||||||
.ant-select-focused,
|
.ant-select-focused,
|
||||||
.ant-select-open {
|
.ant-select-open {
|
||||||
|
z-index: 2;
|
||||||
.ant-select-selection {
|
.ant-select-selection {
|
||||||
box-shadow: 0 0 0 2px fade(@primary-color, 50%);
|
.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-input-group {
|
||||||
|
.ant-row-flex {
|
||||||
|
.ant-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-input-group-addon {
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form-item-label {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
|
||||||
|
margin-right: @padding-md;
|
||||||
|
|
||||||
|
text-align: left;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
>label {
|
||||||
|
color: lighten(@black, 10%);
|
||||||
|
&::after {
|
||||||
|
content: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ant-form-item-control-wrapper {
|
.ant-form-item-control-wrapper {
|
||||||
width: 50%;
|
flex: 0 0 61.8%;
|
||||||
|
|
||||||
|
width: 61.8%;
|
||||||
min-width: 220px;
|
min-width: 220px;
|
||||||
}
|
}
|
||||||
|
.ant-form-explain {
|
||||||
|
font-size: @font-size-base - 1px;
|
||||||
|
|
||||||
|
margin-top: @padding-xs;
|
||||||
|
margin-bottom: @padding-xxs;
|
||||||
|
margin-left: -61.8%;
|
||||||
|
|
||||||
|
transition: none;
|
||||||
|
animation: none;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
color: fade(darken(@primary-color, 38.2%), 61.8%);
|
||||||
|
}
|
||||||
|
// 上下布局
|
||||||
|
.yo-form--vertical {
|
||||||
|
display: block;
|
||||||
|
.ant-form-item-control {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
&-radio {
|
||||||
|
.ant-radio-wrapper {
|
||||||
|
line-height: @padding-lg;
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
margin-right: 0;
|
||||||
|
+.ant-radio-wrapper {
|
||||||
|
margin-top: @padding-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form-item-control-wrapper {
|
||||||
|
margin-left: @padding-lg;
|
||||||
|
}
|
||||||
|
.ant-form-explain {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
@margin-padding-position: ~'', ~'-top', ~'-left', ~'-right', ~'-bottom';
|
@margin-padding-position: ~'', ~'-top', ~'-left', ~'-right', ~'-bottom';
|
||||||
@margin-padding-position-name: ~'', ~'t', ~'l', ~'r', ~'b';
|
@margin-padding-position-name: ~'', ~'t', ~'l', ~'r', ~'b';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
.ant-select-arrow {
|
.ant-select-arrow {
|
||||||
.ant-select-arrow-icon {
|
.ant-select-arrow-icon {
|
||||||
transform: scaleY(.75);
|
transform: scaleY(.75);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) '~@/assets/style/extend.less';
|
||||||
.yo-query-bar {
|
.yo-query-bar {
|
||||||
margin-bottom: @padding-md;
|
margin-bottom: @padding-md;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@import (reference) '~ant-design-vue/dist/antd.less';
|
@import (reference) './extend.less';
|
||||||
@import (reference) './lib/container.less';
|
@import (reference) './lib/container.less';
|
||||||
|
|
||||||
.main(@nav-background: @layout-header-background,
|
.main(@nav-background: @layout-header-background,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { token } from '@/common/token'
|
|||||||
import status from './status'
|
import status from './status'
|
||||||
import app from '@/main'
|
import app from '@/main'
|
||||||
|
|
||||||
axios.defaults.baseURL = process.env.VUE_APP_BASE_URL + '/api'
|
axios.defaults.baseURL = '/api'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最终直接根据url名称调用接口方法
|
* 最终直接根据url名称调用接口方法
|
||||||
@@ -44,22 +44,39 @@ const api = {}
|
|||||||
|
|
||||||
for (let key in urls) {
|
for (let key in urls) {
|
||||||
|
|
||||||
|
const item = urls[key]
|
||||||
|
let url = '',
|
||||||
|
method = 'post'
|
||||||
|
if (item.constructor === String) {
|
||||||
|
url = item
|
||||||
|
} else if (item.constructor === Array) {
|
||||||
|
url = item[0]
|
||||||
|
if (item[1]) {
|
||||||
|
method = item[1].toLowerCase()
|
||||||
|
}
|
||||||
|
} else if (item.constructor === Object) {
|
||||||
|
url = item.url
|
||||||
|
if (item.method) {
|
||||||
|
method = item.method.toLowerCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
api[`${key}E`] = function (params = {}) {
|
api[`${key}E`] = function (params = {}) {
|
||||||
return initInstance().post(urls[key], params)
|
return initInstance()[method](url, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
api[key] = function (params = {}) {
|
api[key] = function (params = {}) {
|
||||||
return new Promise((reslove, reject) => {
|
return new Promise((reslove, reject) => {
|
||||||
api[`${key}E`](params)
|
api[`${key}E`](params)
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
if (data.status === status.OK) {
|
if (data.code === status.OK) {
|
||||||
reslove(data)
|
reslove(data)
|
||||||
} else {
|
} else {
|
||||||
reject(data)
|
reject(data)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
if (process.env.PROD) {
|
if (process.env.VUE_APP_NODE_ENV === 'development') {
|
||||||
alert('发生错误,请联系管理员')
|
alert('发生错误,请联系管理员')
|
||||||
} else {
|
} else {
|
||||||
console.warn(err, urls[key])
|
console.warn(err, urls[key])
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 接口的3种配置方式
|
||||||
|
* 1.string
|
||||||
|
* 如login: '/login'\
|
||||||
|
* 将会默认已POST方式请求接口/login
|
||||||
|
* 2.array
|
||||||
|
* 如login: ['/login', 'post']
|
||||||
|
* 数组[0]必填,为接口地址,[1]选填,为请求方式(不区分大小写),默认为POST
|
||||||
|
* 3.object
|
||||||
|
* 如login: { url: '/login', method: 'post' }
|
||||||
|
* [url]必填,为接口地址,[method]选填,为请求方式(不区分大小写),默认为POST
|
||||||
|
*/
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
login: '/gate/login',
|
login: '/login',
|
||||||
|
logout: ['/logout', 'get'],
|
||||||
|
getLoginUser: ['/getLoginUser', 'get'],
|
||||||
|
|
||||||
getMenu: '/menu/get',
|
getMenu: '/menu/get',
|
||||||
|
|
||||||
|
|||||||
@@ -1,46 +1,46 @@
|
|||||||
import { api } from '@/common/api';
|
import { api } from '@/common/api'
|
||||||
import { token } from '@/common/token';
|
import { token } from '@/common/token'
|
||||||
import { encryptByDES, decryptByDES } from '@/util/des';
|
import { encryptByDES, decryptByDES } from '@/util/des'
|
||||||
import app from '@/main';
|
import app from '@/main'
|
||||||
|
|
||||||
const GLOBAL_KEY = '__GLOBAL';
|
const GLOBAL_KEY = '__GLOBAL'
|
||||||
|
|
||||||
const setGlobal = (info) => {
|
const setGlobal = (info) => {
|
||||||
app.$set(app.global, 'info', info);
|
app.$set(app.global, 'info', info)
|
||||||
window.sessionStorage.setItem(GLOBAL_KEY, encryptByDES(JSON.stringify(info)));
|
window.sessionStorage.setItem(GLOBAL_KEY, encryptByDES(JSON.stringify(info)))
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeGlobal = () => {
|
const removeGlobal = () => {
|
||||||
app.$set(app.global, 'info', undefined);
|
app.$set(app.global, 'info', undefined)
|
||||||
window.sessionStorage.removeItem(GLOBAL_KEY);
|
window.sessionStorage.removeItem(GLOBAL_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getGlobal = () => {
|
const getGlobal = () => {
|
||||||
return JSON.parse(decryptByDES(window.sessionStorage.getItem(GLOBAL_KEY)));
|
return JSON.parse(decryptByDES(window.sessionStorage.getItem(GLOBAL_KEY)))
|
||||||
}
|
}
|
||||||
|
|
||||||
const doLogin = (args) => {
|
const doLogin = (args) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
api.login({
|
api.login(args).then(({ success, data, message }) => {
|
||||||
account: args.account,
|
if (success) {
|
||||||
password: args.password
|
token.value = data
|
||||||
}).then(({ result }) => {
|
app.$message.success('登录成功')
|
||||||
if (result.success) {
|
|
||||||
token.value = result.data.token;
|
|
||||||
app.$message.success('登录成功');
|
|
||||||
setGlobal(result.data.info)
|
|
||||||
if (app.$route.query.return) {
|
if (app.$route.query.return) {
|
||||||
const r = decryptByDES(app.$route.query.return);
|
const r = decryptByDES(app.$route.query.return)
|
||||||
app.$router.replace(r)
|
app.$router.replace(r)
|
||||||
} else {
|
} else {
|
||||||
app.$router.replace('/');
|
app.$router.replace('/')
|
||||||
}
|
}
|
||||||
resolve();
|
resolve()
|
||||||
} else {
|
} else {
|
||||||
app.$message.error(result.message);
|
app.$message.error(message)
|
||||||
reject();
|
reject()
|
||||||
}
|
}
|
||||||
});
|
}).catch(({ message }) => {
|
||||||
|
if (typeof message === 'object' && message[0]) {
|
||||||
|
app.$message.error(message[0].messages[0])
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,10 +48,10 @@ const doLogout = () => {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
api.logout().then(({ result: { success, message } }) => {
|
api.logout().then(({ result: { success, message } }) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
removeGlobal();
|
removeGlobal()
|
||||||
token.value = '';
|
token.value = ''
|
||||||
if (app.$route.path === '/') {
|
if (app.$route.path === '/') {
|
||||||
app.$router.replace('/login');
|
app.$router.replace('/login')
|
||||||
} else {
|
} else {
|
||||||
app.$router.replace({
|
app.$router.replace({
|
||||||
path: '/login',
|
path: '/login',
|
||||||
@@ -60,10 +60,10 @@ const doLogout = () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
resolve();
|
resolve()
|
||||||
} else {
|
} else {
|
||||||
app.$message.error(message);
|
app.$message.error(message)
|
||||||
reject();
|
reject()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -72,11 +72,11 @@ const doLogout = () => {
|
|||||||
const doCheck = () => {
|
const doCheck = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
api.checkLogin().then(({ result }) => {
|
api.checkLogin().then(({ result }) => {
|
||||||
setGlobal(result);
|
setGlobal(result)
|
||||||
resolve();
|
resolve()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
reject();
|
reject()
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,5 +85,6 @@ export {
|
|||||||
doLogout,
|
doLogout,
|
||||||
doCheck,
|
doCheck,
|
||||||
|
|
||||||
|
setGlobal,
|
||||||
getGlobal
|
getGlobal
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* auth: 允许的权限
|
||||||
|
* authExclude: 排除的权限
|
||||||
|
*
|
||||||
|
* auth的几种传值方式
|
||||||
|
* 1.String
|
||||||
|
* 例: auth="sysApp:page"
|
||||||
|
* 直接传入字符串,对单项权限进行验证
|
||||||
|
*
|
||||||
|
* 2.Array
|
||||||
|
* 2.1.单项权限
|
||||||
|
* 例: :auth="['sysApp:page']"
|
||||||
|
* 2.2.并且关系多项权限
|
||||||
|
* 例: :auth="['sysApp:page', 'sysApp:add']"
|
||||||
|
* 数组中传入多个字符串
|
||||||
|
* 此时验证的是同时拥有"sysApp:page"和"sysApp:add"两项权限才会渲染
|
||||||
|
* 2.3.或者关系多项权限
|
||||||
|
* 例: :auth="[['sysApp:page', 'sysApp:add'], ['sysApp:edit']]"
|
||||||
|
* 等同于: :auth="[['sysApp:page', 'sysApp:add'], 'sysApp:edit']"
|
||||||
|
* 二维数组结构,内部数组之间为并且关系
|
||||||
|
* 此时验证的是"sysApp:page"&"sysApp:add"||"sysApp:edit"
|
||||||
|
* 2.4.可直接传入布尔值
|
||||||
|
* 例: :auth="['sysApp:page', 1 === 1]"
|
||||||
|
* :auth="[['sysApp:page', 'sysApp:add'], 1 === 1]"
|
||||||
|
*
|
||||||
|
* 3.Json
|
||||||
|
* 如果觉得多项权限时每次都要写应用编号比较繁琐,可对Array形式进行简化
|
||||||
|
* 3.1.单项权限
|
||||||
|
* 例: :auth="{ sysApp: 'page' }"
|
||||||
|
* 3.2.并且关系多项权限
|
||||||
|
* 例: :auth="{ sysApp: ['page', 'add'] }"
|
||||||
|
* 3.3.或者关系多项权限
|
||||||
|
* 例: :auth="{ sysApp: [['page', 'add'], ['edit']]}"
|
||||||
|
* 等同于: :auth="{ sysApp: [['page', 'add'], 'edit']}"
|
||||||
|
* 3.4.可直接传入布尔值
|
||||||
|
* 例: :auth="{ sysApp: ['page', 1 === 1] }"
|
||||||
|
* :auth="{ sysApp: [['page', 'add'], 1 === 1] }"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
functional: true,
|
||||||
|
props: {
|
||||||
|
auth: {
|
||||||
|
default() {
|
||||||
|
return new Array()
|
||||||
|
},
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
authExclude: {
|
||||||
|
default() {
|
||||||
|
return new Array()
|
||||||
|
},
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render(h, context) {
|
||||||
|
const { props, scopedSlots } = context
|
||||||
|
const global = context.parent.$root.global
|
||||||
|
const auth = props.auth
|
||||||
|
const authExclude = props.authExclude
|
||||||
|
|
||||||
|
if (!global.info) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 超级管理员
|
||||||
|
*/
|
||||||
|
// if (global.info.adminType === 1) {
|
||||||
|
// return scopedSlots.default()
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (auth.length) {
|
||||||
|
for (let i = 0; i < auth.length; i++) {
|
||||||
|
if (global.info && (auth[i] & global.info.authority) === auth[i]) {
|
||||||
|
return scopedSlots.default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (authExclude.length) {
|
||||||
|
let flag = false
|
||||||
|
for (let i = 0; i < authExclude.length; i++) {
|
||||||
|
if (global.info && (authExclude[i] & global.info.authority) === authExclude[i]) {
|
||||||
|
flag = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flag) {
|
||||||
|
return scopedSlots.default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -44,6 +44,8 @@ Vue.prototype.$_ = _
|
|||||||
*/
|
*/
|
||||||
import Container from './components/container'
|
import Container from './components/container'
|
||||||
Vue.component('Container', Container)
|
Vue.component('Container', Container)
|
||||||
|
import Authorized from './components/authorized'
|
||||||
|
Vue.component('Auth', Authorized)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 引入主题样式
|
* 引入主题样式
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<container>
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col></a-col>
|
||||||
|
</a-row>
|
||||||
|
</container>
|
||||||
|
</template>
|
||||||
79
Api/Ewide.Core/Ewide.Core.Web.Src/src/pages/form/yo.vue
Normal file
79
Api/Ewide.Core/Ewide.Core.Web.Src/src/pages/form/yo.vue
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<container>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<a-form-model class="yo-form yo-form--fixed">
|
||||||
|
<h3>输入框</h3>
|
||||||
|
<Input />
|
||||||
|
<h3>数字输入框</h3>
|
||||||
|
<div class="yo-form-group">
|
||||||
|
<a-form-model-item label="数字输入框">
|
||||||
|
<span slot="help">
|
||||||
|
<a-tag color="pink">a-input-number</a-tag>可以输入和选择数字
|
||||||
|
</span>
|
||||||
|
<a-input-number autocomplete="off" placeholder="请输入数字" />
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
<h3>文本域</h3>
|
||||||
|
<div class="yo-form-group">
|
||||||
|
<a-form-model-item label="文本域">
|
||||||
|
<a-textarea autocomplete="off" placeholder="请输入文字" />
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
<h3>提及</h3>
|
||||||
|
<div class="yo-form-group">
|
||||||
|
<a-form-model-item label="提及">
|
||||||
|
<a-mentions placeholder="请输入'@'进行提及">
|
||||||
|
<a-mentions-option value="史莱姆">史莱姆</a-mentions-option>
|
||||||
|
<a-mentions-option value="哥布林">哥布林</a-mentions-option>
|
||||||
|
<a-mentions-option value="牛头人">牛头人</a-mentions-option>
|
||||||
|
</a-mentions>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
<h3>单选框</h3>
|
||||||
|
<div class="yo-form-group">
|
||||||
|
<a-form-model-item label="单选框">
|
||||||
|
<span slot="help">
|
||||||
|
<a-tag color="pink">a-radio-group > a-radio</a-tag>横排的单选框。请注意,因为控件区域宽度的限制,在这里无法使用单选框按钮
|
||||||
|
</span>
|
||||||
|
<a-radio-group>
|
||||||
|
<a-radio value="1">攻击</a-radio>
|
||||||
|
<a-radio value="2">防御</a-radio>
|
||||||
|
<a-radio value="3">剑技</a-radio>
|
||||||
|
<a-radio value="4">魔法</a-radio>
|
||||||
|
<a-radio value="5">回复</a-radio>
|
||||||
|
<a-radio value="6">虐杀</a-radio>
|
||||||
|
<a-radio value="7">踩在脚下</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item class="yo-form--vertical yo-form--vertical-radio" label="垂直单选框">
|
||||||
|
<span slot="help">
|
||||||
|
垂直单选框,需要在垂直布局控件的基础上,添加类
|
||||||
|
<a-tag color="pink">.yo-form--vertical-radio</a-tag>
|
||||||
|
</span>
|
||||||
|
<a-radio-group>
|
||||||
|
<a-radio value="1">攻击</a-radio>
|
||||||
|
<a-radio value="2">防御</a-radio>
|
||||||
|
<a-radio value="3">剑技</a-radio>
|
||||||
|
<a-radio value="4">魔法</a-radio>
|
||||||
|
<a-radio value="5">回复</a-radio>
|
||||||
|
<a-radio value="6">虐杀</a-radio>
|
||||||
|
<a-radio value="7">踩在脚下</a-radio>
|
||||||
|
<a-radio value="8">
|
||||||
|
<a-input />
|
||||||
|
</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
</a-form-model>
|
||||||
|
</container>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Input from './yo/Input';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Input,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<div class="yo-form-group">
|
||||||
|
<a-form-model-item label="输入框">
|
||||||
|
<a-input autocomplete="off" placeholder="请输入文字" />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="只读输入框">
|
||||||
|
<a-input autocomplete="off" placeholder="请输入文字" readonly />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="前缀和后缀">
|
||||||
|
<a-input addon-after="后缀" addon-before="前缀" autocomplete="off" placeholder="请输入文字" />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="输入框组">
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-input style="width: 40%" />
|
||||||
|
<a-input style="width: 60%" />
|
||||||
|
</a-input-group>
|
||||||
|
<a-input-group>
|
||||||
|
<a-row :gutter="8">
|
||||||
|
<a-col :span="10">
|
||||||
|
<a-input />
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="14">
|
||||||
|
<a-input />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-input-group>
|
||||||
|
<a-input-group>
|
||||||
|
<a-row type="flex">
|
||||||
|
<a-col flex="120px">
|
||||||
|
<a-select default-value="Zhejiang">
|
||||||
|
<a-select-option value="Zhejiang">Zhejiang</a-select-option>
|
||||||
|
<a-select-option value="Jiangsu">Jiangsu</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-col>
|
||||||
|
<a-col flex="auto">
|
||||||
|
<a-input default-value="Xihu District, Hangzhou" />
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-input-group>
|
||||||
|
<a-input-group compact>
|
||||||
|
<a-select default-value="1">
|
||||||
|
<a-select-option value="1">Between</a-select-option>
|
||||||
|
<a-select-option value="2">Except</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
<a-input placeholder="Minimum" style=" width: 100px; text-align: center" />
|
||||||
|
<a-input
|
||||||
|
disabled
|
||||||
|
placeholder="~"
|
||||||
|
style=" width: 30px; border-left: 0; pointer-events: none; backgroundColor: transparent"
|
||||||
|
/>
|
||||||
|
<a-input placeholder="Maximum" style=" width: 100px; text-align: center; border-left: 0" />
|
||||||
|
</a-input-group>
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item class="yo-form--vertical" label="上下布局">
|
||||||
|
<span slot="help">
|
||||||
|
上下布局,请在
|
||||||
|
<a-tag color="pink">a-form-model-item</a-tag>上添加类
|
||||||
|
<a-tag color="pink">.yo-form--vertical</a-tag>
|
||||||
|
</span>
|
||||||
|
<a-input autocomplete="off" placeholder="请输入文字" />
|
||||||
|
</a-form-model-item>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
143
Api/Ewide.Core/Ewide.Core.Web.Src/src/pages/system/app/index.vue
Normal file
143
Api/Ewide.Core/Ewide.Core.Web.Src/src/pages/system/app/index.vue
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<template>
|
||||||
|
<container>
|
||||||
|
<br />
|
||||||
|
<a-card :bordered="false">
|
||||||
|
<Auth :auth="{ sysApp: ['page'] }">
|
||||||
|
<div class="yo-query-bar">
|
||||||
|
<a-form-model :model="query" layout="inline">
|
||||||
|
<a-form-model-item label="应用名称">
|
||||||
|
<a-input placeholder="请输入应用名称" v-model="query.name" />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item label="唯一编码">
|
||||||
|
<a-input placeholder="请输入唯一编码" v-model="query.code" />
|
||||||
|
</a-form-model-item>
|
||||||
|
<a-form-model-item>
|
||||||
|
<a-button html-type="submit" type="primary">查询</a-button>
|
||||||
|
</a-form-model-item>
|
||||||
|
</a-form-model>
|
||||||
|
</div>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
|
<a-table
|
||||||
|
:bordered="true"
|
||||||
|
:columns="columns"
|
||||||
|
:data-source="data"
|
||||||
|
:pagination="{ pageSize: 20}"
|
||||||
|
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
|
||||||
|
>
|
||||||
|
<div class="yo-action-bar" slot="title">
|
||||||
|
<div class="yo-action-bar--actions">
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
<a-button :disabled="true">Button</a-button>
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
<a-button-group>
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
<a-button>Button</a-button>
|
||||||
|
</a-button-group>
|
||||||
|
<a-dropdown>
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="1">1st item</a-menu-item>
|
||||||
|
<a-menu-item key="2">2nd item</a-menu-item>
|
||||||
|
<a-menu-item key="3">3rd item</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
<a-button>
|
||||||
|
Actions
|
||||||
|
<a-icon type="down" />
|
||||||
|
</a-button>
|
||||||
|
</a-dropdown>
|
||||||
|
<a-dropdown-button>
|
||||||
|
Dropdown
|
||||||
|
<a-menu slot="overlay">
|
||||||
|
<a-menu-item key="1">
|
||||||
|
<a-icon type="user" />1st menu item
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="2">
|
||||||
|
<a-icon type="user" />2nd menu item
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-item key="3">
|
||||||
|
<a-icon type="user" />3rd item
|
||||||
|
</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
</a-dropdown-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
<br />
|
||||||
|
</container>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
const _data = [
|
||||||
|
{
|
||||||
|
area: '海曙区',
|
||||||
|
title: '曙光电影院地块',
|
||||||
|
count: 13,
|
||||||
|
date: '2021-01-01',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
area: '江北区',
|
||||||
|
title: '大庆新村地块旧城区改建项目',
|
||||||
|
count: 322,
|
||||||
|
date: '2021-01-01',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
area: '宁海县',
|
||||||
|
title: '桥头胡街道旧城区改造华驰文教地块',
|
||||||
|
count: 1,
|
||||||
|
date: '2021-01-01',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
area: '慈溪市',
|
||||||
|
title: '七二三南延道路工程',
|
||||||
|
count: 1,
|
||||||
|
date: '2021-01-01',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
area: '北仑区',
|
||||||
|
title: '原粮食局宿舍楼1号、2号楼(太河路北延工程)',
|
||||||
|
count: 32,
|
||||||
|
date: '2021-01-01',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const data = Object.assign([], _data, _data, _data);
|
||||||
|
data.map((p, i) => (p.key = 'abcdefghijklmnopqrstuvwxyz'[i]));
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
query: {
|
||||||
|
area: '宁波市',
|
||||||
|
year: '2021',
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '区域',
|
||||||
|
dataIndex: 'area',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '项目名称',
|
||||||
|
dataIndex: 'title',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '户数',
|
||||||
|
dataIndex: 'count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'date',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
data,
|
||||||
|
selectedRowKeys: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSelectChange(selectedRowKeys) {
|
||||||
|
this.selectedRowKeys = selectedRowKeys;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-form-model :model="formInline" @submit="handleSubmit" @submit.native.prevent layout="inline">
|
<a-form-model :model="form" @submit="handleSubmit" @submit.native.prevent layout="inline">
|
||||||
<a-form-model-item>
|
<a-form-model-item>
|
||||||
<a-input placeholder="Username" v-model="formInline.user">
|
<a-input placeholder="Username" v-model="form.user">
|
||||||
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="user" />
|
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="user" />
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item>
|
<a-form-model-item>
|
||||||
<a-input placeholder="Password" type="password" v-model="formInline.password">
|
<a-input placeholder="Password" type="password" v-model="form.password">
|
||||||
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="lock" />
|
<a-icon slot="prefix" style="color:rgba(0,0,0,.25)" type="lock" />
|
||||||
</a-input>
|
</a-input>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
<a-form-model-item>
|
<a-form-model-item>
|
||||||
<a-button
|
<a-button
|
||||||
:disabled="formInline.user === '' || formInline.password === ''"
|
:disabled="form.user === '' || form.password === ''"
|
||||||
|
:loading="loading"
|
||||||
html-type="submit"
|
html-type="submit"
|
||||||
type="primary"
|
type="primary"
|
||||||
>Log in</a-button>
|
>Log in</a-button>
|
||||||
@@ -25,7 +26,8 @@ import { doLogin } from '@/common/login';
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
formInline: {
|
loading: false,
|
||||||
|
form: {
|
||||||
user: '',
|
user: '',
|
||||||
password: '',
|
password: '',
|
||||||
},
|
},
|
||||||
@@ -33,9 +35,12 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSubmit(e) {
|
handleSubmit(e) {
|
||||||
|
this.loading = true;
|
||||||
doLogin({
|
doLogin({
|
||||||
account: this.formInline.user,
|
account: this.form.user,
|
||||||
password: this.formInline.password,
|
password: this.form.password,
|
||||||
|
}).then(() => {
|
||||||
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,13 @@
|
|||||||
{{ pane.title }}
|
{{ pane.title }}
|
||||||
</div>
|
</div>
|
||||||
<a-menu slot="overlay">
|
<a-menu slot="overlay">
|
||||||
|
<template v-if="mode === 'development'">
|
||||||
|
<a-menu-item @click="onCopyComponent(pane)" key="-1">
|
||||||
|
复制组件地址
|
||||||
|
<a-tag color="red">dev</a-tag>
|
||||||
|
</a-menu-item>
|
||||||
|
<a-menu-divider />
|
||||||
|
</template>
|
||||||
<a-menu-item @click="onLoadContentWindow(pane.key)" key="0">重新加载</a-menu-item>
|
<a-menu-item @click="onLoadContentWindow(pane.key)" key="0">重新加载</a-menu-item>
|
||||||
<a-menu-divider />
|
<a-menu-divider />
|
||||||
<a-menu-item :disabled="!pane.closable" @click="$emit('close', pane.key);" key="1">关闭</a-menu-item>
|
<a-menu-item :disabled="!pane.closable" @click="$emit('close', pane.key);" key="1">关闭</a-menu-item>
|
||||||
@@ -42,6 +49,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
mode: process.env.VUE_APP_NODE_ENV,
|
||||||
actived: '',
|
actived: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -79,6 +87,22 @@ export default {
|
|||||||
onChange(activeKey) {
|
onChange(activeKey) {
|
||||||
this.$emit('change', activeKey);
|
this.$emit('change', activeKey);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onCopyComponent(pane) {
|
||||||
|
try {
|
||||||
|
const copy = document.createElement('textarea');
|
||||||
|
document.body.append(copy);
|
||||||
|
copy.value = `/pages${pane.path}`;
|
||||||
|
copy.select();
|
||||||
|
setTimeout(() => {
|
||||||
|
document.execCommand('copy');
|
||||||
|
copy.remove();
|
||||||
|
this.$message.success('已复制到剪切板');
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
this.$message.error('复制错误');
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<container v-else-if="$root.global.settings.layout === 'top-nav'">
|
<container v-else-if="$root.global.settings.layout === 'top-nav'">
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<Logo />
|
<Logo />
|
||||||
<Sider @open="(nav) => $emit('open', nav)" />
|
<Sider :nav="nav" @open="(nav) => $emit('open', nav)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<a-input-search placeholder="请输入检索关键字" />
|
<a-input-search placeholder="请输入检索关键字" />
|
||||||
@@ -57,5 +57,16 @@ export default {
|
|||||||
Logo,
|
Logo,
|
||||||
Sider,
|
Sider,
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
nav: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
modules: [],
|
||||||
|
menus: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
<template>
|
|
||||||
<section>
|
|
||||||
<a-layout-sider
|
|
||||||
v-if="$root.global.settings.layout === 'left-menu' || $root.global.settings.layout === 'right-menu'"
|
|
||||||
v-model="$root.global.settings.siderCollapsed"
|
|
||||||
width="200"
|
|
||||||
>
|
|
||||||
<Logo />
|
|
||||||
<swiper :options="siderSwiperOptions" :style="{ height: '100%' }" ref="sider-swiper">
|
|
||||||
<swiper-slide :style="{ height: 'auto' }">
|
|
||||||
<a-menu
|
|
||||||
:selectable="false"
|
|
||||||
:style="{ height: '100%', borderRight: 0 }"
|
|
||||||
:theme="$root.global.settings.navTheme"
|
|
||||||
@openChange="onMenuOpenChange"
|
|
||||||
mode="inline"
|
|
||||||
>
|
|
||||||
<template v-for="c1 in menu">
|
|
||||||
<a-sub-menu :key="c1.id" v-if="c1.children && c1.children.length">
|
|
||||||
<span slot="title">
|
|
||||||
<a-icon :type="c1.icon" v-if="c1.icon" />
|
|
||||||
<span>{{ c1.name }}</span>
|
|
||||||
</span>
|
|
||||||
<template v-for="c2 in c1.children">
|
|
||||||
<a-menu-item :key="c2.id" @click="onOpenContentWindow(c2)">
|
|
||||||
<a-icon :type="c2.icon" v-if="c2.icon" />
|
|
||||||
<span>{{ c2.name }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-sub-menu>
|
|
||||||
<a-menu-item :key="c1.id" @click="onOpenContentWindow(c1)" v-else>
|
|
||||||
<a-icon :type="c1.icon" v-if="c1.icon" />
|
|
||||||
<span>{{ c1.name }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-menu>
|
|
||||||
</swiper-slide>
|
|
||||||
<div class="swiper-scrollbar"></div>
|
|
||||||
</swiper>
|
|
||||||
</a-layout-sider>
|
|
||||||
<template v-else-if="$root.global.settings.layout === 'top-nav'">
|
|
||||||
<a-menu
|
|
||||||
:selectable="false"
|
|
||||||
:style="{ borderBottom: 0 }"
|
|
||||||
:theme="$root.global.settings.navTheme"
|
|
||||||
@openChange="onMenuOpenChange"
|
|
||||||
mode="horizontal"
|
|
||||||
>
|
|
||||||
<template v-for="c1 in menu">
|
|
||||||
<a-sub-menu :key="c1.id" v-if="c1.children && c1.children.length">
|
|
||||||
<span slot="title">
|
|
||||||
<a-icon :type="c1.icon" v-if="c1.icon" />
|
|
||||||
<span>{{ c1.name }}</span>
|
|
||||||
</span>
|
|
||||||
<template v-for="c2 in c1.children">
|
|
||||||
<a-menu-item :key="c2.id" @click="onOpenContentWindow(c2)">
|
|
||||||
<a-icon :type="c2.icon" v-if="c2.icon" />
|
|
||||||
<span>{{ c2.name }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-sub-menu>
|
|
||||||
<a-menu-item :key="c1.id" @click="onOpenContentWindow(c1)" v-else>
|
|
||||||
<a-icon :type="c1.icon" v-if="c1.icon" />
|
|
||||||
<span>{{ c1.name }}</span>
|
|
||||||
</a-menu-item>
|
|
||||||
</template>
|
|
||||||
</a-menu>
|
|
||||||
</template>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import Logo from './logo';
|
|
||||||
|
|
||||||
const menu = [
|
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
name: '列表',
|
|
||||||
icon: 'unordered-list',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: '1-1',
|
|
||||||
name: '表格及查询',
|
|
||||||
icon: 'table',
|
|
||||||
component: '/list/query',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
name: '表单',
|
|
||||||
icon: 'form',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: '2-1',
|
|
||||||
name: '一般表单',
|
|
||||||
component: '/form/normal',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2-2',
|
|
||||||
name: 'yo表单',
|
|
||||||
component: '/form/yo',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '100',
|
|
||||||
name: '文档',
|
|
||||||
icon: 'snippets',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
id: '100-1',
|
|
||||||
name: '使用文档',
|
|
||||||
icon: 'code',
|
|
||||||
component: '/doc/use',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
Logo,
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
siderSwiperOptions: {
|
|
||||||
direction: 'vertical',
|
|
||||||
slidesPerView: 'auto',
|
|
||||||
freeMode: true,
|
|
||||||
scrollbar: {
|
|
||||||
el: '.swiper-scrollbar',
|
|
||||||
},
|
|
||||||
mousewheel: true,
|
|
||||||
},
|
|
||||||
menu,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
swiper() {
|
|
||||||
return this.$refs['sider-swiper'].$swiper;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
if (this.$root.global.settings.layout === 'left-menu' || this.$root.global.settings.layout === 'right-menu') {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.swiper.update();
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// this.$api.getMenu().then(({ result: { data } }) => {
|
|
||||||
// this.menu = data;
|
|
||||||
// });
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onMenuOpenChange() {
|
|
||||||
this.windowTriggerResize();
|
|
||||||
},
|
|
||||||
|
|
||||||
windowTriggerResize() {
|
|
||||||
let e = new Event('resize');
|
|
||||||
window.dispatchEvent(e);
|
|
||||||
},
|
|
||||||
|
|
||||||
onOpenContentWindow(nav) {
|
|
||||||
this.$emit('open', {
|
|
||||||
key: nav.id,
|
|
||||||
title: nav.name,
|
|
||||||
icon: nav.icon,
|
|
||||||
path: nav.component,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<section>
|
||||||
|
<a-layout-sider
|
||||||
|
v-if="$root.global.settings.layout === 'left-menu' || $root.global.settings.layout === 'right-menu'"
|
||||||
|
v-model="$root.global.settings.siderCollapsed"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
|
<Logo />
|
||||||
|
<swiper :options="siderSwiperOptions" :style="{ height: '100%' }" ref="sider-swiper">
|
||||||
|
<swiper-slide :style="{ height: 'auto' }">
|
||||||
|
<Menu
|
||||||
|
:menu-style="{ height: '100%', borderRight: 0 }"
|
||||||
|
:nav="nav"
|
||||||
|
@openChange="onMenuOpenChange"
|
||||||
|
mode="inline"
|
||||||
|
/>
|
||||||
|
</swiper-slide>
|
||||||
|
<div class="swiper-scrollbar"></div>
|
||||||
|
</swiper>
|
||||||
|
</a-layout-sider>
|
||||||
|
<template v-else-if="$root.global.settings.layout === 'top-nav'">
|
||||||
|
<Menu
|
||||||
|
:menu-style="{ borderBottom: 0 }"
|
||||||
|
:nav="nav"
|
||||||
|
@openChange="onMenuOpenChange"
|
||||||
|
mode="horizontal"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Logo from '../logo';
|
||||||
|
import Menu from './menu';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Logo,
|
||||||
|
Menu,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
nav: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
modules: [],
|
||||||
|
menus: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
siderSwiperOptions: {
|
||||||
|
direction: 'vertical',
|
||||||
|
slidesPerView: 'auto',
|
||||||
|
freeMode: true,
|
||||||
|
scrollbar: {
|
||||||
|
el: '.swiper-scrollbar',
|
||||||
|
},
|
||||||
|
mousewheel: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
swiper() {
|
||||||
|
return this.$refs['sider-swiper'].$swiper;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if (this.$root.global.settings.layout === 'left-menu' || this.$root.global.settings.layout === 'right-menu') {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.swiper.update();
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onMenuOpenChange() {
|
||||||
|
this.windowTriggerResize();
|
||||||
|
},
|
||||||
|
|
||||||
|
windowTriggerResize() {
|
||||||
|
let e = new Event('resize');
|
||||||
|
window.dispatchEvent(e);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<template>
|
||||||
|
<a-menu
|
||||||
|
:mode="mode"
|
||||||
|
:selectable="false"
|
||||||
|
:style="menuStyle"
|
||||||
|
:theme="$root.global.settings.navTheme"
|
||||||
|
@openChange="onMenuOpenChange"
|
||||||
|
>
|
||||||
|
<template v-for="c1 in menu">
|
||||||
|
<a-sub-menu :key="c1.id" v-if="c1.children && c1.children.length">
|
||||||
|
<span slot="title">
|
||||||
|
<a-icon :type="c1.meta.icon" v-if="c1.meta.icon" />
|
||||||
|
<span>{{ c1.meta.title }}</span>
|
||||||
|
</span>
|
||||||
|
<template v-for="c2 in c1.children">
|
||||||
|
<a-menu-item :key="c2.id" @click="onOpenContentWindow(c2)">
|
||||||
|
<a-icon :type="c2.meta.icon" v-if="c2.meta.icon" />
|
||||||
|
<span>{{ c2.meta.title }}</span>
|
||||||
|
</a-menu-item>
|
||||||
|
</template>
|
||||||
|
</a-sub-menu>
|
||||||
|
<a-menu-item :key="c1.id" @click="onOpenContentWindow(c1)" v-else>
|
||||||
|
<a-icon :type="c1.meta.icon" v-if="c1.meta.icon" />
|
||||||
|
<span>{{ c1.meta.title }}</span>
|
||||||
|
</a-menu-item>
|
||||||
|
</template>
|
||||||
|
</a-menu>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
nav: {
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
modules: [],
|
||||||
|
menus: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
menuStyle: {
|
||||||
|
default() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
type: Object || String,
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
default: 'inline',
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
menu: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.serializeMenu();
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
nav: {
|
||||||
|
deep: true,
|
||||||
|
handler() {
|
||||||
|
this.serializeMenu();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
serializeMenu() {
|
||||||
|
const menu = this.$_.cloneDeep(this.nav.menus);
|
||||||
|
const children = this.$_.groupBy(menu, 'pid');
|
||||||
|
this.menu = menu
|
||||||
|
.filter((p) => !p.pid)
|
||||||
|
.map((p) => {
|
||||||
|
return {
|
||||||
|
...p,
|
||||||
|
children: children[p.id],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onMenuOpenChange() {
|
||||||
|
this.$emit('openChange');
|
||||||
|
},
|
||||||
|
|
||||||
|
onOpenContentWindow(menu) {
|
||||||
|
this.openContentWindow({
|
||||||
|
key: menu.id,
|
||||||
|
title: menu.meta.title,
|
||||||
|
icon: menu.meta.icon,
|
||||||
|
path: menu.component,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -7,9 +7,14 @@
|
|||||||
[`yo-layout--${$root.global.settings.layout}`]: true,
|
[`yo-layout--${$root.global.settings.layout}`]: true,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Sider @open="onOpenContentWindow" v-if="$root.global.settings.layout === 'left-menu'" />
|
<Sider
|
||||||
|
:nav="nav"
|
||||||
|
@open="onOpenContentWindow"
|
||||||
|
v-if="$root.global.settings.layout === 'left-menu'"
|
||||||
|
/>
|
||||||
<a-layout>
|
<a-layout>
|
||||||
<Header
|
<Header
|
||||||
|
:nav="nav"
|
||||||
@open="onOpenContentWindow"
|
@open="onOpenContentWindow"
|
||||||
@reload="onReloadContentWindow"
|
@reload="onReloadContentWindow"
|
||||||
@setting="setting.visible = true"
|
@setting="setting.visible = true"
|
||||||
@@ -26,7 +31,11 @@
|
|||||||
/>
|
/>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
<Sider @open="onOpenContentWindow" v-if="$root.global.settings.layout === 'right-menu'" />
|
<Sider
|
||||||
|
:nav="nav"
|
||||||
|
@open="onOpenContentWindow"
|
||||||
|
v-if="$root.global.settings.layout === 'right-menu'"
|
||||||
|
/>
|
||||||
</a-layout>
|
</a-layout>
|
||||||
<Setting :visible="setting.visible" @close="setting.visible = false" />
|
<Setting :visible="setting.visible" @close="setting.visible = false" />
|
||||||
</section>
|
</section>
|
||||||
@@ -41,11 +50,14 @@ import 'moment/locale/zh-cn';
|
|||||||
moment.locale('zh-cn');
|
moment.locale('zh-cn');
|
||||||
|
|
||||||
import Header from './_layout/header';
|
import Header from './_layout/header';
|
||||||
import Sider from './_layout/sider';
|
import Sider from './_layout/sider/index';
|
||||||
import Content from './_layout/content';
|
import Content from './_layout/content';
|
||||||
|
|
||||||
import Setting from './setting';
|
import Setting from './setting';
|
||||||
|
|
||||||
|
import { api } from '@/common/api';
|
||||||
|
import { setGlobal } from '@/common/login';
|
||||||
|
|
||||||
const getNewID = () => {
|
const getNewID = () => {
|
||||||
return Math.random().toString(16).slice(2);
|
return Math.random().toString(16).slice(2);
|
||||||
};
|
};
|
||||||
@@ -67,9 +79,28 @@ export default {
|
|||||||
setting: {
|
setting: {
|
||||||
visible: false,
|
visible: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
nav: {
|
||||||
|
loaded: false,
|
||||||
|
modules: [],
|
||||||
|
menus: [],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
api.getLoginUser().then(({ data }) => {
|
||||||
|
const info = { ...data };
|
||||||
|
delete info.apps;
|
||||||
|
delete info.menus;
|
||||||
|
setGlobal(info);
|
||||||
|
|
||||||
|
this.nav.modules = data.apps;
|
||||||
|
this.nav.menus = data.menus;
|
||||||
|
this.nav.loaded = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
Vue.prototype.openContentWindow = this.onOpenContentWindow;
|
Vue.prototype.openContentWindow = this.onOpenContentWindow;
|
||||||
Vue.prototype.closeContentWindow = this.onCloseContentWindow;
|
Vue.prototype.closeContentWindow = this.onCloseContentWindow;
|
||||||
@@ -98,7 +129,7 @@ export default {
|
|||||||
closable,
|
closable,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (settings.path && settings.path.startsWith('/')) {
|
if (settings.path) {
|
||||||
const key = settings.key || getNewID();
|
const key = settings.key || getNewID();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,6 +141,8 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const path = settings.path.startsWith('/') ? settings.path : `/${settings.path}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向标签页队列中添加一个新的标签页
|
* 向标签页队列中添加一个新的标签页
|
||||||
*/
|
*/
|
||||||
@@ -119,7 +152,7 @@ export default {
|
|||||||
icon: settings.icon,
|
icon: settings.icon,
|
||||||
title: settings.title || '新建窗口',
|
title: settings.title || '新建窗口',
|
||||||
component: null,
|
component: null,
|
||||||
path: settings.path,
|
path,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,14 @@ module.exports = {
|
|||||||
devServer: {
|
devServer: {
|
||||||
open: true,
|
open: true,
|
||||||
port: 6588,
|
port: 6588,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: process.env.VUE_APP_BASE_URL,
|
||||||
|
pathRewrite: {
|
||||||
|
'^/api': ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
lintOnSave: false,
|
lintOnSave: false,
|
||||||
css: {
|
css: {
|
||||||
|
|||||||
Reference in New Issue
Block a user