shuishen
2024-01-19 4f8f5e5375b82a5ebc1f67f389b934b3b757f062
双登录页处理
10 files modified
1 files added
995 ■■■■■ changed files
public/index.html 4 ●●●● patch | view | raw | blame | history
src/lang/en.js 198 ●●●● patch | view | raw | blame | history
src/page/index/logo.vue 32 ●●●● patch | view | raw | blame | history
src/page/login/index.vue 15 ●●●●● patch | view | raw | blame | history
src/page/login/tenement.vue 150 ●●●●● patch | view | raw | blame | history
src/router/avue-router.js 127 ●●●●● patch | view | raw | blame | history
src/router/page/index.js 109 ●●●●● patch | view | raw | blame | history
src/store/getters.js 65 ●●●●● patch | view | raw | blame | history
src/store/modules/common.js 73 ●●●● patch | view | raw | blame | history
src/views/authority/role.vue 215 ●●●●● patch | view | raw | blame | history
src/views/wel/index.vue 7 ●●●● patch | view | raw | blame | history
public/index.html
@@ -24,11 +24,11 @@
      securityJsCode: '5c569caedb31676fc64da5be4c5e8cee',
    }
  </script>
  <script type="text/javascript" src='https://webapi.amap.com/maps?v=1.4.11&key=fce315b8c816ec06755a523ccae9922d&plugin=AMap.PlaceSearch'></script>
    <script type="text/javascript"
        src='https://webapi.amap.com/maps?v=1.4.11&key=fce315b8c816ec06755a523ccae9922d&plugin=AMap.PlaceSearch'></script>
  <script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
    <!-- AvueMap-end-->
  <link rel="icon" href="<%= BASE_URL %>favicon.png"> 
  <title>基层智治综合协同平台</title>
  <style>
    html,
