田源
2024-08-12 c7f555bb017d2c011c6cbe688208a82acaed3fa9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
import {validatenull} from "@/util/validate";
 
let RouterPlugin = function () {
  this.$router = null;
  this.$store = null;
 
};
RouterPlugin.install = function (vue, option = {}) {
  this.$router = option.router;
  this.$store = option.store;
  this.$vue = new vue({i18n: option.i18n});
 
  // 这个的作用是 为了检查出网页链接,因为本项目用到了 iframe
  function isURL(s) {
    if (s.includes('html')) return true;
    return /^http[s]?:\/\/.*/.test(s)
  }
 
  // 将参数处理为参数的形式拼接
  function objToform(obj) {
    let result = [];
    Object.keys(obj).forEach(ele => {
      result.push(`${ele}=${obj[ele]}`);
    })
    return result.join('&');
  }
 
  this.$router.$avueRouter = {
    //全局配置
    $website: this.$store.getters.website,
    group: '',
    meta: {},
    safe: this,
    // 设置标题
    setTitle: (title) => {
      const defaultTitle = this.$vue.$t('title');
      title = title ? `${title}-${defaultTitle}` : defaultTitle;
      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]
      }
      this.$store.commit('DEL_TAG', tag)
    },
    generateTitle: (title, key) => {
      if (!key) return title;
      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)
 
        return translatedTitle
      }
      return title
    },
    //处理路由
    getPath: function (params) {
      let {src} = params;
      let result = src || '/';
      if (isURL(src)) {
        result = `/myiframe/urlPath?${objToform(params)}`;
      }
      return result;
    },
    //正则处理路由
    vaildPath: function (list, path) {
      let result = false;
      list.forEach(ele => {
        if (new RegExp("^" + ele + ".*", "g").test(path)) {
          result = true
        }
 
      })
      return result;
    },
    //设置路由值
    getValue: function (route) {
      let value = "";
      if (route.query.src) {
        value = route.query.src;
      } else {
        value = route.path;
      }
      return value;
    },
    //动态路由
    // 路由是专门的一个接口获取
    /**
     * aMenu: 接受到的动态路由数据 menu的结构外层有父级path 里面有一个childen 记录页面的路由
     * first: 为了区分外界 调用formatRoutes 和 当前文件调用 formatRoutes
     */
    formatRoutes: function (aMenu = [], first) {
      const aRouter = []
      // 获取到全局配置中的 props
      const propsConfig = this.$website.menu.props;
      // 设置 props默认值 作用就是将字段设置成配置的
      const propsDefault = {
        label: propsConfig.label || 'name',
        path: 'code',
        code: 'code',
        pathValue: 'pathValue',
        icon: propsConfig.icon || 'icon',
        children: propsConfig.children || 'children',
        meta: propsConfig.meta || 'meta',
      }
      // 如果没有权限菜单就结束
      if (aMenu.length === 0) return;
      // 开始处理menu
      for (let i = 0; i < aMenu.length; i++) {
        // 取到当前要处理的一项
        const oMenu = aMenu[i];
        // 这一块的赋值 也就是取到返回的值
        let path = (() => {
          if (first) {
            // 将 '/index' 替换为 ''
            return oMenu[propsDefault.pathValue].replace('/index', '')
          } else {
            return oMenu[propsDefault.pathValue]
          }
        })();
        let code = (() => {
          return oMenu[propsDefault.code]
        })();
 
        let component = '';
        let parts = '';
 
        // 如果路径中存在 '?',则取问号前面部分给 parts
        if (path.includes('?')) {
          parts = path.split("?")[0];
        } else {
          parts = path; // 不存在 '?' 整条路径就是 parts
        }
        if(validatenull(parts)){
          parts='UI';
        }
        // 如果问号前面部分不在 ['ui', 'UI', 'base'] 中,则是自定义组件
        if (!['ui', 'UI', 'base','bs'].includes(parts) && parts.indexOf('views/')==-1) {
          component = `views/custom-ui/${parts}`;
        }else if (['UI', 'ui', 'base','bs'].includes(parts)) {
          // 如果问号前面等于 UI、ui 则为UI引擎
          component = 'views/base/UIContentViewer';
        }else{
          component = `${parts}`;
        }
 
        let name = oMenu[propsDefault.label],
          icon = oMenu[propsDefault.icon],
          children = oMenu[propsDefault.children],
          meta = oMenu[propsDefault.meta] || {};
        // meta中 keepalive 的处理
        meta = Object.assign(meta, (function () {
          if (option.keepAlive === true) {
            return {
              keepAlive: true
            }
          }
        })());
        //是否有子路由
        const isChild = children.length !== 0;
        const oRouter = {
          path: '/' + code,
          component(resolve) {
            // 判断是否为首路由
            if (first) {
              require(['../page/index'], resolve)
              return
              // 判断是否为多层路由
            } else if (isChild && !first) {
              require(['../page/index/layout'], resolve)
              return
              // 判断是否为最终的页面视图
            } else {
              require([`../${component}.vue`], resolve)
            }
          },
          name: name,
          icon: icon,
          meta: meta,
          redirect: (() => {
            // 第一次进来但是没有子路由的 需要添加redirect
            if (!isChild && first && !isURL(path)) return `${path}/index`
            else return '';
          })(),
          // 整理子路由的route 配置
          // 处理是否为一级路由
          children: !isChild ? (() => {
            if (first) {
              // 这里的isURL判断,因为这个网站有使用 iframe。所以需要判断是否为网页链接
              if (!isURL(path)) oMenu[propsDefault.pathValue] = `${path}/index`;
              return [{
                component(resolve) {
                  require([`../${component}.vue`], resolve)
                },
                icon: icon,
                name: name,
                meta: meta,
                path: 'index'
              }]
            }
            return [];
          })() : (() => {
            /**
             * 这里是重点,当有子路由的时候 会再去执行 formatRoutes 方法,然后又会有一个新的 aMenu for循环。
             * 最后返回的是一个数组 aRouter 这个数组就会作为 childen的值被 return
             */
            return this.formatRoutes(children, false)
          })()
        }
        aRouter.push(oRouter)
      }
      // for循环结束
      // 这个first 卡的其实就是首路由
      if (first) {
        this.safe.$router.addRoutes(aRouter)
      } else {
        // 这里返回的是子组件
        return aRouter
      }
    }
  }
}
export default RouterPlugin;