diff --git a/docs/.vuepress/configs/sidebar/zh.ts b/docs/.vuepress/configs/sidebar/zh.ts index 6622735d..28bf909c 100644 --- a/docs/.vuepress/configs/sidebar/zh.ts +++ b/docs/.vuepress/configs/sidebar/zh.ts @@ -15,6 +15,7 @@ export const zh: SidebarConfig = { text: '基础', children: [ '/zh/guide/directory-structure.md', + '/zh/guide/config.md', '/zh/guide/route.md', '/zh/guide/plugin.md', '/zh/guide/template.md', diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md new file mode 100644 index 00000000..69a031b1 --- /dev/null +++ b/docs/zh/guide/config.md @@ -0,0 +1,79 @@ +# 配置 + +`fes` 在 `.fes.js` 文件中添加项目基础配置。一份常见的配置示例如下: +```js +export default { + base: '/foo/', + publicPath: '/', + devServer: { + port: 8080 + } + mock: { + prefix: '/v2' + }, + proxy: { + '/v2': { + 'target': 'https://api.douban.com/', + 'changeOrigin': true, + }, + }, + layout: { + title: "Fes.js", + footer: 'Created by MumbelFe', + multiTabs: false, + menus: [{ + name: 'index' + }, { + name: 'onepiece' + }, { + name: 'store' + }, { + name: 'simpleList' + }] + } +} +``` + +## 配置文件 +可以新建 `.fes.local.js` 作为本地临时配置文件。这份配置会和 `.fes.js` 做 deep merge 后形成最终配置。 +```js +// .fes.js +export default { mock: false }; + +// .fes.local.js +export default { + mock: true, + dvServer: { port: 8080 } +}; +``` +最终的配置是: +```js +{ + mock: true, + devServer: { port: 8080 } +}; +``` +::: tip +`.fes.local.js` 仅在 fes dev 时有效。 + +`.fes.local.js` 是本地验证使用的临时配置,请将其添加到 `.gitignore`,务必不要提交到 git 仓库中。 + +`.fes.local.js` 配置的优先级最高,比 `FES_ENV` 指定的配置更高。 +::: + +## 多环境多份配置 +可以通过环境变量 `FES_ENV` 区分不同环境,来指定配置文件。 +```js + // .fes.js + export default { mock: false }; + + // .fes.local.js + export default { + mock: true, + dvServer: { port: 8080 } + }; +``` +根据指定的 `FES_ENV` 拿对应的配置,这份配置会和 `.fes.js` 做 deep merge 后形成最终配。 +::: tip +`FES_ENV` 指定的配置优先级高于 `.fes.js` 文件的配置 +::: \ No newline at end of file diff --git a/docs/zh/reference/config/README.md b/docs/zh/reference/config/README.md index 85d56734..45b53853 100644 --- a/docs/zh/reference/config/README.md +++ b/docs/zh/reference/config/README.md @@ -4,574 +4,281 @@ sidebar: auto # 配置 -VuePress 配置的参考文档,可以通过配置文件来设置这些配置。 VuePress 约定的配置文件为(按照优先顺序): +以下配置项通过字母排序。 -- 当前工作目录 `cwd` 下: - - `vuepress.config.ts` - - `vuepress.config.js` -- 源文件目录 `sourceDir` 下: - - `.vuepress/config.ts` - - `.vuepress/config.js` +## alias -你也可以通过 [命令行接口](./cli.md) 的 `--config` 选项来指定配置文件。 +- 类型: `object` +- 默认值: `{}` +- 详情: -## 站点配置 + 配置别名,对引用路径进行映射。 -### base +- 示例: +```js +export default { + alias: { + main: 'src/assets/styles/main' + } +} +``` +然后 `import('main')`,实际上是 `import('src/assets/styles/main')`。 + +## base - 类型: `string` - -- 默认值: `/` - -- 详情: - - 部署站点的基础路径。 - - 如果你想让你的网站部署到一个子路径下,你将需要设置它。它的值应当总是以斜杠开始,并以斜杠结束。举例来说,如果你想将你的网站部署到 `https://foo.github.io/bar/`,那么 `base` 应该被设置成 `"/bar/"`。 - - `base` 将会作为前缀自动地插入到所有以 `/` 开始的其他选项的链接中,所以你只需要指定一次。 - -- 参考: - - [指南 > 静态资源 > Base Helper](../guide/assets.md#base-helper) - - [指南 > 部署](../guide/deployment.md) - -### lang - -- 类型: `string` - -- 默认值: `en-US` - -- 详情: - - 站点的语言。 - - 它将会在最终渲染出的 HTML 中作为 `` 标签的 `lang` 属性。 - - 它可以设置在不同语言的 locales 中。 - -- 参考: - - [配置 > locales](#locales) - -### title - -- 类型: `string` - - 默认值: `''` +- 详情: -- 详情: - - 站点的标题。 - - 它将会作为所有页面标题的后缀,并且在默认主题的导航栏中显示。 - - 它可以设置在不同语言的 locales 中。 - -- 参考: - - [配置 > locales](#locales) - -### description - -- 类型: `string` + 设置路由前缀,通常用于部署到非根目录。比如你有路由 `/pageA`、`/pageB`,然后设置了 `base` 为 `/manage/`,那么就可以通过 `/manage/pageA`、`/manage/pageB` 访问到它们。 + +## cssLoader +- 类型: `object` - 默认值: `''` +- 详情: -- 详情: + 设置 [css-loader 配置项](https://github.com/webpack-contrib/css-loader#options)。 - 站点的描述。 - - 它将会在最终渲染出的 HTML 中作为 `` 标签的 `content` 属性。它会被每个页面的 Frontmatter 中的 `description` 字段覆盖。 - - 它可以设置在不同语言的 locales 中。 - -- 参考: - - [配置 > locales](#locales) - - [Frontmatter > description](./frontmatter.md#description) - -### head - -- 类型: `HeadConfig[]` +## copy +- 类型: `Array(string) || Array(object)` - 默认值: `[]` - - 详情: - 在最终渲染出的 HTML 的 `` 标签内加入的额外标签。 - - 你可以通过 `[tagName, { attrName: attrValue }, innerHTML?]` 的格式来添加标签。 - - 它可以设置在不同语言的 locales 中。 - + 设置要复制到输出目录的文件、文件夹。 + + 配置约定 `from-to` 规则, 其中 `from` 是相对于 `cwd` 的路径,`to` 是相对于输出路径的路径。 - 示例: - - 增加一个自定义的 favicon : - ```js -module.exports = { - head: [ - ['link', { rel: 'icon', href: '/logo.png' }] - ] +export default { + copy: { + from: '/src/assets/images', + to: 'assets/images' + } } ``` +上面示例中,实现了将 `cwd` 路径中的 `/src/assets/images` 文件夹,在编译完成后,`copy` 到输出路径下的 `assets/images` 文件夹。 - 渲染为: - -```html - - - -``` - -- 参考: - - [配置 > locales](#locales) - - [Frontmatter > head](./frontmatter.md#head) - -### locales - -- 类型: `{ [path: string]: Partial }` +## define +- 类型: `object` - 默认值: `{}` - - 详情: - - 多语言支持的各个语言 locales 。 - - 可以使用的字段有: - - - [lang](#lang) - - [title](#title) - - [description](#description) - - [head](#head) - -- 参考: - - [指南 > I18n](../guide/i18n.md) - -## 主题配置 - -### theme - -- 类型: `string` - -- 默认值: `'@vuepress/default'` - -- 详情: - - 你想要使用的主题的名称或绝对路径。 - - 这个选项可以接收主题名称、主题简称或主题的绝对路径。 - + + 用于提供给代码中可用的变量。 - 示例: - ```js -module.exports = { - theme: 'vuepress-theme-foo', - theme: 'bar', - theme: '/path/to/local/theme', +export default { + define: { + __DEV__: 'development' + } } ``` +然后你代码里写 `console.log(__DEV__)`,会被编译成 `console.log('development')`。 -- 参考: - - [指南 > 主题](../guide/theme.md) - -### themeConfig - -- 类型: `ThemeConfig` +## devServer +- 类型: `object` - 默认值: `{}` - - 详情: + + 配置开发服务器。支持以下子配置项: - 为当前使用的主题提供的配置项。具体的配置项取决于你使用的主题。 + - port,端口号,默认 `8000` + - host,默认 `localhost` + - https,是否启用 https server,同时也会开启 HTTP/2 -- 参考: - - [默认主题 > 配置](./default-theme/config.md) + 启用 port 和 host 也可以通过环境变量 `PORT` 和 `HOST` 临时指定。 -## 打包工具配置 - -### bundler +## devtool - 类型: `string` - -- 默认值: `'@vuepress/webpack'` - +- 默认值: `cheap-module-source-map` in dev, `undefined` in build - 详情: - 你想要使用的打包工具的名称。 + 用户配置 sourcemap 类型。详见 [ webpack#devtool 配置](https://webpack.js.org/configuration/devtool/#devtool)。 - 可以使用打包工具名称的简称。 +## extraPostCSSPlugins -- 参考: - - [指南 > 打包工具](../guide/bundler.md) +- 类型: `array` +- 默认值: `[]` +- 详情: -### bundlerConfig + 设置额外的 [postcss 插件](https://github.com/postcss/postcss/blob/master/docs/plugins.md)。 -- 类型: `BundlerConfig` - -- 默认值: `{}` - -- 详情: - - 为当前使用的打包工具提供的配置项。具体的配置项取决于你使用的打包工具。 - -## 目录配置 - -### dest - -- 类型: `string` - -- 默认值: `` `${sourceDir}/.vuepress/dist` `` - -- 详情: - - 指定 `vuepress build` 命令的输出目录。 - -### temp - -- 类型: `string` - -- 默认值: `` `${sourceDir}/.vuepress/.temp` `` - -- 详情: - - 指定临时文件目录。 - -### cache - -- 类型: `string` - -- 默认值: `` `${sourceDir}/.vuepress/.cache` `` - -- 详情: - - 指定缓存目录。 - -### public - -- 类型: `string` - -- 默认值: `` `${sourceDir}/.vuepress/public` `` - -- 详情: - - 指定 Public 文件目录。 - -- 参考: - - [指南 > 静态资源 > Public 文件](../guide/assets.md#public-文件) - -## Markdown 配置 - -### markdown - -- 类型: `MarkdownOptions` - -- 默认值: `{}` - -- 详情: - - 对 VuePress 内置的 Markdown 语法扩展进行配置。 - -- 参考: - - [指南 > Markdown > 语法扩展](../guide/markdown.md#语法扩展) - -#### markdown.anchor - -- 类型: `AnchorPluginOptions | false` - -- 详情: - - [markdown-it-anchor](https://github.com/valeriangalliat/markdown-it-anchor) 的配置项。 - - 设置为 `false` 可以禁用该插件。 - -- 参考: - - [指南 > Markdown > 语法扩展 > 标题锚点](../guide/markdown.md#标题锚点) - -#### markdown.assets - -- 类型: `AssetsPluginOptions | false` - -- 详情: - - VuePress 内置的 markdown-it assets 插件的配置项。 - - 设置为 `false` 可以禁用该插件。 - -::: danger -除非你了解它的用途,否则你不应该设置该配置项。 -::: - -#### markdown.code - -- 类型: `CodePluginOptions | false` - -- 详情: - - VuePress 内置的 markdown-it code 插件的配置项。 - - 设置为 `false` 可以禁用该插件。 - -- 参考: - - [指南 > Markdown > 语法扩展 > 代码块](../guide/markdown.md#代码块) - -##### markdown.code.highlight - -- 类型: `boolean` - -- 默认值: `true` - -- 详情: - - 是否启用代码块语法高亮。 - - 如果你想在客户端进行语法高翔,你可以禁用该配置项。比如使用 [Prismjs](https://prismjs.com/) 或 [highlight.js](https://highlightjs.org/) 。 - -- 参考: - - [指南 > Markdown > 语法扩展 > 代码块 > 语法高亮](../guide/markdown.md#语法高亮) - -##### markdown.code.highlightLines - -- 类型: `boolean` - -- 默认值: `true` - -- 详情: - - 是否启用代码块行高亮。 - -- 参考: - - [指南 > Markdown > 语法扩展 > 代码块 > 行高亮](../guide/markdown.md#行高亮) - -##### markdown.code.lineNumbers - -- 类型: `boolean` - -- 默认值: `true` - -- 详情: - - 是否启用代码块行号。 - -- 参考: - - [指南 > Markdown > 语法扩展 > 代码块 > 行号](../guide/markdown.md#行号) - -##### markdown.code.preWrapper - -- 类型: `boolean` - -- 默认值: `true` - -- 详情: - - 是否在 `
` 标签外额外包裹一层。
-
-  `highlightLines` 和 `lineNumbers` 依赖于这个额外的包裹层。这换句话说,如果你禁用了 `preWrapper` ,那么行高亮和行号也会被同时禁用。
-
-  如果你想要在客户端来实现这些功能时,可以禁用该配置项。比如使用 [Prismjs Line Highlight](https://prismjs.com/plugins/line-highlight/) 或者 [Prismjs Line Numbers](https://prismjs.com/plugins/line-numbers/)。
-
-##### markdown.code.vPre
-
-- 类型: `boolean`
-
-- 默认值: `true`
-
-- 详情:
-
-  是否在 `
` 标签上添加 `v-pre` 指令。
-
-- 参考:
-  - [指南 > Markdown > 语法扩展 > 代码块 > 添加 v-pre](../guide/markdown.md#添加-v-pre)
-
-#### markdown.customComponent
-
-- 类型: `undefined | false`
-
-- 详情:
-
-  VuePress 内置的 markdown-it custom-component 插件的配置项。
-
-  设置为 `false` 可以禁用该插件。
-
-::: danger
-除非你了解它的用途,否则你不应该设置该配置项。
-:::
-
-#### markdown.emoji
-
-- 类型: `EmojiPluginOptions | false`
-
-- 详情:
-
-  [markdown-it-emoji](https://github.com/markdown-it/markdown-it-emoji) 的配置项。
-
-  设置为 `false` 可以禁用该插件。
-
-- 参考:
-  - [指南 > Markdown > 语法扩展 > Emoji](../guide/markdown.md#emoji)
-
-#### markdown.extractHeaders
-
-- 类型: `ExtractHeadersPluginOptions | false`
-
-- 详情:
-
-  VuePress 内置的 markdown-it extract-headers 插件的配置项。
-
-  它将会把页面的标题提取到 Page Data 中,可以用于生成侧边栏、目录等。比如当前页面的侧边栏,就是由这个插件提取出的标题来自动生成的。
-
-  设置为 `false` 可以禁用该插件。
-
-#### markdown.hoistTags
-
-- 类型: `HoistTagsPluginOptions | false`
-
-- 详情:
-
-  VuePress 内置的 markdown-it hoist-tags 插件的配置项。
-
-  它将会把你的 Markdown 中特定的 HTML 标签提升到 SFC 的顶层。默认情况下,只有 `
+
+```
+## API
+### get
+* `get(name: string)` 获取指定名字的枚举
+
+* `get(name: string, key: string)` 获取指定名字及键枚举默认值
+
+* `get(name: string, opt: {extend: Array})` 获取指定名字的自定义格式枚举,[查看extend配置](#extend配置)
+
+* `get(name: string, key: string, opt: {dir: string})` 获取指定名字及键枚举[dir规则](#dir规则)的值
+
+```js
+get('status')
+get('status', '1')
+get('status', {
+    extend: [
+        {
+            key: 'name',
+            dir: 'value',
+        },
+        {
+            key: 'disabled',
+            transfer: item => item === '0'
+        }
+    ]
+})
+get('status', '1', {dir: 'value'})
+```
+
+### push
+动态添加枚举,重复添加会覆盖
+* `push(name: string, _enum: Array)`
+* `push(name: string, _enum: Array, opt?: Object)`
+    * opt.keyName 指定key的取值属性,默认是key
+    * opt.valueName 指定value的取值属性
+
+枚举项为数组,枚举项的[0]解析为key,枚举项的[1]解析为value
+
+枚举项为对象时,根据opt配置keyName、valueName取枚举项属性值分别作为key和value,`如果valueName未设置则value就是枚举项`
+
+### remove
+* remove(name: string)
+
+移除指定的枚举
+### concat
+基于现有的枚举,连接上新的枚举后返回新的枚举
+* `concat(name: string, _enum: Array, opt?: Object))`
+    * opt.keyName 指定key的取值属性,默认是key
+    * opt.valueName 指定value的取值属性
+    * opt.before 是否添加在现有的之前,默认是false
+    * opt.extend:返回的枚举[extend配置](#extend配置)
+
+### convert
+将传入的枚举格式转换为{key, value}的形式
+* `convert(name: string, _enum: Array, opt?: Object))`
+    * opt.keyName 指定key的取值属性,默认是key
+    * opt.valueName 指定value的取值属性
+
+### extend配置
+扩展枚举项属性的配置
+* `extend: Array`
+    * `key` 指定扩展的属性名
+    * `dir` 指定该属性的取值路径
+    * `transfer(item: {key: any, value: any})` 转换函数,参数未枚举项,返回就是该属性的值
+::: tip
+同时设置[dir](#dir规则)和transfer,transfer优先
+:::
+
+```js
+get('status', {
+    extend: [
+        {
+            key: 'name',
+            dir: 'value',
+        },
+        {
+            key: 'disabled',
+            transfer: item => item.key === '0'
+        }
+    ]
+})
+```
+
+
+### dir规则
+dir是指定枚举项value的取值方式,规则如下:
+* 对象属性 `A`、`A.B`
+* 数组 `[0]`、`[0][1]`
+* 混合 `A[0]`、`[0].A`、`A[0].B`
+
+```js
+// 假如枚举项value的结构如下
+const user = {
+    age: 18,
+    name: 'aring',
+    role: [
+        {
+            id: 1,
+            name: '管理员'
+        },
+                    {
+            id: 2,
+            name: '业务操作员'
+        }
+    ]
+}
+// 那么规则解析是:
+dir              value
+'age'        =>  18
+'role[0]'    =>  {id: 1, name: '管理员'}
+'role[1].id' =>  2
+```
+::: tip
+枚举项value如果是基本类型,则规则不生效,value就是当前值
+:::
\ No newline at end of file
diff --git a/docs/zh/reference/plugin/plugins/vuex.md b/docs/zh/reference/plugin/plugins/vuex.md
index 0a951f12..bfe1e079 100644
--- a/docs/zh/reference/plugin/plugins/vuex.md
+++ b/docs/zh/reference/plugin/plugins/vuex.md
@@ -1,9 +1,62 @@
 # @webank/fes-plugin-vuex
+## 介绍
+集成vuex插件
 
+增强vuex,导出所有的mutations、actions和getter的事件类型,编辑器提示
 
+约定模式,module和plugin定义放在sotres目录下,文件名包含plugin被解析为插件,无需额外配置,定义即可用。
+
+::: tip
+vuex的提供的api直接导入使用
+:::
 ## 启用方式
+在 `package.json` 中引入依赖:
+```json
+{
+    "dependencies": {
+        "@webank/fes": "^2.0.0",
+        "@webank/fes-plugin-vuex": "^2.0.0"
+    }
+}
+```
 
 ## 配置
+在 `.fes.js` 中配置:
+```js
+export default {
+    vuex: {
+        strict: true // 开启严格模式
+    }
+}
+```
 
+## 场景使用
+vuex定义模块之后,使用getter、mutation、action都是通过传入字符路径,如:
+```js
+import { useStore } from 'vuex';
+const store = useStore();
+store.getters['user/address']
+store.commit('counter/increment')
+store.dispatch('user/login')
+```
 
-## API
\ No newline at end of file
+使用该插件,可以利用导出的事件类型,如:
+```js
+import { useStore } from 'vuex';
+import { MUTATION_TYPES, GETTER_TYPES, ACTION_TYPES } from '@webank/fes';
+const store = useStore();
+store.getters[GETTER_TYPES.user.address]
+store.commit(MUTATION_TYPES.counter.increment)
+store.dispatch(ACTION_TYPES.user.login)
+```
+## API
+### MUTATION_TYPES
+* 类型 `Object`
+* mutation的所有事件类型
+ 
+### GETTER_TYPES
+* 类型 `Object`
+* getter的所有方法名
+### ACTION_TYPES
+* 类型 `Object`
+* action的所有事件类型
diff --git a/packages/fes-plugin-enums/src/runtime/core.tpl b/packages/fes-plugin-enums/src/runtime/core.tpl
index 325a59d7..4d08521b 100644
--- a/packages/fes-plugin-enums/src/runtime/core.tpl
+++ b/packages/fes-plugin-enums/src/runtime/core.tpl
@@ -111,7 +111,7 @@ function format(_enum = [], extend = []) {
  * @param dir 
  */
 function parseValueDir(value, dir='value') {
-    if (['object', 'function'].indexOf(typeof value) || !value || !dir) return value
+    if (!['object', 'function'].includes(typeof value) || !value || !dir) return value
     if (dir.startsWith('[')) {
         let key = dir.slice(1, dir.indexOf(']'))
         return parseValueDir(value[key], dir.slice(dir.indexOf(']') + 1))
@@ -133,7 +133,7 @@ function parseValueDir(value, dir='value') {
  * 转换传入的枚举数组
  * @param {string} name 枚举名称
  * @param {Array} _enum 枚举数组,数组元素可以是数组或者对象
- * @param {{keyName: 'key', valueName: string}} opt keyName: 指定枚举键名称取值属性 valueName 指定枚举键值取值属性
+ * @param {keyName: string, valueName: string} opt keyName: 指定枚举键名称取值属性 valueName 指定枚举键值取值属性
  */
 function convert(name, _enum, opt = { keyName: '', valueName: '' }) {
     if (!name) {
diff --git a/packages/fes-plugin-vuex/src/helper.js b/packages/fes-plugin-vuex/src/helper.js
index 9cec46dd..1c84adfb 100644
--- a/packages/fes-plugin-vuex/src/helper.js
+++ b/packages/fes-plugin-vuex/src/helper.js
@@ -1,6 +1,6 @@
 import { parser } from '@umijs/utils';
 import { readdirSync, readFileSync, statSync } from 'fs';
-import { join } from 'path';
+import { join, sep } from 'path';
 
 /**
  * 获取文件夹所有JS文件路径
@@ -28,7 +28,7 @@ function getDirFilePaths(dir) {
 function pathToHump(path, root) {
     return path.replace(root, '')
         .replace('.js', '')
-        .replace(/(\/|\.|-|_)\S/g, text => text[1].toUpperCase())
+        .replace(RegExp(`(${sep}|\\.|-|_)\\S`, 'g'), text => text[1].toUpperCase())
         .replace(/\S/, text => text.toLowerCase());
 }
 
@@ -102,7 +102,7 @@ function parseModel(paths = [], root) {
     let GETTER_TYPES = {};
     paths.forEach((path) => {
         const moduleName = pathToHump(path, root);
-        importModules.push(`import ${moduleName} from '${path}'`);
+        importModules.push(`import ${moduleName} from '${path.replace(/\\/g, '\\\\')}'`);
         modules.push(moduleName);
         const content = readFileSync(path).toString('utf-8');
         let ast = parser.parse(content, {
diff --git a/packages/fes-template/src/pages/index.vue b/packages/fes-template/src/pages/index.vue
index d16bd4ee..f6b04963 100644
--- a/packages/fes-template/src/pages/index.vue
+++ b/packages/fes-template/src/pages/index.vue
@@ -63,6 +63,18 @@ export default {
             ]
         });
         console.log(roles);
+        console.log(enums.get('status', {
+            extend: [
+                {
+                    key: 'name',
+                    dir: 'value'
+                },
+                {
+                    key: 'disabled',
+                    transfer: item => item.key === '0'
+                }
+            ]
+        }));
         onMounted(() => {
             console.log(router);
             setTimeout(() => {