src/lang/en.js
@@ -1,122 +1,122 @@
export default {
  title: '基层智治综合协同平台',
  logoutTip: 'Exit the system, do you want to continue?',
  submitText: 'submit',
  cancelText: 'cancel',
  search: 'Please input search content',
  menuTip: 'none menu list',
  title: "",
  logoutTip: "Exit the system, do you want to continue?",
  submitText: "submit",
  cancelText: "cancel",
  search: "Please input search content",
  menuTip: "none menu list",
  common: {
    condition: 'condition',
    display: 'display',
    hide: 'hide'
    condition: "condition",
    display: "display",
    hide: "hide",
  },
  tip: {
    select: 'Please select',
    input: 'Please input'
    select: "Please select",
    input: "Please input",
  },
  upload: {
    upload: 'upload',
    tip: 'Drag files here,/'
    upload: "upload",
    tip: "Drag files here,/",
  },
  date: {
    start: 'Start date',
    end: 'End date',
    t: 'today',
    y: 'yesterday',
    n: 'nearly 7',
    a: 'whole'
    start: "Start date",
    end: "End date",
    t: "today",
    y: "yesterday",
    n: "nearly 7",
    a: "whole",
  },
  form: {
    printBtn: 'print',
    mockBtn: 'mock',
    submitBtn: 'submit',
    emptyBtn: 'empty'
    printBtn: "print",
    mockBtn: "mock",
    submitBtn: "submit",
    emptyBtn: "empty",
  },
  crud: {
    filter: {
      addBtn: 'add',
      clearBtn: 'clear',
      resetBtn: 'reset',
      cancelBtn: 'cancel',
      submitBtn: 'submit'
      addBtn: "add",
      clearBtn: "clear",
      resetBtn: "reset",
      cancelBtn: "cancel",
      submitBtn: "submit",
    },
    column: {
      name: 'name',
      hide: 'hide',
      fixed: 'fixed',
      filters: 'filters',
      sortable: 'sortable',
      index: 'index',
      width: 'width'
      name: "name",
      hide: "hide",
      fixed: "fixed",
      filters: "filters",
      sortable: "sortable",
      index: "index",
      width: "width",
    },
    tipStartTitle: 'Currently selected',
    tipEndTitle: 'items',
    editTitle: 'edit',
    copyTitle: 'copy',
    addTitle: 'add',
    viewTitle: 'view',
    filterTitle: 'filter',
    showTitle: 'showTitle',
    menu: 'menu',
    addBtn: 'add',
    show: 'show',
    hide: 'hide',
    open: 'open',
    shrink: 'shrink',
    printBtn: 'print',
    excelBtn: 'excel',
    updateBtn: 'update',
    cancelBtn: 'cancel',
    searchBtn: 'search',
    emptyBtn: 'empty',
    menuBtn: 'menu',
    saveBtn: 'save',
    viewBtn: 'view',
    editBtn: 'edit',
    copyBtn: 'copy',
    delBtn: 'delete'
    tipStartTitle: "Currently selected",
    tipEndTitle: "items",
    editTitle: "edit",
    copyTitle: "copy",
    addTitle: "add",
    viewTitle: "view",
    filterTitle: "filter",
    showTitle: "showTitle",
    menu: "menu",
    addBtn: "add",
    show: "show",
    hide: "hide",
    open: "open",
    shrink: "shrink",
    printBtn: "print",
    excelBtn: "excel",
    updateBtn: "update",
    cancelBtn: "cancel",
    searchBtn: "search",
    emptyBtn: "empty",
    menuBtn: "menu",
    saveBtn: "save",
    viewBtn: "view",
    editBtn: "edit",
    copyBtn: "copy",
    delBtn: "delete",
  },
  login: {
    title: 'Login ',
    info: 'BladeX Development Platform',
    tenantId: 'Please input tenantId',
    username: 'Please input username',
    password: 'Please input a password',
    wechat: 'Wechat',
    qq: 'QQ',
    github: 'github',
    gitee: 'gitee',
    phone: 'Please input a phone',
    code: 'Please input a code',
    submit: 'Login',
    userLogin: 'userLogin',
    phoneLogin: 'phoneLogin',
    thirdLogin: 'thirdLogin',
    ssoLogin: 'ssoLogin',
    msgText: 'send code',
    msgSuccess: 'reissued code',
    title: "Login ",
    info: "BladeX Development Platform",
    tenantId: "Please input tenantId",
    username: "Please input username",
    password: "Please input a password",
    wechat: "Wechat",
    qq: "QQ",
    github: "github",
    gitee: "gitee",
    phone: "Please input a phone",
    code: "Please input a code",
    submit: "Login",
    userLogin: "userLogin",
    phoneLogin: "phoneLogin",
    thirdLogin: "thirdLogin",
    ssoLogin: "ssoLogin",
    msgText: "send code",
    msgSuccess: "reissued code",
  },
  navbar: {
    info: 'info',
    logOut: 'logout',
    userinfo: 'userinfo',
    switchDept : 'switch dept',
    dashboard: 'dashboard',
    lock: 'lock',
    bug: 'none bug',
    bugs: 'bug',
    screenfullF: 'exit screenfull',
    screenfull: 'screenfull',
    language: 'language',
    notice: 'notice',
    theme: 'theme',
    color: 'color'
    info: "info",
    logOut: "logout",
    userinfo: "userinfo",
    switchDept: "switch dept",
    dashboard: "dashboard",
    lock: "lock",
    bug: "none bug",
    bugs: "bug",
    screenfullF: "exit screenfull",
    screenfull: "screenfull",
    language: "language",
    notice: "notice",
    theme: "theme",
    color: "color",
  },
  tagsView: {
    search: 'Search',
    menu: 'menu',
    clearCache: 'Clear Cache',
    closeOthers: 'Close Others',
    closeAll: 'Close All'
  }
    search: "Search",
    menu: "menu",
    clearCache: "Clear Cache",
    closeOthers: "Close Others",
    closeAll: "Close All",
  },
};
src/page/index/logo.vue
@@ -1,47 +1,61 @@
<!--
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-12-14 17:10:00
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-01-19 15:47:47
 * @FilePath: \jczz_web\src\page\index\logo.vue
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
-->
<template>
  <div class="avue-logo">
    <transition name="fade">
      <span v-if="keyCollapse"
            class="avue-logo_subtitle"
            key="0">
            <span v-if="keyCollapse" class="avue-logo_subtitle" key="0">
        {{website.logo}}
      </span>
    </transition>
    <transition-group name="fade">
      <template v-if="!keyCollapse">
        <span class="avue-logo_title"
              key="1">{{website.indexTitle}} </span>
                <span class="avue-logo_title" key="1">{{ webTitle }} </span>
      </template>
    </transition-group>
  </div>
