# 常见问题

::: tip

列举了一些常见的问题。有问题可以先来这里寻找，如果没有可以在 [issue](http://192.168.9.192/eci-frontend/base-framework-docs/-/issues) 提。

:::

## 前言

遇到问题,可以先从以下几个方面查找

1. 对应模块的 GitLab 仓库 [issue](http://192.168.9.192/eci-frontend/base-framework-docs/-/issues) 搜索
2. 从[google](https://www.google.com)搜索问题
3. 从[百度](https://www.百度.com)搜索问题
4. 在下面列表找不到问题可以到 issue 提问 [issues](http://192.168.9.192/eci-frontend/base-framework-docs/-/issues)

## 关于缓存更新问题

base-framework 的项目配置默认是缓存在 `localStorage` 内，所以版本更新后可能有些配置没改变。

解决方式是每次更新代码的时候修改 `package.json` 内的 `version` 版本号. 因为 localStorage 的 key 是根据版本号来的。所以更新后版本不同前面的配置会失效。重新登录即可

`PROJECT_NAME__DEVELOPMENT__2.0.3__COMMON__LOCAL__KEY__` key 的组成是 [项目名]+[开发环境]+[版本号]+[key]

## 关于修改配置文件的问题

当修改 `.env` 等环境文件及 `vite.config.ts` 文件时，vite 会自动重启服务。

自动重启有几率出现问题，请重新运行项目即可解决.

## esbuild 模式下开启 LEGACY 打包失败

如果将  build.minify 设置为 'esbuild'，且不能启用 LEGACY，否则打包将会报错，两者选其一即可打包。

## 添加菜单后没显示

菜单必须和路由匹配才会显示在界面上，所以得确保菜单和对应的路由存在即可显示.

## 本地运行报错

由于 vite 在本地没有转换代码，且代码中用到了可选链等比较新的语法。所以本地开发需要使用版本较高的浏览器(`Chrome 85+`)进行开发

## tab 页切换后页面空白

这是由于开启了路由切换动画,且对应的页面组件存在多个根节点导致的，在页面最外层添加`<div></div>`即可

**错误示例**

```vue
<template>
  <!-- 注释也算一个节点 -->
  <h1>text h1</h1>
  <h2>text h2</h2>
</template>
```

**正确示例**

```vue
<template>
  <div>
    <h1>text h1</h1>
    <h2>text h2</h2>
  </div>
</template>
```

::: tip 提示

- 如果想使用多个根标签，可以禁用路由切换动画
- template 下面的根注释节点也算一个节点

:::

## 组件命名问题

目前在 vite+vue3.0.5 版本中，如果组件命名携带关键字，则可能会导致内存溢出。例如 `ImportExcel` excel 导入组件。

## 我的代码本地开发可以，打包就不行了

目前发现这个原因可能有以下，可以从以下原因来排查，如果还有别的可能，可以提交 pr 来告诉我

1. 使用了 ctx 这个变量，ctx 本身未暴露出在实例类型内，尤大也是说了不要用这个属性。这个属性只是用于内部使用。

```ts
import { getCurrentInstance } from 'vue';
getCurrentInstance().ctx.xxxx;
```

## safari 问题

目前在 safari 上面本地开发运行样式会有问题，还未找到原因，有知道的也可以告诉我。

## 环境问题

如果出现依赖安装报错，启动报错等。先检查电脑环境有没有安装齐全。

- Node 版本必须大于`12.0.0`不支持 `13`， 推荐 16 版本。
- Git
- Pnpm 最新版

## 依赖安装问题

- 如果依赖安装不了或者启动报错可以先尝试 删除 `pnpm-lock.yaml` 和 `node_modules`，然后重新运行 `pnpm install`
- 如果依赖安装不了或者报错，可以尝试切换手机热点来进行依赖安装。
- 如果还是不行，可以自行配置国内镜像安装。
- 也可以在项目根目录创建 `.npmrc` 文件，内容如下

```bash
# .npmrc
registry = https://registry.npm.taobao.org
```

然后重新执行`pnpm run reinstall`等待安装完成即可

## 打包文件过大

- 首先，starter模板由于引用了比较多的库文件，所以打包会比较大。可以删减不必要的依赖包。

- 其次建议开启 gzip，使用之后体积会只有原先 1/3 左右。

gzip 可以由服务器直接开启。如果是这样，前端不需要构建 `.gz` 格式的文件

如果前端构建了 `.gz` 文件，以 nginx 为例，nginx 需要开启 `gzip_static: on` 这个选项。

- 开启 gzip 的同时还可以同时开启 `brotli`，比 gzip 更好的压缩。两者可以共存

**注意**

- gzip_static: 这个模块需要 nginx 另外安装，默认的 nginx 没有安装这个模块。

- 开启 `brotli` 也需要 nginx 另外安装模块

## 运行错误

如果出现类似以下错误，请检查项目全路径（包含所有父级路径）不能出现中文、日文、韩文。否则将会出现路径访问 404 导致以下问题

```ts
[vite] Failed to resolve module import "ant-design-vue/dist/antd.css-vben-adminode_modulesant-design-vuedistantd.css". (imported by /@/setup/ant-design-vue/index.ts)
```

## 控制台路由警告问题

如果看到控制台有如下警告，且页面**能正常打开** 可以忽略该警告。

后续 `vue-router` 可能会提供配置项来关闭警告

**2.6.1及以上版本已移除此警告**

```ts
[Vue Router warn]: No match found for location with path "xxxx"
```

## 启动报错

当出现以下错误信息时，请检查你的 nodejs 版本号是否符合要求

```bash
TypeError: str.matchAll is not a function
at Object.extractor (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:146:27)
at Extract (vue-vben-admin-main\node_modules@purge-icons\core\dist\index.js:173:54)

```

## 页面报错

当页面出现以下报错，是因为 /xxx 对应的路由组件内部出现了错误。

```ts
 Uncaught (in promise) Error: Couldn't resolve component "default" at "/xxx"

```

可以尝试从以下几点排查

1. 检查对应组件内部 import 的所有文件是否正确
2. 检查引入方式是否错误。

```ts
// 正确的
import { cloneDeep } from 'lodash-es';

// 报错
import _ from 'lodash-es';
```

3. 检查样式是否使用变量及有没有引入对应的变量文件
4. 检查代码明显的语法错误

这样就不会是使用的取值忘记 xxx.value 来进行数据获取

## 跨域问题

参考[跨域问题](../dep/cors)

## 接口请求问题

proxy 代理不成功，没有代理到实际地址？

代理只是服务请求代理，这个地址是不会变的。 原理可以简单的理解为，在本地启了一个服务，你先请求了本地的服务，本地的服务转发了你的请求到实际服务器。所以你在浏览器上看到的请求地址还是 `http://localhost:8000/xxx`。以服务端是否收到请求为准。

## 组件库问题

跟组件库相关的问题可以查看[常见问题](https://www.antdv.com/docs/vue/faq-cn)

## 动态调整菜单问题

菜单数据的值被存放在 `store/modules/permission` store 中, 你可以在这里进行修改

## 更灵活的菜单路由权限控制

你可以在 `store/modules/permission`下, 修改 `routeFilter` 方法来进行更灵活的菜单路由权限控制

```
 const routeFilter = (route: AppRouteRecordRaw) => {
    const { meta } = route;
    // 抽出角色
    const { roles } = meta || {};

    // 添加你的自定义逻辑来过滤路由和菜单
    if (xxx) {
      return false;
    }

    if (!roles) return true;
    // 进行角色权限判断
    return roleList.some((role) => roles.includes(role));
  };

```
