diff --git a/.env b/.env index 0c6e7c8..8cdc7a5 100644 --- a/.env +++ b/.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 diff --git a/.env.development b/.env.development index 67b0aee..ab6bd4b 100644 --- a/.env.development +++ b/.env.development @@ -1 +1 @@ -VUE_APP_API_BASE_URL=http://dev.iczer.com +VUE_APP_API_BASE_URL=http://192.168.31.90:19000 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..55a81b9 --- /dev/null +++ b/.gitlab-ci.yml @@ -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 # 部署正式环境 + + + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..182dbab --- /dev/null +++ b/Dockerfile @@ -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;"] diff --git a/deploy/mes-antd-admin-dev.yaml b/deploy/mes-antd-admin-dev.yaml new file mode 100644 index 0000000..6676f4f --- /dev/null +++ b/deploy/mes-antd-admin-dev.yaml @@ -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 diff --git a/deploy/mes-antd-admin-prod.yaml b/deploy/mes-antd-admin-prod.yaml new file mode 100644 index 0000000..0f318aa --- /dev/null +++ b/deploy/mes-antd-admin-prod.yaml @@ -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 diff --git a/deploy/mes-antd-admin-test.yaml b/deploy/mes-antd-admin-test.yaml new file mode 100644 index 0000000..4b4106f --- /dev/null +++ b/deploy/mes-antd-admin-test.yaml @@ -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 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..506ac29 --- /dev/null +++ b/docker-compose.yml @@ -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}" \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..c5eb070 --- /dev/null +++ b/nginx/nginx.conf @@ -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; + } + } +} diff --git a/src/bootstrap.js b/src/bootstrap.js index 8c53146..4878912 100644 --- a/src/bootstrap.js +++ b/src/bootstrap.js @@ -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 diff --git a/src/components/form/FormRow.vue b/src/components/form/FormRow.vue index def3f63..15c59c3 100644 --- a/src/components/form/FormRow.vue +++ b/src/components/form/FormRow.vue @@ -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; + // } + // } } } diff --git a/src/components/tool/AStepItem.vue b/src/components/tool/AStepItem.vue index 981a35c..f120e98 100644 --- a/src/components/tool/AStepItem.vue +++ b/src/components/tool/AStepItem.vue @@ -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; + // } + // } + // } diff --git a/src/components/tool/AvatarList.vue b/src/components/tool/AvatarList.vue index 7390cce..4a59e0f 100644 --- a/src/components/tool/AvatarList.vue +++ b/src/components/tool/AvatarList.vue @@ -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; + // } + // } } } diff --git a/src/config/config.js b/src/config/config.js index 49c32fe..ad021c5 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -5,7 +5,7 @@ module.exports = { mode: 'dark', }, multiPage: true, - // asyncRoutes: true, //异步加载路由,true:开启,false:不开启 + asyncRoutes: true, //异步加载路由,true:开启,false:不开启 animate: { name: 'lightSpeed', direction: 'left' diff --git a/src/layouts/tabs/TabsHead.vue b/src/layouts/tabs/TabsHead.vue index 499b0e9..e4da246 100644 --- a/src/layouts/tabs/TabsHead.vue +++ b/src/layouts/tabs/TabsHead.vue @@ -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') diff --git a/src/mock/user/login.js b/src/mock/user/login.js index 97db1a1..1832c89 100644 --- a/src/mock/user/login.js +++ b/src/mock/user/login.js @@ -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 } diff --git a/src/pages/form/step/Step2.vue b/src/pages/form/step/Step2.vue index a0b8415..b4e89f9 100644 --- a/src/pages/form/step/Step2.vue +++ b/src/pages/form/step/Step2.vue @@ -73,11 +73,11 @@ export default { diff --git a/src/pages/login/Login.vue b/src/pages/login/Login.vue index 888665d..2ad3a4c 100644 --- a/src/pages/login/Login.vue +++ b/src/pages/login/Login.vue @@ -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 diff --git a/src/router/async/config.async.js b/src/router/async/config.async.js index 6a80edf..29bd35e 100644 --- a/src/router/async/config.async.js +++ b/src/router/async/config.async.js @@ -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 = { diff --git a/src/router/config.js b/src/router/config.js index 2e8c3f1..c1e4572 100644 --- a/src/router/config.js +++ b/src/router/config.js @@ -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/' + } + } ] }, ] diff --git a/src/router/guards.js b/src/router/guards.js index 4bf0e62..f3b9bf9 100644 --- a/src/router/guards.js +++ b/src/router/guards.js @@ -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] diff --git a/src/router/index.js b/src/router/index.js index c5aa144..730128d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -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} // 导出路由配置和初始化路由方法 diff --git a/src/services/api.js b/src/services/api.js index f74208a..f5c0630 100644 --- a/src/services/api.js +++ b/src/services/api.js @@ -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`, } diff --git a/src/services/dataSource.js b/src/services/dataSource.js index 22bb960..d5777e3 100644 --- a/src/services/dataSource.js +++ b/src/services/dataSource.js @@ -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) { diff --git a/src/services/user.js b/src/services/user.js index 1f9d760..ae93bb8 100644 --- a/src/services/user.js +++ b/src/services/user.js @@ -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>} +*/ +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>} +*/ 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>} +*/ +export async function getPermission() { + const userId = parseInt(localStorage.getItem(process.env.VUE_APP_USER_KEY)) // 获取用户id并转换为整数 + return request(PERMISSION, METHOD.POST, { + uid:userId + }) } /** diff --git a/src/store/modules/account.js b/src/store/modules/account.js index ae80b9b..8105524 100644 --- a/src/store/modules/account.js +++ b/src/store/modules/account.js @@ -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中 } } } diff --git a/src/store/modules/setting.js b/src/store/modules/setting.js index 58471ce..f45bd70 100644 --- a/src/store/modules/setting.js +++ b/src/store/modules/setting.js @@ -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)) // 存储自定义标题 } } } diff --git a/src/utils/authority-utils.js b/src/utils/authority-utils.js index f9c171e..cb6def5 100644 --- a/src/utils/authority-utils.js +++ b/src/utils/authority-utils.js @@ -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 => { diff --git a/src/utils/request.js b/src/utils/request.js index b7bf84d..09b521f 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -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}) diff --git a/src/utils/routerUtil.js b/src/utils/routerUtil.js index ae0741e..79dec00 100644 --- a/src/utils/routerUtil.js +++ b/src/utils/routerUtil.js @@ -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))