</template>
<script>
import { mapGetters } from "vuex";
import { getStore } from "@/util/store"
import { mapGetters } from "vuex"
export default {
  name: "logo",
  data() {
    return {};
        return {
            webTitle: getStore({ name: "webTitle" })
        }
  },
  created() {},
  computed: {
    ...mapGetters(["website", "keyCollapse"])
  },
  methods: {}
};
}
</script>
<style lang="scss">
.fade-leave-active {
  transition: opacity 0.2s;
}
.fade-enter-active {
  transition: opacity 2.5s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
.avue-logo {
  position: fixed;
  top: 0;
@@ -56,12 +70,14 @@
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
  color: rgba(255, 255, 255, 0.8);
  z-index: 1024;
  &_title {
    display: block;
    text-align: center;
    font-weight: 300;
    font-size: 20px;
  }
  &_subtitle {
    display: block;
    text-align: center;
src/page/login/index.vue
@@ -7,7 +7,8 @@
                    {{ time }}
                </div>
                <!-- <img class="img" src="/img/logo.png" alt=""> -->
                <p class="title">{{ $t('login.info') }}</p>
                <!-- <p class="title">{{ $t('login.info') }}</p> -->
                <p class="title">基层智治综合协同平台</p>
            </div>
            <div class="login-border">
                <img class="img" src="/img/logo.png" alt="">
@@ -33,6 +34,7 @@
    </div>
</template>
<script>
import { setStore, getStore } from "@/util/store"
import Watermark from "@/warterMarkVUE"
import userLogin from "./userlogin"
import codeLogin from "./codelogin"
@@ -71,6 +73,17 @@
        }
    },
    created () {
        document.title = "基层智治综合协同平台"
        setStore({
            name: "webTitle",
            content: '基层智治综合协同平台',
        })
        setStore({
            name: "webType",
            content: 'default',
        })
        Watermark.remove()
        this.handleLogin()
src/page/login/tenement.vue
New file
@@ -0,0 +1,150 @@
<template>
    <div class="login-container" ref="login" @keyup.enter.native="handleLogin">
        <top-color v-show="false"></top-color>
        <div class="login-weaper animated bounceInDown">
            <div class="login-left">
                <div class="login-time">
                    {{ time }}
                </div>
                <!-- <img class="img" src="/img/logo.png" alt=""> -->
                <!-- <p class="title">{{ $t('login.info') }}</p> -->
                <p class="title">上饶市智慧物业管理平台</p>
            </div>
            <div class="login-border">
                <img class="img" src="/img/logo.png" alt="">
                <div class="login-main">
                    <h4 class="login-title">
                        {{ $t('login.title') }}
                        <!-- <top-lang></top-lang> -->
                    </h4>
                    <userLogin v-if="activeName === 'user'"></userLogin>
                    <!-- <codeLogin v-else-if="activeName==='code'"></codeLogin> -->
                    <!-- <thirdLogin v-else-if="activeName==='third'"></thirdLogin> -->
                    <div class="login-menu">
                        <!-- <a href="#" @click.stop="activeName='user'">{{ $t('login.userLogin') }}</a> -->
                        <!--<a href="#" @click.stop="activeName='code'">{{ $t('login.phoneLogin') }}</a>-->
                        <!-- <a href="#" @click.stop="activeName='third'">{{ $t('login.thirdLogin') }}</a> -->
                        <!-- <a :href="website.ssoUrl + website.redirectUri">{{ $t('login.ssoLogin') }}</a> -->
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
import { setStore, getStore } from "@/util/store"
import Watermark from "@/warterMarkVUE"
import userLogin from "./userlogin"
import codeLogin from "./codelogin"
import thirdLogin from "./thirdlogin"
import { mapGetters } from "vuex"
import { dateFormat } from "@/util/date"
import { validatenull } from "@/util/validate"
import topLang from "@/page/index/top/top-lang"
import topColor from "@/page/index/top/top-color"
import { getQueryString, getTopUrl } from "@/util/util"
export default {
    name: "login",
    components: {
        userLogin,
        codeLogin,
        thirdLogin,
        topLang,
        topColor
    },
    data () {
        return {
            time: "",
            activeName: "user",
            socialForm: {
                tenantId: "000000",
                source: "",
                code: "",
                state: "",
            }
        }
    },
    watch: {
        $route () {
            this.handleLogin()
        }
    },
    created () {
        document.title = "上饶市智慧物业管理平台"
        setStore({
            name: "webTitle",
            content: '上饶市智慧物业管理平台',
        })
        setStore({
            name: "webType",
            content: 'secend',
        })
        Watermark.remove()
        this.handleLogin()
        this.getTime()
    },
    mounted () {
    },
    computed: {
        ...mapGetters(["website", "tagWel"])
    },
    props: [],
    methods: {
        getTime () {
            setInterval(() => {
                this.time = dateFormat(new Date())
            }, 1000)
        },
        handleLogin () {
            const topUrl = getTopUrl()
            const redirectUrl = "/oauth/redirect/"
            const ssoCode = "?code="
            this.socialForm.source = getQueryString("source")
            this.socialForm.code = getQueryString("code")
            this.socialForm.state = getQueryString("state")
            if (validatenull(this.socialForm.source) && topUrl.includes(redirectUrl)) {
                let source = topUrl.split("?")[0]
                source = source.split(redirectUrl)[1]
                this.socialForm.source = source
            }
            if (topUrl.includes(redirectUrl) && !validatenull(this.socialForm.source) && !validatenull(this.socialForm.code) && !validatenull(this.socialForm.state)) {
                const loading = this.$loading({
                    lock: true,
                    text: '第三方系统登录中,请稍后。。。',
                    spinner: "el-icon-loading"
                })
                this.$store.dispatch("LoginBySocial", this.socialForm).then(() => {
                    window.location.href = topUrl.split(redirectUrl)[0]
                    this.$router.push({ path: this.tagWel.value })
                    loading.close()
                }).catch(() => {
                    loading.close()
                })
            } else if (!topUrl.includes(redirectUrl) && !validatenull(this.socialForm.code) && !validatenull(this.socialForm.state)) {
                const loading = this.$loading({
                    lock: true,
                    text: '单点系统登录中,请稍后。。。',
                    spinner: "el-icon-loading"
                })
                this.$store.dispatch("LoginBySso", this.socialForm).then(() => {
                    window.location.href = topUrl.split(ssoCode)[0]
                    this.$router.push({ path: this.tagWel.value })
                    loading.close()
                }).catch(() => {
                    loading.close()
                })
            }
        }
    }
}
</script>
<style lang="scss">
@import "@/styles/login.scss";
</style>
src/router/avue-router.js
@@ -1,8 +1,10 @@
let RouterPlugin = function () {
  this.$router = null;
  this.$store = null;
};
import { getStore } from "@/util/store";
RouterPlugin.install = function (vue, option = {}) {
  this.$router = option.router;
  this.$store = option.store;
@@ -10,53 +12,58 @@
  // 这个的作用是 为了检查出网页链接,因为本项目用到了 iframe
  function isURL(s) {
    if (s.includes('html')) return true;
    return /^http[s]?:\/\/.*/.test(s)
    if (s.includes("html")) return true;
    return /^http[s]?:\/\/.*/.test(s);
  }
  // 将参数处理为参数的形式拼接
  function objToform(obj) {
    let result = [];
    Object.keys(obj).forEach(ele => {
    Object.keys(obj).forEach((ele) => {
      result.push(`${ele}=${obj[ele]}`);
    })
    return result.join('&');
    });
    return result.join("&");
  }
  this.$router.$avueRouter = {
    //全局配置
    $website: this.$store.getters.website,
    group: '',
    group: "",
    meta: {},
    safe: this,
    // 设置标题
    setTitle: (title) => {
      const defaultTitle = this.$vue.$t('title');
      title = title ? `${title}-${defaultTitle}` : defaultTitle;
      //   const defaultTitle = this.$vue.$t("title");
      title = title
        ? `${title}-${getStore({ name: "webTitle" })}`
        : getStore({ name: "webTitle" });
      document.title = title;
    },
    closeTag: (value) => {
      let tag = value || this.$store.getters.tag;
      if (typeof value === 'string') {
        tag = this.$store.getters.tagList.filter(ele => ele.value === value)[0]
      if (typeof value === "string") {
        tag = this.$store.getters.tagList.filter(
          (ele) => ele.value === value
        )[0];
      }
      this.$store.commit('DEL_TAG', tag)
      this.$store.commit("DEL_TAG", tag);
    },
    generateTitle: (title, key) => {
      if (!key) return title;
      const hasKey = this.$vue.$te('route.' + key)
      const hasKey = this.$vue.$te("route." + key);
      if (hasKey) {
        // $t :this method from vue-i18n, inject in @/lang/index.js
        const translatedTitle = this.$vue.$t('route.' + key)
        const translatedTitle = this.$vue.$t("route." + key);
        return translatedTitle
        return translatedTitle;
      }
      return title
      return title;
    },
    //处理路由
    getPath: function (params) {
      let {src} = params;
      let result = src || '/';
      let result = src || "/";
      if (isURL(src)) {
        result = `/myiframe/urlPath?${objToform(params)}`;
      }
@@ -65,12 +72,11 @@
    //正则处理路由
    vaildPath: function (list, path) {
      let result = false;
      list.forEach(ele => {
      list.forEach((ele) => {
        if (new RegExp("^" + ele + ".*", "g").test(path)) {
          result = true
          result = true;
        }
      })
      });
      return result;
    },
    //设置路由值
@@ -92,17 +98,17 @@
    formatRoutes: function (aMenu = [], first) {
      // window.console.log('aMenu')
      // window.console.log(aMenu)
      const aRouter = []
      const aRouter = [];
      // 获取到全局配置中的 props
      const propsConfig = this.$website.menu.props;
      // 设置 props默认值 作用就是将字段设置成配置的
      const propsDefault = {
        label: propsConfig.label || 'name',
        path: propsConfig.path || 'path',
        icon: propsConfig.icon || 'icon',
        children: propsConfig.children || 'children',
        meta: propsConfig.meta || 'meta',
      }
        label: propsConfig.label || "name",
        path: propsConfig.path || "path",
        icon: propsConfig.icon || "icon",
        children: propsConfig.children || "children",
        meta: propsConfig.meta || "meta",
      };
      // 如果没有权限菜单就结束
      if (aMenu.length === 0) return;
      // 开始处理menu
@@ -113,25 +119,28 @@
        let path = (() => {
            if (first) {
              // 将 '/index' 替换为 ''
              return oMenu[propsDefault.path].replace('/index', '')
              return oMenu[propsDefault.path].replace("/index", "");
            } else {
              return oMenu[propsDefault.path]
              return oMenu[propsDefault.path];
            }
          })(),
          //特殊处理组件 执行完这个 component 也就是精确到具体的文件了  views文件夹下面就是具体的页面代码
          component = 'views' + oMenu.path,
          component = "views" + oMenu.path,
          name = oMenu[propsDefault.label],
          icon = oMenu[propsDefault.icon],
          children = oMenu[propsDefault.children],
          meta = oMenu[propsDefault.meta] || {};
          // meta中 keepalive 的处理
        meta = Object.assign(meta, (function () {
        meta = Object.assign(
          meta,
          (function () {
          if (option.keepAlive === true) {
            return {
              keepAlive: true
                keepAlive: true,
              };
            }
          }
        })());
          })()
        );
        //是否有子路由
        const isChild = children.length !== 0;
        const oRouter = {
@@ -139,15 +148,15 @@
          component(resolve) {
            // 判断是否为首路由
            if (first) {
              require(['../page/index'], resolve)
              return
              require(["../page/index"], resolve);
              return;
              // 判断是否为多层路由
            } else if (isChild && !first) {
              require(['../page/index/layout'], resolve)
              return
              require(["../page/index/layout"], resolve);
              return;
              // 判断是否为最终的页面视图
            } else {
              require([`../${component}.vue`], resolve)
              require([`../${component}.vue`], resolve);
            }
          },
          name: name,
@@ -155,45 +164,49 @@
          meta: meta,
          redirect: (() => {
            // 第一次进来但是没有子路由的 需要添加redirect
            if (!isChild && first && !isURL(path)) return `${path}/index`
            else return '';
            if (!isChild && first && !isURL(path)) return `${path}/index`;
            else return "";
          })(),
          // 整理子路由的route 配置
          // 处理是否为一级路由
          children: !isChild ? (() => {
          children: !isChild
            ? (() => {
            if (first) {
              // 这里的isURL判断,因为这个网站有使用 iframe。所以需要判断是否为网页链接
              if (!isURL(path)) oMenu[propsDefault.path] = `${path}/index`;
              return [{
                  return [
                    {
                component(resolve) {
                  require([`../${component}.vue`], resolve)
                        require([`../${component}.vue`], resolve);
                },
                icon: icon,
                name: name,
                meta: meta,
                path: 'index'
              }]
                      path: "index",
                    },
                  ];
            }
            return [];
          })() : (() => {
              })()
            : (() => {
            /**
             * 这里是重点,当有子路由的时候 会再去执行 formatRoutes 方法,然后又会有一个新的 aMenu for循环。
             * 最后返回的是一个数组 aRouter 这个数组就会作为 childen的值被 return
            */
            return this.formatRoutes(children, false)
          })()
        }
        aRouter.push(oRouter)
                return this.formatRoutes(children, false);
              })(),
        };
        aRouter.push(oRouter);
      }
      // for循环结束
      // 这个first 卡的其实就是首路由
      if (first) {
        this.safe.$router.addRoutes(aRouter)
        this.safe.$router.addRoutes(aRouter);
      } else {
        // 这里返回的是子组件
        return aRouter
        return aRouter;
      }
    }
  }
}
    },
  };
};
export default RouterPlugin;
src/router/page/index.js
@@ -1,81 +1,102 @@
import Layout from '@/page/index/'
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-12-14 17:10:00
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-01-19 11:40:51
 * @FilePath: \jczz_web\src\router\page\index.js
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
 */
