This commit is contained in:
parent
e121ad5143
commit
cb187d0b74
2
.env
2
.env
|
|
@ -7,4 +7,4 @@ VUE_APP_USER_KEY=admin.user
|
|||
VUE_APP_SETTING_KEY=admin.setting
|
||||
VUE_APP_TBAS_KEY=admin.tabs
|
||||
VUE_APP_TBAS_TITLES_KEY=admin.tabs.titles
|
||||
VUE_APP_API_BASE_URL=http://api.iczer.com
|
||||
VUE_APP_API_BASE_URL=http://192.168.31.90:19000
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
VUE_APP_API_BASE_URL=http://dev.iczer.com
|
||||
VUE_APP_API_BASE_URL=http://192.168.31.90:19000
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
|
||||
stages: # List of stages for jobs, and their order of execution
|
||||
- build
|
||||
- deploy-dev
|
||||
# - deploy-test
|
||||
- deploy-prod
|
||||
|
||||
|
||||
|
||||
|
||||
variables:
|
||||
REGISTRY_GITLAB: registry.gitlab.com/seasoul/mes-antd-admin
|
||||
BUILD_NUMBER: ${CI_COMMIT_SHORT_SHA}-${CI_PIPELINE_ID}
|
||||
KUBE_CONFIG: /etc/deploy/config
|
||||
cache:
|
||||
paths:
|
||||
- ./mod_cache/
|
||||
|
||||
|
||||
build-rpc-job: # This job runs in the build stage, which runs first.
|
||||
stage: build
|
||||
image: tico/docker:latest
|
||||
tags:
|
||||
- k8s-runner
|
||||
variables:
|
||||
NAME: antd-admin
|
||||
PORT: 8080
|
||||
APP_NAME: antd-admin
|
||||
script:
|
||||
- ls
|
||||
- mkdir -p ./.ssh
|
||||
- mv $SSH_PRIVATE_KEY ./.ssh/id_rsa
|
||||
- chmod 600 ./.ssh/id_rsa
|
||||
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
|
||||
# 如果是登录私有仓库则需要更换如下代码:
|
||||
- docker build -f Dockerfile -t $APP_NAME:v${BUILD_NUMBER} . --network=host #编译成镜像
|
||||
- docker tag $APP_NAME:v${BUILD_NUMBER} $REGISTRY_GITLAB/$APP_NAME:v${BUILD_NUMBER} #将镜像加上tag
|
||||
- docker push $REGISTRY_GITLAB/$APP_NAME:v${BUILD_NUMBER} #提交到镜像仓库
|
||||
- docker tag $APP_NAME:v${BUILD_NUMBER} $REGISTRY_GITLAB/$APP_NAME:latest #将镜像加上tag
|
||||
- docker push $REGISTRY_GITLAB/$APP_NAME:latest #提交到镜像仓库
|
||||
after_script:
|
||||
- docker rmi $APP_NAME:v${BUILD_NUMBER} #删除镜像
|
||||
- docker rmi $REGISTRY_GITLAB/$APP_NAME:v${BUILD_NUMBER} #删除镜像
|
||||
- docker images|grep none|awk '{print $3}'|xargs docker rmi # 清理无tag的镜像
|
||||
# - docker rm $(docker ps --all -q -f status=exited) # 清理容器
|
||||
|
||||
deploy-rpc-dev-job:
|
||||
stage: deploy-dev
|
||||
image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/kubectl:1.16.6
|
||||
tags:
|
||||
- k8s-runner
|
||||
script:
|
||||
- mkdir -p /etc/deploy
|
||||
- echo $kube_config |base64 -d > $KUBE_CONFIG
|
||||
- kubectl get nodes
|
||||
- kubectl apply -f deploy/mes-antd-admin-dev.yaml # 部署测试环境
|
||||
|
||||
# deploy-rpc-test-job:
|
||||
# stage: deploy-dev
|
||||
# image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/kubectl:1.16.6
|
||||
# tags:
|
||||
# - k8s-runner
|
||||
# script:
|
||||
# - mkdir -p /etc/deploy
|
||||
# - mv $kube_config $KUBE_CONFIG
|
||||
# - kubectl get nodes
|
||||
# - kubectl apply -f deploy/mes-antd-admin-test.yaml # 部署灰度测试环境
|
||||
|
||||
deploy-rpc-prod-job:
|
||||
stage: deploy-prod
|
||||
image: registry.cn-hangzhou.aliyuncs.com/haoshuwei24/kubectl:1.16.6
|
||||
tags:
|
||||
- k8s-runner
|
||||
script:
|
||||
- mkdir -p /etc/deploy
|
||||
- echo $kube_config |base64 -d > $KUBE_CONFIG
|
||||
- kubectl get nodes
|
||||
- kubectl apply -f deploy/mes-antd-admin-prod.yaml # 部署正式环境
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
# build stage
|
||||
FROM node:lts-alpine as build-stage
|
||||
ENV API_SERVER_HOST=http://zxx4.f3322.net:30880/api/middle/
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN yarn install && yarn run build
|
||||
|
||||
# production stage
|
||||
FROM nginx:stable-alpine as production-stage
|
||||
COPY nginx/nginx.conf /etc/nginx/nginx.conf
|
||||
COPY --from=build-stage /app/dist /usr/share/nginx/html
|
||||
|
||||
EXPOSE 80
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mes-antd-admin
|
||||
namespace: sealers-dev
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 5
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mes-antd-admin
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
containers:
|
||||
- name: bmes-antd-admin
|
||||
image: registry.gitlab.com/seasoul/mes-antd-admin:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 80
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: timezone
|
||||
mountPath: /etc/localtime
|
||||
# ============EnvSetttingStart===========
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
env: # 环境变量
|
||||
- name: API_SERVER_HOST # Api服务地址
|
||||
value: http://zxx4.f3322.net # 请在files-settings.yaml中修改
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
# ============EnvSetttingEnd===========
|
||||
imagePullSecrets:
|
||||
- name: gitlab
|
||||
volumes:
|
||||
- name: timezone
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mes-antd-admin-svc
|
||||
namespace: sealers-dev
|
||||
spec:
|
||||
ports:
|
||||
- port: 19001
|
||||
targetPort: 19001
|
||||
selector:
|
||||
app: mes-antd-admin
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-c
|
||||
namespace: sealers-dev
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-c
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-m
|
||||
namespace: sealers-dev
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-m
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: 80
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mes-antd-admin
|
||||
namespace: sealers-prod
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 5
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mes-antd-admin
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
containers:
|
||||
- name: bmes-antd-admin
|
||||
image: registry.gitlab.com/seasoul/mes-antd-admin:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 80
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: timezone
|
||||
mountPath: /etc/localtime
|
||||
# ============EnvSetttingStart===========
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
env: # 环境变量
|
||||
- name: API_SERVER_HOST # Api服务地址
|
||||
value: http://zxx4.f3322.net # 请在files-settings.yaml中修改
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
# ============EnvSetttingEnd===========
|
||||
imagePullSecrets:
|
||||
- name: gitlab
|
||||
volumes:
|
||||
- name: timezone
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mes-antd-admin-svc
|
||||
namespace: sealers-prod
|
||||
spec:
|
||||
ports:
|
||||
- port: 19001
|
||||
targetPort: 19001
|
||||
selector:
|
||||
app: mes-antd-admin
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-c
|
||||
namespace: sealers-prod
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-c
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-m
|
||||
namespace: sealers-prod
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-m
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: 80
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mes-antd-admin
|
||||
namespace: sealers-test
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 5
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mes-antd-admin
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mes-antd-admin
|
||||
spec:
|
||||
containers:
|
||||
- name: bmes-antd-admin
|
||||
image: registry.gitlab.com/seasoul/mes-antd-admin:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 80
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 80
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
resources:
|
||||
requests:
|
||||
cpu: 50m
|
||||
memory: 64Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 256Mi
|
||||
volumeMounts:
|
||||
- name: timezone
|
||||
mountPath: /etc/localtime
|
||||
# ============EnvSetttingStart===========
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
env: # 环境变量
|
||||
- name: API_SERVER_HOST # Api服务地址
|
||||
value: http://zxx4.f3322.net # 请在files-settings.yaml中修改
|
||||
# 该内容为gozero-batch生成的内容,请不要手动修改
|
||||
# ============EnvSetttingEnd===========
|
||||
imagePullSecrets:
|
||||
- name: gitlab
|
||||
volumes:
|
||||
- name: timezone
|
||||
hostPath:
|
||||
path: /usr/share/zoneinfo/Asia/Shanghai
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mes-antd-admin-svc
|
||||
namespace: sealers-test
|
||||
spec:
|
||||
ports:
|
||||
- port: 19001
|
||||
targetPort: 19001
|
||||
selector:
|
||||
app: mes-antd-admin
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-c
|
||||
namespace: sealers-test
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-c
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: cpu
|
||||
targetAverageUtilization: 80
|
||||
|
||||
---
|
||||
|
||||
apiVersion: autoscaling/v2beta1
|
||||
kind: HorizontalPodAutoscaler
|
||||
metadata:
|
||||
name: mes-antd-admin-hpa-m
|
||||
namespace: sealers-test
|
||||
labels:
|
||||
app: mes-antd-admin-hpa-m
|
||||
spec:
|
||||
scaleTargetRef:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
name: mes-antd-admin
|
||||
minReplicas: 1
|
||||
maxReplicas: 50
|
||||
metrics:
|
||||
- type: Resource
|
||||
resource:
|
||||
name: memory
|
||||
targetAverageUtilization: 80
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
version: '3.5'
|
||||
|
||||
networks:
|
||||
backend:
|
||||
driver: ${NETWORKS_DRIVER}
|
||||
|
||||
|
||||
services:
|
||||
mes-antd-admin:
|
||||
container_name: mes-antd-admin
|
||||
image: registry.gitlab.com/seasoul/mes-antd-admin:latest
|
||||
# depends_on: # 依赖容器
|
||||
# - app_config-rpc # 在 app_config-rpc 服务容器启动后启动
|
||||
restart: always
|
||||
ports: # 设置端口映射
|
||||
- "80:80"
|
||||
network_mode: ${NETWORKS_DRIVER}
|
||||
environment: # 设置环境变量
|
||||
- "API_SERVER_HOST=${API_SERVER_HOST}"
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
user nginx;
|
||||
worker_processes 1;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 65535;
|
||||
use epoll;
|
||||
epoll_events 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
|
||||
#charset koi8-r;
|
||||
access_log /var/log/nginx/host.access.log main;
|
||||
error_log /var/log/nginx/error.log error;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
#error_page 404 /404.html;
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,13 +3,15 @@ import {loadInterceptors} from '@/utils/request'
|
|||
import guards from '@/router/guards'
|
||||
import interceptors from '@/utils/axios-interceptors'
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 启动引导方法
|
||||
* 应用启动时需要执行的操作放在这里
|
||||
* @param router 应用的路由实例
|
||||
* @param store 应用的 vuex.store 实例
|
||||
* @param i18n 应用的 vue-i18n 实例
|
||||
* @param i18n 应用的 message 实例
|
||||
* @param message 应用的 message 实例
|
||||
*/
|
||||
function bootstrap({router, store, i18n, message}) {
|
||||
// 设置应用配置
|
||||
|
|
@ -19,7 +21,7 @@ function bootstrap({router, store, i18n, message}) {
|
|||
// 加载路由
|
||||
loadRoutes()
|
||||
// 加载路由守卫
|
||||
loadGuards(guards, {router, store, i18n, message})
|
||||
loadGuards(guards, {router, store, i18n, message})// 权限配置
|
||||
}
|
||||
|
||||
export default bootstrap
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ export default {
|
|||
}
|
||||
.content {
|
||||
flex: 1 1 0;
|
||||
:global {
|
||||
.ant-form-item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
// :global {
|
||||
// .ant-form-item:last-child {
|
||||
// margin-right: 0;
|
||||
// }
|
||||
// .ant-form-item {
|
||||
// margin-bottom: 0px;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -49,11 +49,11 @@ export default {
|
|||
.step-item{
|
||||
cursor: pointer;
|
||||
}
|
||||
:global{
|
||||
.ant-steps-item-process{
|
||||
.linkable{
|
||||
color: @primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
// :global{
|
||||
// .ant-steps-item-process{
|
||||
// .linkable{
|
||||
// color: @primary-color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -57,13 +57,13 @@ export default {
|
|||
margin-left: -8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
:global {
|
||||
.ant-avatar {
|
||||
border: 1px solid #fff;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
// :global {
|
||||
// .ant-avatar {
|
||||
// border: 1px solid #fff;
|
||||
// width: 20px;
|
||||
// height: 20px;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module.exports = {
|
|||
mode: 'dark',
|
||||
},
|
||||
multiPage: true,
|
||||
// asyncRoutes: true, //异步加载路由,true:开启,false:不开启
|
||||
asyncRoutes: true, //异步加载路由,true:开启,false:不开启
|
||||
animate: {
|
||||
name: 'lightSpeed',
|
||||
direction: 'left'
|
||||
|
|
|
|||
|
|
@ -60,9 +60,11 @@
|
|||
},
|
||||
inject:['adminLayout'],
|
||||
created() {
|
||||
|
||||
this.affixed = this.fixedTabs
|
||||
},
|
||||
computed: {
|
||||
|
||||
...mapState('setting', ['layout', 'pageWidth', 'fixedHeader', 'fixedTabs', 'customTitles']),
|
||||
lockTitle() {
|
||||
return this.$t(this.fixedTabs ? 'unlock' : 'lock')
|
||||
|
|
|
|||
|
|
@ -17,10 +17,6 @@ Mock.mock(`${process.env.VUE_APP_API_BASE_URL}/login`, 'post', ({body}) => {
|
|||
success = true
|
||||
result.data.permissions = [{id: 'queryForm', operation: ['add', 'edit']}]
|
||||
result.data.roles = [{id: 'admin', operation: ['add', 'edit', 'delete']}]
|
||||
} else if (name === 'test' || password === '888888') {
|
||||
success = true
|
||||
result.data.permissions = [{id: 'queryForm', operation: ['add', 'edit']}]
|
||||
result.data.roles = [{id: 'test', operation: ['add', 'edit', 'delete']}]
|
||||
} else {
|
||||
success = false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ export default {
|
|||
<style lang="less" scoped>
|
||||
.stepFormText {
|
||||
margin-bottom: 24px;
|
||||
:global {
|
||||
.ant-form-item-label,
|
||||
.ant-form-item-control {
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
// :global {
|
||||
// .ant-form-item-label,
|
||||
// .ant-form-item-control {
|
||||
// line-height: 22px;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations('account', ['setUser', 'setPermissions', 'setRoles']),
|
||||
...mapMutations('account', ['setUser']),
|
||||
onSubmit (e) {
|
||||
e.preventDefault()
|
||||
this.form.validateFields((err) => {
|
||||
|
|
@ -109,20 +109,24 @@ export default {
|
|||
})
|
||||
},
|
||||
afterLogin(res) {
|
||||
console.log(res)
|
||||
this.logging = false
|
||||
const loginRes = res.data
|
||||
if (loginRes.code >= 0) {
|
||||
const {user, permissions, roles} = loginRes.data
|
||||
if (loginRes.code == 200) {
|
||||
const user = loginRes.data.uid
|
||||
console.log("user",user)
|
||||
console.log("loginRes.data.access_expire",loginRes.data.access_expire)
|
||||
this.setUser(user)
|
||||
this.setPermissions(permissions)
|
||||
this.setRoles(roles)
|
||||
setAuthorization({token: loginRes.data.token, expireAt: new Date(loginRes.data.expireAt)})
|
||||
// this.setPermissions(permissions)
|
||||
// this.setRoles(roles)
|
||||
setAuthorization({token: loginRes.data.access_token, expireAt: new Date(loginRes.data.access_expire*1000)})
|
||||
// 获取路由配置
|
||||
getRoutesConfig().then(result => {
|
||||
const routesConfig = result.data.data
|
||||
const routesConfig = result.data.data.router
|
||||
loadRoutes(routesConfig)
|
||||
this.$router.push('/dashboard/workplace')
|
||||
this.$message.success(loginRes.message, 3)
|
||||
console.log("开始跳转")
|
||||
this.$router.push('/')
|
||||
this.$message.success(loginRes.msg, 3)
|
||||
})
|
||||
} else {
|
||||
this.error = loginRes.message
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import routerMap from './router.map'
|
||||
import {parseRoutes} from '@/utils/routerUtil'
|
||||
|
||||
// 异步路由中的root为根路由
|
||||
// 异步路由配置
|
||||
const routesConfig = [
|
||||
'login',
|
||||
|
|
@ -14,7 +14,8 @@ const routesConfig = [
|
|||
router: 'exp403',
|
||||
path: '/403',
|
||||
name: '403'
|
||||
}
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
const options = {
|
||||
|
|
|
|||
|
|
@ -275,204 +275,204 @@ const options = {
|
|||
|
||||
|
||||
|
||||
// {
|
||||
// path: 'list',
|
||||
// name: '列表页',
|
||||
// meta: {
|
||||
// icon: 'table'
|
||||
// },
|
||||
// component: PageView,
|
||||
// children: [
|
||||
// {
|
||||
// path: 'query',
|
||||
// name: '查询表格',
|
||||
// meta: {
|
||||
// authority: 'queryForm',
|
||||
// },
|
||||
// component: () => import('@/pages/list/QueryList'),
|
||||
// },
|
||||
// {
|
||||
// path: 'query/detail/:id',
|
||||
// name: '查询详情',
|
||||
// meta: {
|
||||
// highlight: '/list/query',
|
||||
// invisible: true
|
||||
// },
|
||||
// component: () => import('@/pages/Demo')
|
||||
// },
|
||||
// {
|
||||
// path: 'primary',
|
||||
// name: '标准列表',
|
||||
// component: () => import('@/pages/list/StandardList'),
|
||||
// },
|
||||
// {
|
||||
// path: 'card',
|
||||
// name: '卡片列表',
|
||||
// component: () => import('@/pages/list/CardList'),
|
||||
// },
|
||||
// {
|
||||
// path: 'search',
|
||||
// name: '搜索列表',
|
||||
// component: () => import('@/pages/list/search/SearchLayout'),
|
||||
// children: [
|
||||
// {
|
||||
// path: 'article',
|
||||
// name: '文章',
|
||||
// component: () => import('@/pages/list/search/ArticleList'),
|
||||
// },
|
||||
// {
|
||||
// path: 'application',
|
||||
// name: '应用',
|
||||
// component: () => import('@/pages/list/search/ApplicationList'),
|
||||
// },
|
||||
// {
|
||||
// path: 'project',
|
||||
// name: '项目',
|
||||
// component: () => import('@/pages/list/search/ProjectList'),
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: 'details',
|
||||
// name: '详情页',
|
||||
// meta: {
|
||||
// icon: 'profile'
|
||||
// },
|
||||
// component: BlankView,
|
||||
// children: [
|
||||
// {
|
||||
// path: 'basic',
|
||||
// name: '基础详情页',
|
||||
// component: () => import('@/pages/detail/BasicDetail')
|
||||
// },
|
||||
// {
|
||||
// path: 'advance',
|
||||
// name: '高级详情页',
|
||||
// component: () => import('@/pages/detail/AdvancedDetail')
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: 'result',
|
||||
// name: '结果页',
|
||||
// meta: {
|
||||
// icon: 'check-circle-o',
|
||||
// },
|
||||
// component: PageView,
|
||||
// children: [
|
||||
// {
|
||||
// path: 'success',
|
||||
// name: '成功',
|
||||
// component: () => import('@/pages/result/Success')
|
||||
// },
|
||||
// {
|
||||
// path: 'error',
|
||||
// name: '失败',
|
||||
// component: () => import('@/pages/result/Error')
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: 'exception',
|
||||
// name: '异常页',
|
||||
// meta: {
|
||||
// icon: 'warning',
|
||||
// },
|
||||
// component: BlankView,
|
||||
// children: [
|
||||
// {
|
||||
// path: '404',
|
||||
// name: 'Exp404',
|
||||
// component: () => import('@/pages/exception/404')
|
||||
// },
|
||||
// {
|
||||
// path: '403',
|
||||
// name: 'Exp403',
|
||||
// component: () => import('@/pages/exception/403')
|
||||
// },
|
||||
// {
|
||||
// path: '500',
|
||||
// name: 'Exp500',
|
||||
// component: () => import('@/pages/exception/500')
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// path: 'components',
|
||||
// name: '内置组件',
|
||||
// meta: {
|
||||
// icon: 'appstore-o'
|
||||
// },
|
||||
// component: PageView,
|
||||
// children: [
|
||||
// {
|
||||
// path: 'taskCard',
|
||||
// name: '任务卡片',
|
||||
// component: () => import('@/pages/components/TaskCard')
|
||||
// },
|
||||
// {
|
||||
// path: 'palette',
|
||||
// name: '颜色复选框',
|
||||
// component: () => import('@/pages/components/Palette')
|
||||
// },
|
||||
// {
|
||||
// path: 'table',
|
||||
// name: '高级表格',
|
||||
// component: () => import('@/pages/components/table')
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// name: '验权表单',
|
||||
// path: 'auth/form',
|
||||
// meta: {
|
||||
// icon: 'file-excel',
|
||||
// authority: {
|
||||
// permission: 'form'
|
||||
// }
|
||||
// },
|
||||
// component: () => import('@/pages/form/basic')
|
||||
// },
|
||||
// {
|
||||
// name: '带参菜单',
|
||||
// path: 'router/query',
|
||||
// meta: {
|
||||
// icon: 'project',
|
||||
// query: {
|
||||
// name: '菜单默认参数'
|
||||
// }
|
||||
// },
|
||||
// component: () => import('@/pages/Demo')
|
||||
// },
|
||||
// {
|
||||
// name: '动态路由菜单',
|
||||
// path: 'router/dynamic/:id',
|
||||
// meta: {
|
||||
// icon: 'project',
|
||||
// params: {
|
||||
// id: 123
|
||||
// }
|
||||
// },
|
||||
// component: () => import('@/pages/Demo')
|
||||
// },
|
||||
// {
|
||||
// name: 'Ant Design Vue',
|
||||
// path: 'antdv',
|
||||
// meta: {
|
||||
// icon: 'ant-design',
|
||||
// link: 'https://www.antdv.com/docs/vue/introduce-cn/'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: '使用文档',
|
||||
// path: 'document',
|
||||
// meta: {
|
||||
// icon: 'file-word',
|
||||
// link: 'https://iczer.gitee.io/vue-antd-admin-docs/'
|
||||
// }
|
||||
// }
|
||||
{
|
||||
path: 'list',
|
||||
name: '列表页',
|
||||
meta: {
|
||||
icon: 'table'
|
||||
},
|
||||
component: PageView,
|
||||
children: [
|
||||
{
|
||||
path: 'query',
|
||||
name: '查询表格',
|
||||
meta: {
|
||||
authority: 'queryForm',
|
||||
},
|
||||
component: () => import('@/pages/list/QueryList'),
|
||||
},
|
||||
{
|
||||
path: 'query/detail/:id',
|
||||
name: '查询详情',
|
||||
meta: {
|
||||
highlight: '/list/query',
|
||||
invisible: true
|
||||
},
|
||||
component: () => import('@/pages/Demo')
|
||||
},
|
||||
{
|
||||
path: 'primary',
|
||||
name: '标准列表',
|
||||
component: () => import('@/pages/list/StandardList'),
|
||||
},
|
||||
{
|
||||
path: 'card',
|
||||
name: '卡片列表',
|
||||
component: () => import('@/pages/list/CardList'),
|
||||
},
|
||||
{
|
||||
path: 'search',
|
||||
name: '搜索列表',
|
||||
component: () => import('@/pages/list/search/SearchLayout'),
|
||||
children: [
|
||||
{
|
||||
path: 'article',
|
||||
name: '文章',
|
||||
component: () => import('@/pages/list/search/ArticleList'),
|
||||
},
|
||||
{
|
||||
path: 'application',
|
||||
name: '应用',
|
||||
component: () => import('@/pages/list/search/ApplicationList'),
|
||||
},
|
||||
{
|
||||
path: 'project',
|
||||
name: '项目',
|
||||
component: () => import('@/pages/list/search/ProjectList'),
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'details',
|
||||
name: '详情页',
|
||||
meta: {
|
||||
icon: 'profile'
|
||||
},
|
||||
component: BlankView,
|
||||
children: [
|
||||
{
|
||||
path: 'basic',
|
||||
name: '基础详情页',
|
||||
component: () => import('@/pages/detail/BasicDetail')
|
||||
},
|
||||
{
|
||||
path: 'advance',
|
||||
name: '高级详情页',
|
||||
component: () => import('@/pages/detail/AdvancedDetail')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'result',
|
||||
name: '结果页',
|
||||
meta: {
|
||||
icon: 'check-circle-o',
|
||||
},
|
||||
component: PageView,
|
||||
children: [
|
||||
{
|
||||
path: 'success',
|
||||
name: '成功',
|
||||
component: () => import('@/pages/result/Success')
|
||||
},
|
||||
{
|
||||
path: 'error',
|
||||
name: '失败',
|
||||
component: () => import('@/pages/result/Error')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'exception',
|
||||
name: '异常页',
|
||||
meta: {
|
||||
icon: 'warning',
|
||||
},
|
||||
component: BlankView,
|
||||
children: [
|
||||
{
|
||||
path: '404',
|
||||
name: 'Exp404',
|
||||
component: () => import('@/pages/exception/404')
|
||||
},
|
||||
{
|
||||
path: '403',
|
||||
name: 'Exp403',
|
||||
component: () => import('@/pages/exception/403')
|
||||
},
|
||||
{
|
||||
path: '500',
|
||||
name: 'Exp500',
|
||||
component: () => import('@/pages/exception/500')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'components',
|
||||
name: '内置组件',
|
||||
meta: {
|
||||
icon: 'appstore-o'
|
||||
},
|
||||
component: PageView,
|
||||
children: [
|
||||
{
|
||||
path: 'taskCard',
|
||||
name: '任务卡片',
|
||||
component: () => import('@/pages/components/TaskCard')
|
||||
},
|
||||
{
|
||||
path: 'palette',
|
||||
name: '颜色复选框',
|
||||
component: () => import('@/pages/components/Palette')
|
||||
},
|
||||
{
|
||||
path: 'table',
|
||||
name: '高级表格',
|
||||
component: () => import('@/pages/components/table')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: '验权表单',
|
||||
path: 'auth/form',
|
||||
meta: {
|
||||
icon: 'file-excel',
|
||||
authority: {
|
||||
permission: 'form'
|
||||
}
|
||||
},
|
||||
component: () => import('@/pages/form/basic')
|
||||
},
|
||||
{
|
||||
name: '带参菜单',
|
||||
path: 'router/query',
|
||||
meta: {
|
||||
icon: 'project',
|
||||
query: {
|
||||
name: '菜单默认参数'
|
||||
}
|
||||
},
|
||||
component: () => import('@/pages/Demo')
|
||||
},
|
||||
{
|
||||
name: '动态路由菜单',
|
||||
path: 'router/dynamic/:id',
|
||||
meta: {
|
||||
icon: 'project',
|
||||
params: {
|
||||
id: 123
|
||||
}
|
||||
},
|
||||
component: () => import('@/pages/Demo')
|
||||
},
|
||||
{
|
||||
name: 'Ant Design Vue',
|
||||
path: 'antdv',
|
||||
meta: {
|
||||
icon: 'ant-design',
|
||||
link: 'https://www.antdv.com/docs/vue/introduce-cn/'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '使用文档',
|
||||
path: 'document',
|
||||
meta: {
|
||||
icon: 'file-word',
|
||||
link: 'https://iczer.gitee.io/vue-antd-admin-docs/'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import {hasAuthority} from '@/utils/authority-utils'
|
||||
import {loginIgnore} from '@/router/index'
|
||||
import {checkAuthorization} from '@/utils/request'
|
||||
import NProgress from 'nprogress'
|
||||
import {hasAuthority} from '@/utils/authority-utils' // 权限判断
|
||||
import {loginIgnore} from '@/router/index' // 不用登录白名单
|
||||
import {checkAuthorization} from '@/utils/request' // 登录校验
|
||||
import NProgress from 'nprogress' // 进度条
|
||||
|
||||
NProgress.configure({ showSpinner: false })
|
||||
NProgress.configure({ showSpinner: false }) // 进度条配置 是否显示加载ico
|
||||
|
||||
/**
|
||||
* 进度条开始
|
||||
|
|
@ -11,12 +11,12 @@ NProgress.configure({ showSpinner: false })
|
|||
* @param form
|
||||
* @param next
|
||||
*/
|
||||
const progressStart = (to, from, next) => {
|
||||
const progressStart = (to, from, next) => {
|
||||
// start progress bar
|
||||
if (!NProgress.isStarted()) {
|
||||
NProgress.start()
|
||||
if (!NProgress.isStarted()) { // 如果进度条没有开始
|
||||
NProgress.start() // 进度条开始
|
||||
}
|
||||
next()
|
||||
next() // 正常跳转
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -27,12 +27,12 @@ const progressStart = (to, from, next) => {
|
|||
* @param options
|
||||
*/
|
||||
const loginGuard = (to, from, next, options) => {
|
||||
const {message} = options
|
||||
if (!loginIgnore.includes(to) && !checkAuthorization()) {
|
||||
const {message} = options // 获取message
|
||||
if (!loginIgnore.includes(to) && !checkAuthorization()) { // 如果不是白名单 并且登录校验失败
|
||||
message.warning('登录已失效,请重新登录')
|
||||
next({path: '/login'})
|
||||
next({path: '/login'}) // 跳转到登录页面
|
||||
} else {
|
||||
next()
|
||||
next() // 如果是白名单,正常跳转
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,16 +43,17 @@ const loginGuard = (to, from, next, options) => {
|
|||
* @param next
|
||||
* @param options
|
||||
*/
|
||||
|
||||
const authorityGuard = (to, from, next, options) => {
|
||||
const {store, message} = options
|
||||
const permissions = store.getters['account/permissions']
|
||||
const roles = store.getters['account/roles']
|
||||
if (!hasAuthority(to, permissions, roles)) {
|
||||
const permissions = store.getters['account/permissions'] // 获取权限数据
|
||||
if (!hasAuthority(to, permissions)) { // 判断是否有权限
|
||||
// 如果没有权限,跳转到403页面
|
||||
message.warning(`对不起,您无权访问页面: ${to.fullPath},请联系管理员`)
|
||||
next({path: '/403'})
|
||||
// NProgress.done()
|
||||
} else {
|
||||
next()
|
||||
next() // 如果有权限,正常跳转到你设置好的页面
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,22 +66,22 @@ const authorityGuard = (to, from, next, options) => {
|
|||
* @returns {*}
|
||||
*/
|
||||
const redirectGuard = (to, from, next, options) => {
|
||||
const {store} = options
|
||||
const getFirstChild = (routes) => {
|
||||
const route = routes[0]
|
||||
if (!route.children || route.children.length === 0) {
|
||||
const {store} = options // 获取store
|
||||
const getFirstChild = (routes) => { // 获取第一个子路由
|
||||
const route = routes[0] // 获取第一个路由
|
||||
if (!route.children || route.children.length === 0) { // 如果没有子路由,返回当前路由
|
||||
return route
|
||||
}
|
||||
return getFirstChild(route.children)
|
||||
return getFirstChild(route.children) // 如果有子路由,递归获取第一个子路由
|
||||
}
|
||||
if (store.state.setting.layout === 'mix') {
|
||||
const firstMenu = store.getters['setting/firstMenu']
|
||||
if (firstMenu.find(item => item.fullPath === to.fullPath)) {
|
||||
store.commit('setting/setActivatedFirst', to.fullPath)
|
||||
const subMenu = store.getters['setting/subMenu']
|
||||
if (subMenu.length > 0) {
|
||||
const redirect = getFirstChild(subMenu)
|
||||
return next({path: redirect.fullPath})
|
||||
if (store.state.setting.layout === 'mix') { // 如果是混合导航模式
|
||||
const firstMenu = store.getters['setting/firstMenu'] // 获取第一个菜单
|
||||
if (firstMenu.find(item => item.fullPath === to.fullPath)) { // 如果是第一个菜单列表,
|
||||
store.commit('setting/setActivatedFirst', to.fullPath) // 设置激活的第一个菜单
|
||||
const subMenu = store.getters['setting/subMenu'] // 获取第一个菜单的子菜单
|
||||
if (subMenu.length > 0) { // 如果有子菜单
|
||||
const redirect = getFirstChild(subMenu) // 获取第一个子菜单
|
||||
return next({path: redirect.fullPath}) // 重定向到第一个子菜单
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,11 +94,12 @@ const redirectGuard = (to, from, next, options) => {
|
|||
* @param form
|
||||
* @param options
|
||||
*/
|
||||
const progressDone = () => {
|
||||
const progressDone = () => { // 进度条结束
|
||||
// finish progress bar
|
||||
NProgress.done()
|
||||
NProgress.done() // 进度条结束
|
||||
}
|
||||
|
||||
// guards 是登录守卫,权限守卫,进度条守卫,重定向守卫的集合
|
||||
export default {
|
||||
beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard],
|
||||
afterEach: [progressDone]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import {formatRoutes} from '@/utils/routerUtil'
|
||||
import {formatRoutes} from '@/utils/routerUtil' // 引入路由格式化工具
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
// 不需要登录拦截的路由配置
|
||||
const loginIgnore = {
|
||||
const loginIgnore = { // 登录白名单
|
||||
names: ['404', '403'], //根据路由名称匹配
|
||||
paths: ['/login'], //根据路由fullPath匹配
|
||||
/**
|
||||
|
|
@ -13,19 +13,26 @@ const loginIgnore = {
|
|||
* @param route vue-router 的 route 对象
|
||||
* @returns {boolean}
|
||||
*/
|
||||
includes(route) {
|
||||
return this.names.includes(route.name) || this.paths.includes(route.path)
|
||||
includes(route) { // 判断路由是否包含在该配置中
|
||||
return this.names.includes(route.name) || this.paths.includes(route.path) // 返回true则不需要登录拦截
|
||||
}
|
||||
}
|
||||
|
||||
// 解决重复点击路由报错的BUG
|
||||
const originalPush = Router.prototype.push // 保存原型对象中的push方法
|
||||
Router.prototype.push = function push(location) { // 重写原型对象中的push方法
|
||||
return originalPush.call(this, location).catch((err) => err) // 抛出错误
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化路由实例
|
||||
* @param isAsync 是否异步路由模式
|
||||
* @returns {VueRouter}
|
||||
*/
|
||||
function initRouter(isAsync) {
|
||||
const options = isAsync ? require('./async/config.async').default : require('./config').default
|
||||
formatRoutes(options.routes)
|
||||
return new Router(options)
|
||||
function initRouter(isAsync) { // 初始化路由
|
||||
const options = isAsync ? require('./async/config.async').default : require('./config').default // 引入路由配置
|
||||
formatRoutes(options.routes) // 格式化路由
|
||||
return new Router(options) // 返回路由实例
|
||||
}
|
||||
export {loginIgnore, initRouter}
|
||||
export {loginIgnore, initRouter} // 导出路由配置和初始化路由方法
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
//跨域代理前缀
|
||||
// const API_PROXY_PREFIX='/api'
|
||||
// const BASE_URL = process.env.NODE_ENV === 'production' ? process.env.VUE_APP_API_BASE_URL : API_PROXY_PREFIX
|
||||
const BASE_URL = process.env.VUE_APP_API_BASE_URL
|
||||
const BASE_URL = process.env.VUE_APP_API_BASE_URL // 获取环境变量VUE_APP_API_BASE_URL
|
||||
module.exports = {
|
||||
LOGIN: `${BASE_URL}/login`,
|
||||
ROUTES: `${BASE_URL}/routes`,
|
||||
GOODS: `${BASE_URL}/goods`,
|
||||
GOODS_COLUMNS: `${BASE_URL}/columns`,
|
||||
LOGIN: `${BASE_URL}/AdminUser/v1/login`,
|
||||
ROUTES: `${BASE_URL}/AdminUser/v1/routers`,
|
||||
USERINFO: `${BASE_URL}/AdminUser/v1/userinfo`,
|
||||
PERMISSION: `${BASE_URL}/AdminUser/v1/permission`,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {GOODS, GOODS_COLUMNS} from './api'
|
||||
import {GOODS, GOODS_COLUMNS} from './api' // 引入api.js中的常量
|
||||
import {METHOD, request} from '@/utils/request'
|
||||
|
||||
export async function goodsList(params) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import {LOGIN, ROUTES} from '@/services/api'
|
||||
import {LOGIN, ROUTES, USERINFO,PERMISSION} from '@/services/api'
|
||||
import {request, METHOD, removeAuthorization} from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 登录服务
|
||||
* @param name 账户名
|
||||
|
|
@ -9,13 +8,42 @@ import {request, METHOD, removeAuthorization} from '@/utils/request'
|
|||
*/
|
||||
export async function login(name, password) {
|
||||
return request(LOGIN, METHOD.POST, {
|
||||
name: name,
|
||||
mobile: name,
|
||||
password: password
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
* @param uid
|
||||
* @returns {Promise<AxiosResponse<T>>}
|
||||
*/
|
||||
export async function getUserInfo() {
|
||||
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数
|
||||
return request(USERINFO, METHOD.POST, {uid: userId})
|
||||
}
|
||||
/**
|
||||
* 获取路由配置
|
||||
* @param uid
|
||||
* @returns {Promise<AxiosResponse<T>>}
|
||||
*/
|
||||
export async function getRoutesConfig() {
|
||||
return request(ROUTES, METHOD.GET)
|
||||
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数
|
||||
return request(ROUTES, METHOD.POST, {
|
||||
uid:userId
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取权限配置
|
||||
* @param uid
|
||||
* @returns {Promise<AxiosResponse<T>>}
|
||||
*/
|
||||
export async function getPermission() {
|
||||
const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数
|
||||
return request(PERMISSION, METHOD.POST, {
|
||||
uid:userId
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,76 +1,60 @@
|
|||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
user: undefined,
|
||||
permissions: null,
|
||||
roles: null,
|
||||
routesConfig: null
|
||||
user: undefined, // 用户信息
|
||||
permissions: null, // 权限
|
||||
routesConfig: null // 路由配置
|
||||
},
|
||||
getters: {
|
||||
user: state => {
|
||||
if (!state.user) {
|
||||
user: state => { // 用户信息
|
||||
if (!state.user) { // 如果没有用户信息
|
||||
try {
|
||||
const user = localStorage.getItem(process.env.VUE_APP_USER_KEY)
|
||||
state.user = JSON.parse(user)
|
||||
} catch (e) {
|
||||
const user = localStorage.getItem(process.env.VUE_APP_USER_KEY) // 获取用户信息
|
||||
state.user = user // 将用户信息赋值给state.user
|
||||
} catch (e) { // 捕获异常
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
return state.user
|
||||
return state.user // 如果有用户信息,直接返回
|
||||
},
|
||||
permissions: state => {
|
||||
if (!state.permissions) {
|
||||
permissions: state => { // 权限
|
||||
if (!state.permissions) { // 如果没有权限
|
||||
try {
|
||||
const permissions = localStorage.getItem(process.env.VUE_APP_PERMISSIONS_KEY)
|
||||
state.permissions = JSON.parse(permissions)
|
||||
state.permissions = state.permissions ? state.permissions : []
|
||||
} catch (e) {
|
||||
const permissions = localStorage.getItem(process.env.VUE_APP_PERMISSIONS_KEY) // 获取权限
|
||||
state.permissions = JSON.parse(permissions) // 将权限赋值给state.permissions
|
||||
state.permissions = state.permissions ? state.permissions : [] // 如果state.permissions为空,则赋值为空数组
|
||||
} catch (e) { // 捕获异常
|
||||
console.error(e.message)
|
||||
}
|
||||
}
|
||||
return state.permissions
|
||||
return state.permissions // 如果有权限,则返回权限
|
||||
},
|
||||
roles: state => {
|
||||
if (!state.roles) {
|
||||
|
||||
routesConfig: state => { // 路由配置
|
||||
if (!state.routesConfig) { // 如果没有路由配置
|
||||
try {
|
||||
const roles = localStorage.getItem(process.env.VUE_APP_ROLES_KEY)
|
||||
state.roles = JSON.parse(roles)
|
||||
state.roles = state.roles ? state.roles : []
|
||||
} catch (e) {
|
||||
const routesConfig = localStorage.getItem(process.env.VUE_APP_ROUTES_KEY) // 获取路由配置
|
||||
state.routesConfig = JSON.parse(routesConfig) // 将字符串转换为json对象
|
||||
state.routesConfig = state.routesConfig ? state.routesConfig : [] // 如果state.routesConfig为null,则赋值为空数组
|
||||
} catch (e) { // 捕获异常
|
||||
console.error(e.message)
|
||||
}
|
||||
}
|
||||
return state.roles
|
||||
},
|
||||
routesConfig: state => {
|
||||
if (!state.routesConfig) {
|
||||
try {
|
||||
const routesConfig = localStorage.getItem(process.env.VUE_APP_ROUTES_KEY)
|
||||
state.routesConfig = JSON.parse(routesConfig)
|
||||
state.routesConfig = state.routesConfig ? state.routesConfig : []
|
||||
} catch (e) {
|
||||
console.error(e.message)
|
||||
}
|
||||
}
|
||||
return state.routesConfig
|
||||
return state.routesConfig // 如果有路由配置,则返回路由配置
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
setUser (state, user) {
|
||||
state.user = user
|
||||
localStorage.setItem(process.env.VUE_APP_USER_KEY, JSON.stringify(user))
|
||||
setUser (state, user) { // 设置用户信息
|
||||
state.user = user
|
||||
localStorage.setItem(process.env.VUE_APP_USER_KEY, user)// 将所有用户信息存储到process.env.VUE_APP_USER_KEY中
|
||||
},
|
||||
setPermissions(state, permissions) {
|
||||
setPermissions(state, permissions) { // 设置权限
|
||||
state.permissions = permissions
|
||||
localStorage.setItem(process.env.VUE_APP_PERMISSIONS_KEY, JSON.stringify(permissions))
|
||||
localStorage.setItem(process.env.VUE_APP_PERMISSIONS_KEY, JSON.stringify(permissions)) // 将所有权限信息存储到process.env.VUE_APP_PERMISSIONS_KEY中
|
||||
},
|
||||
setRoles(state, roles) {
|
||||
state.roles = roles
|
||||
localStorage.setItem(process.env.VUE_APP_ROLES_KEY, JSON.stringify(roles))
|
||||
},
|
||||
setRoutesConfig(state, routesConfig) {
|
||||
setRoutesConfig(state, routesConfig) { // 设置路由配置
|
||||
state.routesConfig = routesConfig
|
||||
localStorage.setItem(process.env.VUE_APP_ROUTES_KEY, JSON.stringify(routesConfig))
|
||||
localStorage.setItem(process.env.VUE_APP_ROUTES_KEY, JSON.stringify(routesConfig)) // 将所有路由信息存储到process.env.VUE_APP_ROUTES_KEY中
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,113 +1,113 @@
|
|||
import config from '@/config'
|
||||
import {ADMIN} from '@/config/default'
|
||||
import {formatFullPath} from '@/utils/i18n'
|
||||
import {filterMenu} from '@/utils/authority-utils'
|
||||
import {getLocalSetting} from '@/utils/themeUtil'
|
||||
import deepClone from 'lodash.clonedeep'
|
||||
import config from '@/config' // 引入配置文件
|
||||
import {ADMIN} from '@/config/default' // 默认配置
|
||||
import {formatFullPath} from '@/utils/i18n' // 路由国际化
|
||||
import {filterMenu} from '@/utils/authority-utils' // 菜单权限过滤
|
||||
import {getLocalSetting} from '@/utils/themeUtil' // 主题配置
|
||||
import deepClone from 'lodash.clonedeep' // 深拷贝
|
||||
|
||||
const localSetting = getLocalSetting(true)
|
||||
const customTitlesStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_TITLES_KEY)
|
||||
const localSetting = getLocalSetting(true) // 获取本地主题配置
|
||||
const customTitlesStr = sessionStorage.getItem(process.env.VUE_APP_TBAS_TITLES_KEY) // 获取本地自定义标题
|
||||
const customTitles = (customTitlesStr && JSON.parse(customTitlesStr)) || []
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
isMobile: false,
|
||||
animates: ADMIN.animates,
|
||||
palettes: ADMIN.palettes,
|
||||
pageMinHeight: 0,
|
||||
menuData: [],
|
||||
activatedFirst: undefined,
|
||||
customTitles,
|
||||
...config,
|
||||
...localSetting
|
||||
namespaced: true, // 命名空间
|
||||
state: { // 状态
|
||||
isMobile: false, // 是否是移动端
|
||||
animates: ADMIN.animates, // 动画
|
||||
palettes: ADMIN.palettes, // 主题
|
||||
pageMinHeight: 0, // 页面最小高度
|
||||
menuData: [], // 菜单数据
|
||||
activatedFirst: undefined, // 激活的第一个菜单
|
||||
customTitles, // 自定义标题
|
||||
...config, // 配置文件
|
||||
...localSetting // 本地主题配置
|
||||
},
|
||||
getters: {
|
||||
menuData(state, getters, rootState) {
|
||||
menuData(state, getters, rootState) { // 菜单数据
|
||||
if (state.filterMenu) {
|
||||
const {permissions, roles} = rootState.account
|
||||
return filterMenu(deepClone(state.menuData), permissions, roles)
|
||||
return filterMenu(deepClone(state.menuData), permissions, roles) // 过滤菜单 权限 和 角色
|
||||
}
|
||||
return state.menuData
|
||||
},
|
||||
firstMenu(state, getters) {
|
||||
const {menuData} = getters
|
||||
if (menuData.length > 0 && !menuData[0].fullPath) {
|
||||
formatFullPath(menuData)
|
||||
firstMenu(state, getters) { // 第一个菜单
|
||||
const {menuData} = getters // 从getters中获取菜单数据
|
||||
if (menuData.length > 0 && !menuData[0].fullPath) { // 如果菜单数据长度大于0 并且 菜单数据第一个元素没有fullPath
|
||||
formatFullPath(menuData) // 路由国际化
|
||||
}
|
||||
return menuData.map(item => {
|
||||
const menuItem = {...item}
|
||||
delete menuItem.children
|
||||
return menuItem
|
||||
return menuData.map(item => { // 返回data map item
|
||||
const menuItem = {...item} // 菜单项
|
||||
delete menuItem.children // 删除子菜单
|
||||
return menuItem // 返回菜单项
|
||||
})
|
||||
},
|
||||
subMenu(state) {
|
||||
const {menuData, activatedFirst} = state
|
||||
if (menuData.length > 0 && !menuData[0].fullPath) {
|
||||
formatFullPath(menuData)
|
||||
subMenu(state) { // 子菜单
|
||||
const {menuData, activatedFirst} = state // 从state中获取菜单数据 和 激活的第一个菜单
|
||||
if (menuData.length > 0 && !menuData[0].fullPath) { // 如果菜单数据长度大于0 并且 菜单数据第一个元素没有fullPath
|
||||
formatFullPath(menuData) // 路由国际化
|
||||
}
|
||||
const current = menuData.find(menu => menu.fullPath === activatedFirst)
|
||||
return current && current.children || []
|
||||
const current = menuData.find(menu => menu.fullPath === activatedFirst) // 当前菜单
|
||||
return current && current.children || [] // 返回当前菜单的子菜单
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
setDevice (state, isMobile) {
|
||||
setDevice (state, isMobile) { // 设置设备
|
||||
state.isMobile = isMobile
|
||||
},
|
||||
setTheme (state, theme) {
|
||||
setTheme (state, theme) { // 设置主题
|
||||
state.theme = theme
|
||||
},
|
||||
setLayout (state, layout) {
|
||||
setLayout (state, layout) { // 设置布局
|
||||
state.layout = layout
|
||||
},
|
||||
setMultiPage (state, multiPage) {
|
||||
setMultiPage (state, multiPage) { // 设置多页签
|
||||
state.multiPage = multiPage
|
||||
},
|
||||
setAnimate (state, animate) {
|
||||
setAnimate (state, animate) { // 设置动画
|
||||
state.animate = animate
|
||||
},
|
||||
setWeekMode(state, weekMode) {
|
||||
setWeekMode(state, weekMode) { // 设置周模式
|
||||
state.weekMode = weekMode
|
||||
},
|
||||
setFixedHeader(state, fixedHeader) {
|
||||
setFixedHeader(state, fixedHeader) { // 固定头部
|
||||
state.fixedHeader = fixedHeader
|
||||
},
|
||||
setFixedSideBar(state, fixedSideBar) {
|
||||
setFixedSideBar(state, fixedSideBar) { // 设置固定侧边栏
|
||||
state.fixedSideBar = fixedSideBar
|
||||
},
|
||||
setLang(state, lang) {
|
||||
setLang(state, lang) { // 设置语言
|
||||
state.lang = lang
|
||||
},
|
||||
setHideSetting(state, hideSetting) {
|
||||
setHideSetting(state, hideSetting) { // 设置隐藏设置
|
||||
state.hideSetting = hideSetting
|
||||
},
|
||||
correctPageMinHeight(state, minHeight) {
|
||||
correctPageMinHeight(state, minHeight) { // 修正页面最小高度
|
||||
state.pageMinHeight += minHeight
|
||||
},
|
||||
setMenuData(state, menuData) {
|
||||
setMenuData(state, menuData) { // 设置菜单数据
|
||||
state.menuData = menuData
|
||||
},
|
||||
setAsyncRoutes(state, asyncRoutes) {
|
||||
setAsyncRoutes(state, asyncRoutes) { // 设置异步路由
|
||||
state.asyncRoutes = asyncRoutes
|
||||
},
|
||||
setPageWidth(state, pageWidth) {
|
||||
setPageWidth(state, pageWidth) { // 设置页面宽度
|
||||
state.pageWidth = pageWidth
|
||||
},
|
||||
setActivatedFirst(state, activatedFirst) {
|
||||
setActivatedFirst(state, activatedFirst) { // 设置激活的第一个菜单
|
||||
state.activatedFirst = activatedFirst
|
||||
},
|
||||
setFixedTabs(state, fixedTabs) {
|
||||
setFixedTabs(state, fixedTabs) { // 设置固定标签
|
||||
state.fixedTabs = fixedTabs
|
||||
},
|
||||
setCustomTitle(state, {path, title}) {
|
||||
if (title) {
|
||||
const obj = state.customTitles.find(item => item.path === path)
|
||||
if (obj) {
|
||||
obj.title = title
|
||||
} else {
|
||||
state.customTitles.push({path, title})
|
||||
setCustomTitle(state, {path, title}) { // 设置自定义标题
|
||||
if (title) { // 如果标题存在
|
||||
const obj = state.customTitles.find(item => item.path === path) // 获取路径
|
||||
if (obj) { // 如果对象存在
|
||||
obj.title = title // 标题
|
||||
} else { // 否则
|
||||
state.customTitles.push({path, title}) // 添加路径和标题
|
||||
}
|
||||
sessionStorage.setItem(process.env.VUE_APP_TBAS_TITLES_KEY, JSON.stringify(state.customTitles))
|
||||
sessionStorage.setItem(process.env.VUE_APP_TBAS_TITLES_KEY, JSON.stringify(state.customTitles)) // 存储自定义标题
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,46 +4,10 @@
|
|||
* @param permissions 用户权限集合
|
||||
* @returns {boolean|*}
|
||||
*/
|
||||
function hasPermission(authority, permissions) {
|
||||
let required = '*'
|
||||
if (typeof authority === 'string') {
|
||||
required = authority
|
||||
} else if (typeof authority === 'object') {
|
||||
required = authority.permission
|
||||
}
|
||||
return required === '*' || (permissions && permissions.findIndex(item => item === required || item.id === required) !== -1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有路由需要的角色
|
||||
* @param authority 路由权限配置
|
||||
* @param roles 用户角色集合
|
||||
*/
|
||||
function hasRole(authority, roles) {
|
||||
let required = undefined
|
||||
if (typeof authority === 'object') {
|
||||
required = authority.role
|
||||
}
|
||||
return authority === '*' || hasAnyRole(required, roles)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有需要的任意一个角色
|
||||
* @param required {String | Array[String]} 需要的角色,可以是单个角色或者一个角色数组
|
||||
* @param roles 拥有的角色
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasAnyRole(required, roles) {
|
||||
if (!required) {
|
||||
return false
|
||||
} else if(Array.isArray(required)) {
|
||||
return roles.findIndex(role => {
|
||||
return required.findIndex(item => item === role || item === role.id) !== -1
|
||||
}) !== -1
|
||||
} else {
|
||||
return roles.findIndex(role => role === required || role.id === required) !== -1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 路由权限校验
|
||||
|
|
@ -52,14 +16,9 @@ function hasAnyRole(required, roles) {
|
|||
* @param roles 用户角色集合
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasAuthority(route, permissions, roles) {
|
||||
const authorities = [...route.meta.pAuthorities, route.meta.authority]
|
||||
for (let authority of authorities) {
|
||||
if (!hasPermission(authority, permissions) && !hasRole(authority, roles)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
function hasAuthority() { // 权限校验
|
||||
|
||||
return true // 如果都满足,返回true
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -67,6 +26,7 @@ function hasAuthority(route, permissions, roles) {
|
|||
* @param menuData
|
||||
* @param permissions
|
||||
* @param roles
|
||||
* 主要是在src\store\modules\setting.js中使用
|
||||
*/
|
||||
function filterMenu(menuData, permissions, roles) {
|
||||
return menuData.filter(menu => {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ async function request(url, method, params, config) {
|
|||
* @param authType {AUTH_TYPE} 认证类型,默认:{AUTH_TYPE.BEARER}
|
||||
*/
|
||||
function setAuthorization(auth, authType = AUTH_TYPE.BEARER) {
|
||||
console.log("authType:", authType);
|
||||
console.log("auth:", auth);
|
||||
switch (authType) {
|
||||
case AUTH_TYPE.BEARER:
|
||||
Cookie.set(xsrfHeaderName, 'Bearer ' + auth.token, {expires: auth.expireAt})
|
||||
|
|
|
|||
|
|
@ -107,18 +107,24 @@ function loadRoutes(routesConfig) {
|
|||
const {router, store, i18n} = appOptions
|
||||
|
||||
// 如果 routesConfig 有值,则更新到本地,否则从本地获取
|
||||
if (routesConfig) {
|
||||
store.commit('account/setRoutesConfig', routesConfig)
|
||||
console.log("setRoutesConfig:", routesConfig)
|
||||
|
||||
if (routesConfig) { // 如果routesConfig已经存在
|
||||
store.commit('account/setRoutesConfig', routesConfig) // 设置路由配置
|
||||
} else {
|
||||
routesConfig = store.getters['account/routesConfig']
|
||||
}
|
||||
// 如果开启了异步路由,则加载异步路由配置
|
||||
const asyncRoutes = store.state.setting.asyncRoutes
|
||||
if (asyncRoutes) {
|
||||
if (routesConfig && routesConfig.length > 0) {
|
||||
const routes = parseRoutes(routesConfig, routerMap)
|
||||
if (asyncRoutes) { // 如果动态路由存在
|
||||
if (routesConfig && routesConfig.length > 0) { // 如果本地路由配置存在 并且 数量大于0
|
||||
|
||||
const routes = parseRoutes(routesConfig, routerMap) // 解析路由
|
||||
// 合并路由 生成路由表
|
||||
const finalRoutes = mergeRoutes(basicOptions.routes, routes)
|
||||
// 格式化路由
|
||||
formatRoutes(finalRoutes)
|
||||
console.log('最终路由表finalRoutes:', finalRoutes) // 最终路由表
|
||||
router.options = {...router.options, routes: finalRoutes}
|
||||
router.matcher = new Router({...router.options, routes:[]}).matcher
|
||||
router.addRoutes(finalRoutes)
|
||||
|
|
@ -252,9 +258,9 @@ function getI18nKey(path) {
|
|||
* @param guards
|
||||
* @param options
|
||||
*/
|
||||
function loadGuards(guards, options) {
|
||||
const {beforeEach, afterEach} = guards
|
||||
const {router} = options
|
||||
function loadGuards(guards, options) { // 加载导航守卫 guards
|
||||
const {beforeEach, afterEach} = guards // 解构出 beforeEach 和 afterEach
|
||||
const {router} = options // 解构出 router
|
||||
beforeEach.forEach(guard => {
|
||||
if (guard && typeof guard === 'function') {
|
||||
router.beforeEach((to, from, next) => guard(to, from, next, options))
|
||||
|
|
|
|||
Loading…
Reference in New Issue