import Layout from "@/page/index/";
export default [{
  path: '/login',
  name: '登录页',
export default [
  {
    path: "/login",
    name: "登录页",
  component: () =>
    import( /* webpackChunkName: "page" */ '@/page/login/index'),
      import(/* webpackChunkName: "page" */ "@/page/login/index"),
  meta: {
    keepAlive: true,
    isTab: false,
    isAuth: false
  }
      isAuth: false,
    },
},
  {
    path: '/lock',
    name: '锁屏页',
    path: "/tenementLogin",
    name: "登录页",
    component: () =>
      import( /* webpackChunkName: "page" */ '@/page/lock/index'),
      import(/* webpackChunkName: "page" */ "@/page/login/tenement.vue"),
    meta: {
      keepAlive: true,
      isTab: false,
      isAuth: false
    }
      isAuth: false,
    },
  },
  {
    path: '/404',
    component: () =>
      import( /* webpackChunkName: "page" */ '@/components/error-page/404'),
    name: '404',
    path: "/lock",
    name: "锁屏页",
    component: () => import(/* webpackChunkName: "page" */ "@/page/lock/index"),
    meta: {
      keepAlive: true,
      isTab: false,
      isAuth: false
    }
      isAuth: false,
    },
  },
  {
    path: '/403',
    path: "/404",
    component: () =>
      import( /* webpackChunkName: "page" */ '@/components/error-page/403'),
    name: '403',
      import(/* webpackChunkName: "page" */ "@/components/error-page/404"),
    name: "404",
    meta: {
      keepAlive: true,
      isTab: false,
      isAuth: false
    }
      isAuth: false,
    },
  },
  {
    path: '/500',
    path: "/403",
    component: () =>
      import( /* webpackChunkName: "page" */ '@/components/error-page/500'),
    name: '500',
      import(/* webpackChunkName: "page" */ "@/components/error-page/403"),
    name: "403",
    meta: {
      keepAlive: true,
      isTab: false,
      isAuth: false
    }
      isAuth: false,
    },
  },
  {
    path: '/',
    name: '主页',
    redirect: '/wel'
    path: "/500",
    component: () =>
      import(/* webpackChunkName: "page" */ "@/components/error-page/500"),
    name: "500",
    meta: {
      keepAlive: true,
      isTab: false,
      isAuth: false,
    },
  },
  {
    path: '/myiframe',
    path: "/",
    name: "主页",
    redirect: "/wel",
  },
  {
    path: "/myiframe",
    component: Layout,
    redirect: '/myiframe',
    children: [{
    redirect: "/myiframe",
    children: [
      {
      path: ":routerPath",
      name: 'iframe',
        name: "iframe",
      component: () =>
        import( /* webpackChunkName: "page" */ '@/components/iframe/main'),
      props: true
    }]
          import(/* webpackChunkName: "page" */ "@/components/iframe/main"),
        props: true,
      },
    ],
  },
  {
    path: '*',
    redirect: '/404'
  }
]
    path: "*",
    redirect: "/404",
  },
];
src/store/getters.js
@@ -1,29 +1,40 @@
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-12-14 17:10:00
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-01-19 15:58:57
 * @FilePath: \jczz_web\src\store\getters.js
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
 */
const getters = {
  tag: state => state.tags.tag,
  language: state => state.common.language,
  website: state => state.common.website,
  userInfo: state => state.user.userInfo,
  colorName: state => state.common.colorName,
  themeName: state => state.common.themeName,
  isShade: state => state.common.isShade,
  isCollapse: state => state.common.isCollapse,
  keyCollapse: (state, getters) => getters.screen > 1 ? getters.isCollapse : false,
  screen: state => state.common.screen,
  isLock: state => state.common.isLock,
  isFullScren: state => state.common.isFullScren,
  isMenu: state => state.common.isMenu,
  lockPasswd: state => state.common.lockPasswd,
  tagList: state => state.tags.tagList,
  tagWel: state => state.tags.tagWel,
  token: state => state.user.token,
  roles: state => state.user.roles,
  permission: state => state.user.permission,
  menu: state => state.user.menu,
  menuId: state => state.user.menuId,
  menuAll: state => state.user.menuAll,
  logsList: state => state.logs.logsList,
  logsLen: state => state.logs.logsList.length || 0,
  tag: (state) => state.tags.tag,
  language: (state) => state.common.language,
  website: (state) => state.common.website,
  userInfo: (state) => state.user.userInfo,
  colorName: (state) => state.common.colorName,
  themeName: (state) => state.common.themeName,
  isShade: (state) => state.common.isShade,
  isCollapse: (state) => state.common.isCollapse,
  keyCollapse: (state, getters) =>
    getters.screen > 1 ? getters.isCollapse : false,
  screen: (state) => state.common.screen,
  isLock: (state) => state.common.isLock,
  isFullScren: (state) => state.common.isFullScren,
  isMenu: (state) => state.common.isMenu,
  lockPasswd: (state) => state.common.lockPasswd,
  tagList: (state) => state.tags.tagList,
  tagWel: (state) => state.tags.tagWel,
  token: (state) => state.user.token,
  roles: (state) => state.user.roles,
  permission: (state) => state.user.permission,
  menu: (state) => state.user.menu,
  menuId: (state) => state.user.menuId,
  menuAll: (state) => state.user.menuAll,
  logsList: (state) => state.logs.logsList,
  logsLen: (state) => state.logs.logsList.length || 0,
  logsFlag: (state, getters) => getters.logsLen === 0,
  flowRoutes: state => state.dict.flowRoutes,
}
export default getters
  flowRoutes: (state) => state.dict.flowRoutes,
};
export default getters;
src/store/modules/common.js
@@ -1,20 +1,25 @@
import {
  setStore,
  getStore,
  removeStore
} from '@/util/store'
import website from '@/config/website'
/*
 * @Author: shuishen 1109946754@qq.com
 * @Date: 2023-12-14 17:10:00
 * @LastEditors: shuishen 1109946754@qq.com
 * @LastEditTime: 2024-01-19 16:43:29
 * @FilePath: \jczz_web\src\store\modules\common.js
 * @Description:
 *
 * Copyright (c) 2024 by shuishen, All Rights Reserved.
 */
import { setStore, getStore, removeStore } from "@/util/store";
import website from "@/config/website";
const common = {
  state: {
    language: getStore({name: 'language'}) || 'zh',
    language: getStore({ name: "language" }) || "zh",
    isCollapse: false,
    isFullScren: false,
    isMenu: true,
    isShade: false,
    screen: -1,
    isLock: getStore({name: 'isLock'}) || false,
    isLock: getStore({ name: "isLock" }) || false,
    showTag: true,
    showDebug: true,
    showCollapse: true,
@@ -24,18 +29,18 @@
    showTheme: true,
    showMenu: true,
    showColor: true,
    colorName: getStore({name: 'colorName'}) || '#409EFF',
    themeName: 'theme-white',
    lockPasswd: getStore({name: 'lockPasswd'}) || '',
    colorName: getStore({ name: "colorName" }) || "#409EFF",
    themeName: "theme-white",
    lockPasswd: getStore({ name: "lockPasswd" }) || "",
    website: website,
  },
  mutations: {
    SET_LANGUAGE: (state, language) => {
      state.language = language
      state.language = language;
      setStore({
        name: 'language',
        content: state.language
      })
        name: "language",
        content: state.language,
      });
    },
    SET_SHADE: (state, active) => {
      state.isShade = active;
@@ -52,10 +57,10 @@
    SET_LOCK: (state) => {
      state.isLock = true;
      setStore({
        name: 'isLock',
        name: "isLock",
        content: state.isLock,
        type: 'session'
      })
        type: "session",
      });
    },
    SET_SCREEN: (state, screen) => {
      state.screen = screen;
@@ -63,37 +68,37 @@
    SET_COLOR_NAME: (state, colorName) => {
      state.colorName = colorName;
      setStore({
        name: 'colorName',
        name: "colorName",
        content: state.colorName,
      })
      });
    },
    SET_THEME_NAME: (state, themeName) => {
      state.themeName = themeName;
      setStore({
        name: 'themeName',
        name: "themeName",
        content: state.themeName,
      })
      });
    },
    SET_LOCK_PASSWD: (state, lockPasswd) => {
      state.lockPasswd = lockPasswd;
      setStore({
        name: 'lockPasswd',
        name: "lockPasswd",
        content: state.lockPasswd,
        type: 'session'
      })
        type: "session",
      });
    },
    CLEAR_LOCK: (state) => {
      state.isLock = false;
      state.lockPasswd = '';
      state.lockPasswd = "";
      removeStore({
        name: 'lockPasswd',
        type: 'session'
        name: "lockPasswd",
        type: "session",
      });
      removeStore({
        name: 'isLock',
        type: 'session'
        name: "isLock",
        type: "session",
      });
    },
  }
}
export default common
  },
};
export default common;
src/views/authority/role.vue
@@ -1,50 +1,24 @@
<template>
  <basic-container>
    <avue-crud :option="option"
               :table-loading="loading"
               :data="data"
               ref="crud"
               v-model="form"
               :permission="permissionList"
               :before-open="beforeOpen"
               @row-del="rowDel"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
        <avue-crud :option="option" :table-loading="loading" :data="data" ref="crud" v-model="form"
            :permission="permissionList" :before-open="beforeOpen" @row-del="rowDel" @row-update="rowUpdate"
            @row-save="rowSave" @search-change="searchChange" @search-reset="searchReset"
            @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
            @refresh-change="refreshChange" @on-load="onLoad">
      <template slot="menuLeft">
        <el-button type="danger"
                   size="small"
                   icon="el-icon-delete"
                   v-if="permission.role_delete"
                   plain
                <el-button type="danger" size="small" icon="el-icon-delete" v-if="permission.role_delete" plain
                   @click="handleDelete">删 除
        </el-button>
        <el-button size="small"
                   icon="el-icon-setting"
                   @click="handleRole"
                   v-if="userInfo.role_name.includes('admin')"
                   plain>权限设置
                <el-button size="small" icon="el-icon-setting" @click="handleRole"
                    v-if="userInfo.role_name.includes('admin')" plain>权限设置
        </el-button>
      </template>
    </avue-crud>
    <el-dialog title="角色权限配置"
               append-to-body
               :visible.sync="box"
               width="345px">
        <el-dialog title="角色权限配置" append-to-body :visible.sync="box" width="345px">
      <el-tabs type="border-card">
        <el-tab-pane label="权限">
          <el-tree :data="menuGrantList"
                   show-checkbox
                   node-key="id"
                   ref="treeMenu"
                   :default-checked-keys="menuTreeObj"
                   :props="props">
                    <el-tree :data="menuGrantList" show-checkbox node-key="id" ref="treeMenu"
                        :default-checked-keys="menuTreeObj" :props="props">
          </el-tree>
        </el-tab-pane>
        <!-- <el-tab-pane label="数据权限">
@@ -67,20 +41,18 @@
        </el-tab-pane> -->
      </el-tabs>
      <span slot="footer"
            class="dialog-footer">
            <span slot="footer" class="dialog-footer">
        <el-button @click="box = false">取 消</el-button>
        <el-button type="primary"
                   @click="submit">确 定</el-button>
                <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
  </basic-container>
</template>
<script>
  import {add, getList, getRoleList, getRole, getRoleTreeById, grant, grantTree, remove, update} from "@/api/system/role";
  import {mapGetters} from "vuex";
  import website from '@/config/website';
import { add, getList, getRoleList, getRole, getRoleTreeById, grant, grantTree, remove, update } from "@/api/system/role"
import { mapGetters } from "vuex"
import website from '@/config/website'
  export default {
    data() {
@@ -107,6 +79,7 @@
          total: 0
        },
        option: {
                lazy: true,
          tip: false,
          simplePage: true,
          searchShow: true,
@@ -169,12 +142,14 @@
            {
              label: "上级角色",
              prop: "parentId",
              dicData: [],
              type: "tree",
              hide: true,
                        dicData: [],
                        addDisabled: false,
                        // hide: true,
              span: 24,
              props: {
                label: "title"
                            label: "title",
                            value: 'id'
              },
              rules: [
                {
@@ -200,7 +175,7 @@
          ]
        },
        data: []
      };
        }
    },
    computed: {
      ...mapGetters(["userInfo", "permission"]),
@@ -210,69 +185,69 @@
          viewBtn: this.vaildData(this.permission.role_view, false),
          delBtn: this.vaildData(this.permission.role_delete, false),
          editBtn: this.vaildData(this.permission.role_edit, false)
        };
            }
      },
      ids() {
        let ids = [];
            let ids = []
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
                ids.push(ele.id)
        });
        return ids.join(",");
            })
            return ids.join(",")
      },
      idsArray() {
        let ids = [];
            let ids = []
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids;
                ids.push(ele.id)
            })
            return ids
      }
    },
    methods: {
      initData(roleId){
        getRoleTreeById(roleId).then(res => {
          const column = this.findObject(this.option.column, "parentId");
          column.dicData = res.data.data;
        });
                const column = this.findObject(this.option.column, "parentId")
                column.dicData = res.data.data
            })
      },
      submit() {
        const menuList = this.$refs.treeMenu.getCheckedKeys();
        const dataScopeList = [];
        const apiScopeList = [];
            const menuList = this.$refs.treeMenu.getCheckedKeys()
            const dataScopeList = []
            const apiScopeList = []
        grant(this.idsArray, menuList, dataScopeList, apiScopeList).then(() => {
          this.box = false;
                this.box = false
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          this.onLoad(this.page);
        });
                })
                this.onLoad(this.page)
            })
      },
      rowSave(row, done, loading) {
        add(row).then(() => {
          this.onLoad(this.page);
                this.onLoad(this.page)
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
                })
                done()
        }, error => {
          window.console.log(error);
          loading();
        });
                window.console.log(error)
                loading()
            })
      },
      rowUpdate(row, index, done, loading) {
        update(row).then(() => {
          this.onLoad(this.page);
                this.onLoad(this.page)
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
                })
                done()
        }, error => {
          window.console.log(error);
          loading();
        });
                window.console.log(error)
                loading()
            })
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
@@ -281,65 +256,65 @@
          type: "warning"
        })
          .then(() => {
            return remove(row.id);
                    return remove(row.id)
          })
          .then(() => {
            this.onLoad(this.page);
                    this.onLoad(this.page)
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
                    })
                })
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
            this.query = {}
            this.onLoad(this.page)
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
            this.query = params
            this.page.currentPage = 1
            this.onLoad(this.page, params)
            done()
      },
      selectionChange(list) {
        this.selectionList = list;
            this.selectionList = list
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
            this.selectionList = []
            this.$refs.crud.toggleSelection()
      },
      beforeOpen(done, type) {
        if (["add", "edit"].includes(type)) {
          this.initData(this.form.id);
                this.initData(this.form.id)
        }
        done();
            done()
      },
      handleRole() {
        if (this.selectionList.length !== 1) {
          this.$message.warning("只能选择一条数据");
          return;
                this.$message.warning("只能选择一条数据")
                return
        }
        this.menuTreeObj = [];
        this.dataScopeTreeObj = [];
        this.apiScopeTreeObj = [];
            this.menuTreeObj = []
            this.dataScopeTreeObj = []
            this.apiScopeTreeObj = []
        grantTree()
          .then(res => {
            this.menuGrantList = res.data.data.menu;
                    this.menuGrantList = res.data.data.menu
            // this.dataScopeGrantList = res.data.data.dataScope;
            // this.apiScopeGrantList = res.data.data.apiScope;
            getRole(this.ids).then(res => {
              this.menuTreeObj = res.data.data.menu;
                        this.menuTreeObj = res.data.data.menu
              // this.dataScopeTreeObj = res.data.data.dataScope;
              // this.apiScopeTreeObj = res.data.data.apiScope;
              this.box = true;
            });
          });
                        this.box = true
                    })
                })
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
                this.$message.warning("请选择至少一条数据")
                return
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
@@ -347,34 +322,34 @@
          type: "warning"
        })
          .then(() => {
            return remove(this.ids);
                    return remove(this.ids)
          })
          .then(() => {
            this.onLoad(this.page);
                    this.onLoad(this.page)
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
                    })
                    this.$refs.crud.toggleSelection()
                })
      },
      currentChange(currentPage) {
        this.page.currentPage = currentPage;
            this.page.currentPage = currentPage
      },
      sizeChange(pageSize) {
        this.page.pageSize = pageSize;
            this.page.pageSize = pageSize
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
            this.onLoad(this.page, this.query)
      },
      onLoad(page, params = {}) {
        this.loading = true;
            this.loading = true
        getRoleList(Object.assign(params, this.query)).then(res => {
          this.data = res.data.data;
          this.loading = false;
          this.selectionClear();
        });
                this.data = res.data.data
                this.loading = false
                this.selectionClear()
            })
      }
    }
  };
}
</script>
src/views/wel/index.vue
@@ -1,8 +1,8 @@
<template>
    <div id="homeL">
        <div class="homeL-up">
            <span class="h1">基层智治综合协同平台</span>
            <span class="h2">Grassroots intelligent governance integrated cooperation platform</span>
            <span class="h1">{{ webTitle }}</span>
            <span class="h2"></span>
        </div>
        <div class="homeL-bar">
            <div class="outS" @click="down1">
@@ -35,10 +35,13 @@
export default {
    data () {
        return {
            webTitle: getStore({ name: "webTitle" }),
            webType: getStore({ name: "webType" }),
            a: 1,
            globalUserInfo: getStore({ name: "userInfo" }),
        }
    },
    methods: {
        down1 () {
            this.$router.push({ path: "/userHouse/houseHoldList" })