mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-05-20 21:19:52 +08:00
Merge branch 'vue3' of https://github.com/WeBankFinTech/fes.js into vue3
This commit is contained in:
commit
bd4eba275f
12
.github/workflows/docs.yml
vendored
12
.github/workflows/docs.yml
vendored
@ -2,9 +2,9 @@ name: Deploy Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- vue3
|
||||
paths:
|
||||
- 'packages/fes-doc/**/**'
|
||||
- 'docs/**/**'
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
@ -14,7 +14,7 @@ jobs:
|
||||
- name: Build and Deploy
|
||||
uses: JamesIves/github-pages-deploy-action@master
|
||||
env:
|
||||
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
|
||||
BRANCH: gh-pages
|
||||
FOLDER: packages/fes-doc/docs/.vuepress/dist
|
||||
BUILD_SCRIPT: cd packages/fes-doc && npm install && npm run build && cd ../../
|
||||
ACCESS_TOKEN: ${{ secrets.QLIN_GITEE_TOKEN }}
|
||||
BRANCH: master
|
||||
FOLDER: docs/.vuepress/dist
|
||||
BUILD_SCRIPT: npm install && npm run docs:build
|
||||
|
13
README.md
13
README.md
@ -104,3 +104,16 @@ For bugs and feature requests, [please create an issue](https://github.com/WeBan
|
||||
3. Commit your changes: `git commit -am 'Add some feature'`
|
||||
4. Push to the branch: `git push origin my-new-feature`
|
||||
5. Submit a pull request :D
|
||||
|
||||
|
||||
## 社区活动
|
||||
|
||||
### Fesjs 社区有奖征文活动
|
||||
|
||||
为了 Fes.js 开源项目更好的运转,同时回馈开源社区,社区推出有奖征文活动!欢迎大家投递实践经验,给社区用户,更广泛的开发者提供借鉴。
|
||||
|
||||
经验输出也可以帮助到你系统沉淀自有项目,梳理工作思路,也能够帮助你的技术博客做宣传。优秀的实践案例将有机会邀请参与项目社区技术会议分享,赶快来参与吧。
|
||||
请戳:https://mp.weixin.qq.com/s/nV4NG_OUUrdgtft8g_IW4g
|
||||
|
||||
|
||||
|
||||
|
@ -172,7 +172,8 @@ export default function ({ cgiMock, mockjs, utils }) {
|
||||
- utils.file(path),从项目根目录根据path寻找文件,返回文件流。
|
||||
|
||||
## 配置 Mock
|
||||
详见配置 #mock。
|
||||
|
||||
详见配置 [mock](../reference/config/#mock)。
|
||||
|
||||
## 关闭 Mock
|
||||
可以通过配置关闭。
|
||||
|
@ -31,6 +31,7 @@ export default {
|
||||
### top
|
||||
<!--  -->
|
||||
<img :src="$withBase('top.png')" alt="top">
|
||||
|
||||
### mixin
|
||||
<!--  -->
|
||||
<img :src="$withBase('mixin.png')" alt="mixin">
|
||||
@ -69,6 +70,8 @@ export default {
|
||||
title: "Fes.js",
|
||||
// 底部文字
|
||||
footer: 'Created by MumbelFe',
|
||||
// 主题light
|
||||
theme: 'dark'
|
||||
// 是否开启 tabs
|
||||
multiTabs: false,
|
||||
// 布局类型
|
||||
@ -98,6 +101,13 @@ export default {
|
||||
|
||||
- **详情**:页面底部的文字。
|
||||
|
||||
### theme
|
||||
- **类型**:`String`
|
||||
|
||||
- **默认值**:`dark`
|
||||
|
||||
- **详情**:主题,可选有 `dark`、`light`
|
||||
|
||||
### navigation
|
||||
- **类型**:`String`
|
||||
|
||||
|
@ -23,5 +23,19 @@ Fes.js 中约定 `src/global.css` 为全局样式,如果存在此文件,会
|
||||
</style>
|
||||
```
|
||||
|
||||
## CSS Modules
|
||||
支持 `Vue` 的 [CSS Modules](https://vue-loader.vuejs.org/zh/guide/css-modules.html#%E7%94%A8%E6%B3%95) 用法,可以直接使用:
|
||||
```vue
|
||||
<style module>
|
||||
.layout-content {
|
||||
max-width: 1000px;
|
||||
}
|
||||
```
|
||||
如果想直接引入CSS文件的话,则CSS文件名需要包含`.module`,比如:
|
||||
```js
|
||||
import style from '@/styles/index.module.css'
|
||||
console.log(style)
|
||||
```
|
||||
|
||||
## CSS 预处理器
|
||||
Fes.js 内置支持 `less`,不支持 `sass` 和 `stylus`,但如果有需求,可以通过 `chainWebpack` 配置或者 `fes-plugin` 插件的形式支持。
|
@ -172,7 +172,7 @@ export default function ({ cgiMock, mockjs, utils }) {
|
||||
- utils.file(path),从项目根目录根据path寻找文件,返回文件流。
|
||||
|
||||
## 配置 Mock
|
||||
详见配置 #mock。
|
||||
详见配置 [mock](../reference/config/#mock)。
|
||||
|
||||
## 关闭 Mock
|
||||
可以通过配置关闭。
|
||||
|
@ -144,6 +144,24 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## extraBabelPlugins
|
||||
|
||||
- 类型: `array`
|
||||
- 默认值: `[]`
|
||||
- 详情:
|
||||
|
||||
配置额外的 babel 插件。
|
||||
|
||||
- 示例:
|
||||
```js
|
||||
export default {
|
||||
extraBabelPlugins: [
|
||||
['import', { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: 'css' }],
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## extraPostCSSPlugins
|
||||
|
||||
- 类型: `array`
|
||||
@ -278,6 +296,12 @@ export default {
|
||||
|
||||
配置 webpack 的 publicPath。当打包的时候,webpack 会在静态文件路径前面添加 `publicPath` 的值,当你需要修改静态文件地址时,比如使用 CDN 部署,把 `publicPath` 的值设为 CDN 的值就可以。
|
||||
|
||||
## router
|
||||
|
||||
- 类型: `object`
|
||||
- 默认值: `{ mode: 'hash' }`
|
||||
- 详情: 配置路由,具体请查看指南中关于路由的介绍
|
||||
|
||||
## singular
|
||||
- 类型: `boolean`
|
||||
- 默认值: `false`
|
||||
|
@ -14,27 +14,6 @@
|
||||
|
||||
- 可配置页面是否需要 layout。
|
||||
|
||||
## 布局类型
|
||||
配置参数是 `navigation`, 内容默认是 `side`:
|
||||
```js
|
||||
export default {
|
||||
layout: {
|
||||
navigation: 'side
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### side
|
||||
<!--  -->
|
||||
<img :src="$withBase('side.png')" alt="side">
|
||||
|
||||
### top
|
||||
<!--  -->
|
||||
<img :src="$withBase('top.png')" alt="top">
|
||||
### mixin
|
||||
<!--  -->
|
||||
<img :src="$withBase('mixin.png')" alt="mixin">
|
||||
|
||||
## 启用方式
|
||||
在 `package.json` 中引入依赖:
|
||||
```json
|
||||
@ -46,17 +25,53 @@ export default {
|
||||
}
|
||||
```
|
||||
|
||||
## 布局类型
|
||||
配置参数是 `navigation`, 布局有三种类型 `side`、`mixin` 和 `top`, 默认是 `side`:
|
||||
```js
|
||||
export default {
|
||||
layout: {
|
||||
navigation: 'side'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### side
|
||||
<!--  -->
|
||||
<img :src="$withBase('side.png')" alt="side">
|
||||
|
||||
### top
|
||||
<!--  -->
|
||||
<img :src="$withBase('top.png')" alt="top">
|
||||
|
||||
### mixin
|
||||
<!--  -->
|
||||
<img :src="$withBase('mixin.png')" alt="mixin">
|
||||
|
||||
### 页面禁用布局
|
||||
Fes.js 渲染路由时,如果路由元信息存在配置 `layout` 为 `false`,则表示禁用此配置,用户只需要如下配置:
|
||||
布局是默认开启的,但是可能某些页面不需要展示布局样式,比如登录页面。我们只需要在页面的`.vue`中添加如下配置:
|
||||
```vue
|
||||
<config>
|
||||
<config lang="json">
|
||||
{
|
||||
"layout": false
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
</script>
|
||||
```
|
||||
如果只是不想展示`side`,则:
|
||||
<config lang="json">
|
||||
{
|
||||
"layout": {
|
||||
"side": false
|
||||
}
|
||||
}
|
||||
</config>
|
||||
```
|
||||
`layout`的可选配置有:
|
||||
|
||||
- **side**: 左侧区域
|
||||
|
||||
- **top**: 头部区域
|
||||
|
||||
- **logo**:logo和标题区域。
|
||||
|
||||
## 配置
|
||||
|
||||
@ -69,6 +84,8 @@ export default {
|
||||
title: "Fes.js",
|
||||
// 底部文字
|
||||
footer: 'Created by MumbelFe',
|
||||
// 主题light
|
||||
theme: 'dark'
|
||||
// 是否开启 tabs
|
||||
multiTabs: false,
|
||||
// 布局类型
|
||||
@ -98,6 +115,13 @@ export default {
|
||||
|
||||
- **详情**:页面底部的文字。
|
||||
|
||||
### theme
|
||||
- **类型**:`String`
|
||||
|
||||
- **默认值**:`dark`
|
||||
|
||||
- **详情**:主题,可选有 `dark`、`light`
|
||||
|
||||
### navigation
|
||||
- **类型**:`String`
|
||||
|
||||
@ -164,13 +188,13 @@ export default {
|
||||
- 图标使用[antv icon](https://www.antdv.com/components/icon-cn/),在这里使用组件type。
|
||||
```js
|
||||
{
|
||||
name: "user"
|
||||
icon: "user"
|
||||
}
|
||||
```
|
||||
- 图表使用本地或者远程svg图片。
|
||||
- 图标使用本地或者远程svg图片。
|
||||
```js
|
||||
{
|
||||
name: "/wine-outline.svg"
|
||||
icon: "/wine-outline.svg"
|
||||
}
|
||||
```
|
||||
|
||||
@ -191,7 +215,7 @@ export const layout = {
|
||||
|
||||
- **默认值**:`null`
|
||||
|
||||
- **详情**:布局的 Header 部位提供组件自定义功能。
|
||||
- **详情**:top的区域部分位置提供组件自定义功能。
|
||||
|
||||
#### unAccessHandler
|
||||
- **类型**:`Function`
|
||||
|
@ -45,7 +45,7 @@ export default {
|
||||
};
|
||||
```
|
||||
```js
|
||||
// src/locales/zh-CN.js
|
||||
// src/locales/en-US.js
|
||||
export default {
|
||||
menu: {
|
||||
interface: 'interface'
|
||||
|
@ -19,8 +19,7 @@
|
||||
```js
|
||||
export default {
|
||||
request: {
|
||||
dataField: 'result',
|
||||
base: '',
|
||||
dataField: 'result'
|
||||
},
|
||||
}
|
||||
```
|
||||
@ -34,13 +33,15 @@ export default {
|
||||
`dataField` 对应接口统一格式中的数据字段,比如接口如果统一的规范是 `{ success: boolean, result: any}` ,那么就不需要配置,这样你通过 `useRequest` 消费的时候会生成一个默认的 `formatResult`,直接返回 `result` 中的数据,方便使用。如果你的后端接口不符合这个规范,可以自行配置 `dataField`。配置为 `''`(空字符串)的时候不做处理。
|
||||
|
||||
|
||||
#### base
|
||||
#### base(即将废弃)
|
||||
|
||||
- 类型: `string`
|
||||
- 默认值: `''`
|
||||
- 详情:
|
||||
|
||||
`base` 接口前缀。
|
||||
|
||||
⚠️警告,这个字段将在下个版本废弃,推荐使用 [axios baseURL](https://github.com/axios/axios)。
|
||||
### 运行时配置
|
||||
|
||||
在 `app.js` 中进行运行时配置。
|
||||
@ -51,6 +52,8 @@ export const request = {
|
||||
responseDataAdaptor: (data) => {
|
||||
|
||||
},
|
||||
// 关闭 response data 校验(只判断 xhr status)
|
||||
closeResDataCheck: false,
|
||||
// 请求拦截器
|
||||
requestInterceptors: [],
|
||||
// 相应拦截器
|
||||
@ -63,7 +66,6 @@ export const request = {
|
||||
// 特殊 code 处理逻辑
|
||||
},
|
||||
404(error) {
|
||||
|
||||
},
|
||||
default(error) {
|
||||
// 异常统一处理
|
||||
@ -73,6 +75,32 @@ export const request = {
|
||||
...otherConfigs
|
||||
}
|
||||
```
|
||||
|
||||
#### skipErrorHandler
|
||||
|
||||
- 类型: `boolean | string | number | array<string | number>`
|
||||
- 默认值: ``
|
||||
- 详情:
|
||||
|
||||
指定当前请求的某些错误状态不走 `errorHandler`,单独进行处理。如果设置为 `true`,当前请求的错误处理都不走 `errorHandler`。
|
||||
|
||||
- 示列:
|
||||
|
||||
```js
|
||||
import {request} from '@fesjs/fes';
|
||||
|
||||
request('/api/login', null, {
|
||||
skipErrorHandler: '110'
|
||||
}).then((res) => {
|
||||
// do something
|
||||
}).catch((err) => {
|
||||
// 这里处理 code 为 110 的异常
|
||||
// 此时 errorHandler[110] 函数不会生效,也不会执行 errorHandler.default
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 使用
|
||||
|
||||
### 发起一个普通 post 请求
|
||||
@ -90,6 +118,27 @@ request('/api/login', {
|
||||
})
|
||||
```
|
||||
|
||||
### merge 重复请求
|
||||
|
||||
连续发送多个请求,会被合并成一个请求,不会报 `REPEAT` 接口错误。
|
||||
|
||||
当发生 `REPEAT` 请求异常,并且确保自身代码合理的情况下,可以使用该配置。
|
||||
|
||||
```js
|
||||
import {request} from '@fesjs/fes';
|
||||
|
||||
request('/api/login', {
|
||||
username: 'robby',
|
||||
password: '123456'
|
||||
}, {
|
||||
mergeRequest: true, // 在一个请求没有回来前,重复发送的请求会合并成一个请求
|
||||
}).then((res) => {
|
||||
// do something
|
||||
}).catch((err) => {
|
||||
// 处理异常
|
||||
})
|
||||
```
|
||||
|
||||
### 请求节流
|
||||
|
||||
```js
|
||||
@ -118,7 +167,7 @@ request('/api/login', {
|
||||
}, {
|
||||
cache: {
|
||||
cacheType: 'ram', // ram: 内存,session: sessionStorage,local:localStorage
|
||||
cacheTime: 1000 * 60 * 3 // 缓存时间,默认3min
|
||||
cacheTime: 1000 * 60 * 3 // 缓存时间:默认3min
|
||||
},
|
||||
}).then((res) => {
|
||||
// do something
|
||||
@ -129,6 +178,7 @@ request('/api/login', {
|
||||
|
||||
若 `cache` 传 `true`,则默认使用 `ram` 缓存类型,缓存时间 3min。
|
||||
|
||||
|
||||
### 结合 use 使用
|
||||
|
||||
```js
|
||||
|
@ -1,4 +1,4 @@
|
||||
# @fesjs/plugin-access
|
||||
# @fesjs/plugin-sass
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "independent",
|
||||
"changelog": {
|
||||
"repo": "WeBankFinTech/fes.js",
|
||||
"cacheDir": ".changelog",
|
||||
|
@ -11,7 +11,7 @@
|
||||
"clean": "lerna clean",
|
||||
"bootstrap": "lerna bootstrap",
|
||||
"build": "father-build --watch",
|
||||
"ver": "lerna version prerelease --preid rc --no-changelog --no-commit-hooks --no-private",
|
||||
"ver": "lerna version patch --no-changelog --no-commit-hooks --no-private",
|
||||
"release": "father-build && lerna publish from-git",
|
||||
"docs:dev": "vuepress dev docs --clean-cache",
|
||||
"docs:build": "vuepress build docs --clean-cache"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/create-fes-app",
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "2.0.1",
|
||||
"description": "create a app base on fes.js",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
|
@ -1,5 +1,5 @@
|
||||
// fes.config.js 只负责管理 cli 相关的配置
|
||||
import pxtoviewport from 'postcss-px-to-viewport';
|
||||
import pxtoviewport from '@ttou/postcss-px-to-viewport';
|
||||
|
||||
|
||||
export default {
|
||||
|
4
packages/create-fes-app/templates/app/h5/.prettierrc
Normal file
4
packages/create-fes-app/templates/app/h5/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/template-h5",
|
||||
"version": "2.0.0-rc.0",
|
||||
"version": "2.0.0",
|
||||
"description": "fes 移动端项目模版",
|
||||
"scripts": {
|
||||
"build": "fes build",
|
||||
@ -40,13 +40,13 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10",
|
||||
"postcss-px-to-viewport": "1.1.1"
|
||||
"@webank/eslint-config-webank": "0.3.0",
|
||||
"@ttou/postcss-px-to-viewport": "1.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-icon": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-request": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/plugin-icon": "^2.0.0",
|
||||
"@fesjs/plugin-request": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
},
|
||||
"private": true
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
|
||||
export default {
|
||||
define: {
|
||||
__DEV__: false
|
||||
},
|
||||
publicPath: './',
|
||||
access: {
|
||||
roles: {
|
||||
@ -17,13 +14,8 @@ export default {
|
||||
multiTabs: false,
|
||||
menus: [{
|
||||
name: 'index'
|
||||
}, {
|
||||
name: 'onepiece'
|
||||
}]
|
||||
},
|
||||
locale: {
|
||||
legacy: true
|
||||
},
|
||||
devServer: {
|
||||
port: 8000
|
||||
},
|
||||
|
@ -1,4 +1,5 @@
|
||||
.DS_Store
|
||||
.cache
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
4
packages/create-fes-app/templates/app/pc/.prettierrc
Normal file
4
packages/create-fes-app/templates/app/pc/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none"
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import sum from '@/utils/sum';
|
||||
|
||||
test('adds 1 + 2 to equal 3', () => {
|
||||
expect(sum(1, 2)).toBe(3);
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/template",
|
||||
"version": "2.0.0-rc.0",
|
||||
"version": "2.0.0",
|
||||
"description": "fes项目模版",
|
||||
"scripts": {
|
||||
"build": "fes build",
|
||||
@ -43,21 +43,16 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10"
|
||||
"@webank/eslint-config-webank": "0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-access": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-layout": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-locale": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-model": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-enums": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-jest": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-vuex": "^2.0.0-rc.0",
|
||||
"ant-design-vue": "^2.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"vuex": "^4.0.0"
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/plugin-access": "^2.0.0",
|
||||
"@fesjs/plugin-layout": "^2.0.0",
|
||||
"@fesjs/plugin-model": "^2.0.0",
|
||||
"@fesjs/plugin-enums": "^2.0.0",
|
||||
"ant-design-vue": "^2.2.0",
|
||||
"vue": "^3.1.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ export const beforeRender = {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
setRole('admin');
|
||||
// 初始化应用的全局状态,可以通过 useModel('@@initialState') 获取,具体用法看@/components/UserCenter 文件
|
||||
resolve({
|
||||
userName: 'harrywan'
|
||||
});
|
||||
|
@ -0,0 +1 @@
|
||||
// 放工具函数
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>{{initialState.userName}}</div>
|
||||
<div class="right">{{initialState.userName}}</div>
|
||||
</template>
|
||||
<script>
|
||||
import { useModel } from '@fesjs/fes';
|
||||
@ -13,3 +13,9 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scope>
|
||||
.right {
|
||||
text-align: right;
|
||||
padding: 0 20px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,11 +0,0 @@
|
||||
|
||||
export default {
|
||||
test: 'test',
|
||||
'navBar.lang': 'Languages',
|
||||
'layout.user.link.help': 'Help',
|
||||
'layout.user.link.privacy': 'Privacy',
|
||||
'layout.user.link.terms': 'Terms',
|
||||
'app.preview.down.block': 'Download this page to your local project',
|
||||
'app.welcome.link.fetch-blocks': 'Get all block',
|
||||
'app.welcome.link.block-list': 'Quickly build standard, pages based on `block` development'
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
|
||||
export default {
|
||||
'navbar.lang': 'Bahasa',
|
||||
'layout.user.link.help': 'Bantuan',
|
||||
'layout.user.link.privacy': 'Privasi',
|
||||
'layout.user.link.terms': 'Ketentuan',
|
||||
'app.preview.down.block': 'Unduh halaman ini dalam projek lokal anda',
|
||||
'app.welcome.link.fetch-blocks': 'Dapatkan semua blok',
|
||||
'app.welcome.link.block-list':
|
||||
'Buat standar dengan cepat, halaman-halaman berdasarkan pengembangan `block`'
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
|
||||
export default {
|
||||
'navBar.lang': 'Idiomas',
|
||||
'layout.user.link.help': 'ajuda',
|
||||
'layout.user.link.privacy': 'política de privacidade',
|
||||
'layout.user.link.terms': 'termos de serviços',
|
||||
'app.preview.down.block': 'Download this page to your local project'
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
|
||||
export default {
|
||||
test: '测试',
|
||||
'navBar.lang': '语言',
|
||||
'layout.user.link.help': '帮助',
|
||||
'layout.user.link.privacy': '隐私',
|
||||
'layout.user.link.terms': '条款',
|
||||
'app.preview.down.block': '下载此页面到本地项目',
|
||||
'app.welcome.link.fetch-blocks': '获取全部区块',
|
||||
'app.welcome.link.block-list': '基于 block 开发,快速构建标准页面'
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
|
||||
export default {
|
||||
'navBar.lang': '語言',
|
||||
'layout.user.link.help': '幫助',
|
||||
'layout.user.link.privacy': '隱私',
|
||||
'layout.user.link.terms': '條款',
|
||||
'app.preview.down.block': '下載此頁面到本地項目'
|
||||
};
|
@ -1,100 +1,43 @@
|
||||
<template>
|
||||
<div class="haizekuo">
|
||||
<div>国际化: {{t("test")}}</div>
|
||||
fes & 拉夫德鲁 <br />
|
||||
<access :id="accessId"> accessOnepicess1 <input /> </access>
|
||||
<div v-access="accessId"> accessOnepicess2 <input /> </div>
|
||||
<input />
|
||||
<div style="padding: 32px;">
|
||||
<h3>fes & 拉夫德鲁 </h3>
|
||||
<h4>数据字典</h4>
|
||||
<div v-for="item in enumsGet('status')" :key="item.key">{{item.value}}:{{item.key}}</div>
|
||||
<div v-for="item in roles" :key="item.key">{{item.name}}:{{item.disabled}}</div>
|
||||
<div>{{enumsGet('roles', '2', { dir: 'eName' })}}</div>
|
||||
<h4>Vuex <button @click="increment">click me:{{count}}</button></h4>
|
||||
|
||||
<section>
|
||||
计数器
|
||||
<button @click="increment">click me:{{count}}</button>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
import {
|
||||
enums
|
||||
} from '@fesjs/fes';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
const count = ref(0);
|
||||
const increment = () => {
|
||||
count.value++;
|
||||
};
|
||||
|
||||
return {
|
||||
fes,
|
||||
increment,
|
||||
count,
|
||||
enumsGet: enums.get
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<config>
|
||||
{
|
||||
"name": "index",
|
||||
"title": "首页"
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
import { ref, onMounted, computed } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import {
|
||||
useAccess, useRouter, useI18n, locale, enums
|
||||
} from '@fesjs/fes';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
const accessOnepicess = useAccess('/onepiece1');
|
||||
const localI18n = useI18n();
|
||||
const router = useRouter();
|
||||
const accessId = ref('/onepiece1');
|
||||
enums.push('roles', [
|
||||
{
|
||||
id: '1',
|
||||
cName: '系统管理员',
|
||||
eName: 'System',
|
||||
perm: ['1', '2', '3']
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
cName: '业务管理员',
|
||||
eName: 'Business',
|
||||
perm: ['1', '2']
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
cName: '普通用户',
|
||||
eName: 'User',
|
||||
perm: ['1']
|
||||
}
|
||||
], { keyName: 'id' });
|
||||
const roles = enums.get('roles', {
|
||||
extend: [
|
||||
{
|
||||
key: 'name',
|
||||
dir: 'cName'
|
||||
},
|
||||
{
|
||||
key: 'disabled',
|
||||
transfer: item => item.value.perm.some(i => i >= 2)
|
||||
}
|
||||
]
|
||||
});
|
||||
console.log(roles);
|
||||
const store = useStore();
|
||||
console.log('store==>', store);
|
||||
onMounted(() => {
|
||||
console.log(router);
|
||||
setTimeout(() => {
|
||||
locale.setLocale({ lang: 'en-US' });
|
||||
locale.addLocale({ lang: 'ja-JP', messages: { test: 'テスト' } });
|
||||
console.log(locale.getAllLocales());
|
||||
}, 2000);
|
||||
setTimeout(() => {
|
||||
accessId.value = '11';
|
||||
}, 4000);
|
||||
// router.push('/onepiece');
|
||||
});
|
||||
return {
|
||||
accessId,
|
||||
fes,
|
||||
accessOnepicess,
|
||||
t: localI18n.t,
|
||||
enumsGet: enums.get,
|
||||
roles,
|
||||
count: computed(() => store.state.counter.count),
|
||||
increment: () => store.commit('counter/increment')
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.haizekuo {
|
||||
/* background: url('../images/icon.png'); */
|
||||
}
|
||||
</style>
|
||||
|
@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<div>{{fes}}</div>
|
||||
</template>
|
||||
<config>
|
||||
{
|
||||
"name": "onepiece",
|
||||
"title": "onepiece"
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
return {
|
||||
fes
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,10 +0,0 @@
|
||||
<template>
|
||||
<div>test</div>
|
||||
</template>
|
||||
<script>
|
||||
import { } from '@fesjs/fes';
|
||||
|
||||
export default {
|
||||
|
||||
};
|
||||
</script>
|
@ -1,23 +0,0 @@
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: () => ({
|
||||
count: 0
|
||||
}),
|
||||
mutations: {
|
||||
increment(state) {
|
||||
state.count++;
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
doubleCount(state) {
|
||||
return state.count * 2;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
asyncIncrement({ commit }) {
|
||||
setTimeout(() => {
|
||||
commit('increment');
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,3 +0,0 @@
|
||||
import { createLogger } from 'vuex';
|
||||
|
||||
export default createLogger();
|
@ -1,25 +0,0 @@
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: () => ({
|
||||
name: 'aring',
|
||||
age: 20,
|
||||
count: 0
|
||||
}),
|
||||
mutations: {
|
||||
increment(state) {
|
||||
state.count++;
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
doubleCount(state) {
|
||||
return state.count * 2;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
asyncIncrement({ commit }) {
|
||||
setTimeout(() => {
|
||||
commit('increment');
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,3 +0,0 @@
|
||||
export default function sum(a, b) {
|
||||
return a + b;
|
||||
}
|
8479
packages/create-fes-app/templates/app/pc/yarn.lock
Normal file
8479
packages/create-fes-app/templates/app/pc/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/compiler",
|
||||
"version": "2.0.0-rc.5",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/compiler",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-access",
|
||||
"version": "2.0.0-rc.1",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-access",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -26,8 +26,11 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { reactive, unref, computed, inject } from "vue";
|
||||
import createDirective from "./createDirective";
|
||||
import createComponent from "./createComponent";
|
||||
import isPlainObject from "lodash/isPlainObject";
|
||||
|
||||
const accessKey = Symbol("plugin-access");
|
||||
|
||||
@ -50,16 +51,21 @@ const setAccess = (accessIds) => {
|
||||
if (isPromise(accessIds)) {
|
||||
return _syncSetAccessIds(accessIds);
|
||||
}
|
||||
if(isPlainObject(accessIds)){
|
||||
if(accessIds.accessIds){
|
||||
setAccess(accessIds.accessIds);
|
||||
}
|
||||
if(accessIds.roleId){
|
||||
setRole(accessIds.roleId);
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!Array.isArray(accessIds)) {
|
||||
throw new Error("[plugin-access]: argument to the setAccess() must be array or promise");
|
||||
throw new Error("[plugin-access]: argument to the setAccess() must be array or promise or object");
|
||||
}
|
||||
state.currentAccessIds = accessIds;
|
||||
};
|
||||
|
||||
const getAccess = () => {
|
||||
return state.currentAccessIds.slice(0)
|
||||
}
|
||||
|
||||
const _syncSetRoleId = (promise) => {
|
||||
rolePromiseList.push(promise);
|
||||
promise
|
||||
@ -143,7 +149,7 @@ export const access = {
|
||||
isDataReady,
|
||||
setRole,
|
||||
setAccess,
|
||||
getAccess,
|
||||
getAccess: getAllowAccessIds,
|
||||
};
|
||||
|
||||
export const useAccess = (path) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-enums",
|
||||
"version": "2.0.0-rc.1",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-enums",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -27,7 +27,7 @@
|
||||
"access": "public"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ Object.keys(_ENUMS).forEach(key => {
|
||||
function get(name, key, opt = { dir: 'value', extend: []}) {
|
||||
if (Object.prototype.toString.call(key) === '[object Object]') {
|
||||
opt = key
|
||||
key = ''
|
||||
key = null
|
||||
}
|
||||
let list = ENUMS[name] || []
|
||||
let value
|
||||
if (key) {
|
||||
if (key !== undefined && key !== null) {
|
||||
let res = list.filter(item => item.key === key)[0]
|
||||
if (!res) return key
|
||||
value = parseValueDir(res.value, opt.dir) || key
|
||||
@ -81,7 +81,7 @@ function concat(name, _enum, opt = { keyName: '', valueName: '', before: false,
|
||||
} else {
|
||||
list = list.concat(partList)
|
||||
}
|
||||
return readonly(format(list, extend))
|
||||
return readonly(format(list, opt.extend))
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,7 +111,7 @@ function format(_enum = [], extend = []) {
|
||||
* @param dir
|
||||
*/
|
||||
function parseValueDir(value, dir='value') {
|
||||
if (!['object', 'function'].includes(typeof value) || !value || !dir) return value
|
||||
if (!['object', 'function'].includes(typeof value) || !value || !dir || dir === 'value') return value
|
||||
if (dir.startsWith('[')) {
|
||||
let key = dir.slice(1, dir.indexOf(']'))
|
||||
return parseValueDir(value[key], dir.slice(dir.indexOf(']') + 1))
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-icon",
|
||||
"version": "2.0.0-rc.1",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-icon",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-jest",
|
||||
"version": "2.0.0-rc.5",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-jest",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "7.11.6",
|
||||
"@fesjs/compiler": "^2.0.0-rc.5",
|
||||
"@fesjs/compiler": "^2.0.0",
|
||||
"@umijs/babel-preset-umi": "3.2.24",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-layout",
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-layout",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -31,7 +31,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ant-design/icons-vue": "^5.1.6",
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"ant-design-vue": "2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ const matchName = (config, name) => {
|
||||
for (let i = 0; i < config.length; i++) {
|
||||
const item = config[i];
|
||||
if (item.meta && item.meta.name === name) {
|
||||
res = item.meta || {};
|
||||
res = item.meta;
|
||||
res.path = item.path;
|
||||
break;
|
||||
}
|
||||
@ -68,10 +68,10 @@ export function getIconsFromMenu(data) {
|
||||
return [];
|
||||
}
|
||||
let icons = [];
|
||||
(data || []).forEach((item = { path: '/' }) => {
|
||||
data.forEach((item = { path: '/' }) => {
|
||||
if (item.icon) {
|
||||
const { icon } = item;
|
||||
if (icon && icon.type === 'icon') {
|
||||
if (icon.type === 'icon') {
|
||||
icons.push(icon.name);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
<template>
|
||||
<a-layout
|
||||
v-if="routeHasLayout"
|
||||
v-if="routeLayout"
|
||||
:class="[
|
||||
collapsed ? 'main-layout-collapsed' : '',
|
||||
`main-layout-navigation-${navigation}`
|
||||
`main-layout-navigation-${navigation}`,
|
||||
`main-layout-theme-${siderTheme}`
|
||||
]"
|
||||
class="main-layout"
|
||||
>
|
||||
<template v-if="navigation !== 'top'">
|
||||
<template v-if="navigation !== 'top' && routeLayout.side">
|
||||
<div v-if="fixedSideBar" :style="siderFixedStuffStyle" class="layout-sider-fixed-stuff"></div>
|
||||
<a-layout-sider
|
||||
v-model:collapsed="collapsed"
|
||||
@ -19,7 +20,7 @@
|
||||
:theme="siderTheme"
|
||||
collapsible
|
||||
>
|
||||
<div v-if="navigation !== 'mixin'" class="layout-logo">
|
||||
<div v-if="navigation !== 'mixin' && routeLayout.logo" class="layout-logo">
|
||||
<img :src="logo" class="logo-img" />
|
||||
<h1 class="logo-name">{{title}}</h1>
|
||||
</div>
|
||||
@ -27,19 +28,20 @@
|
||||
</a-layout-sider>
|
||||
</template>
|
||||
<a-layout class="child-layout">
|
||||
<a-layout-header v-if="currentFixedHeader" class="layout-header">
|
||||
<a-layout-header v-if="currentFixedHeader && routeLayout.top" class="layout-header">
|
||||
</a-layout-header>
|
||||
<a-layout-header
|
||||
v-if="routeLayout.top"
|
||||
:style="headerFixedStyle"
|
||||
:class="[currentFixedHeader ? 'layout-header-fixed' : '']"
|
||||
class="layout-header"
|
||||
>
|
||||
<div v-if="navigation === 'mixin'" class="layout-logo">
|
||||
<div v-if="navigation === 'mixin' && routeLayout.logo" class="layout-logo">
|
||||
<img :src="logo" class="logo-img" />
|
||||
<h1 class="logo-name">{{title}}</h1>
|
||||
</div>
|
||||
<template v-if="navigation === 'top'">
|
||||
<div class="layout-logo">
|
||||
<div v-if="routeLayout.logo" class="layout-logo">
|
||||
<img :src="logo" class="logo-img" />
|
||||
<h1 class="logo-name">{{title}}</h1>
|
||||
</div>
|
||||
@ -134,9 +136,32 @@ export default {
|
||||
setup(props) {
|
||||
const collapsed = ref(false);
|
||||
const route = useRoute();
|
||||
const routeHasLayout = computed(() => {
|
||||
const _routeLayout = route.meta.layout;
|
||||
return _routeLayout === undefined ? true : _routeLayout;
|
||||
const routeLayoutDefault = {
|
||||
side: true,
|
||||
top: true,
|
||||
logo: true
|
||||
};
|
||||
const routeLayout = computed(() => {
|
||||
let config;
|
||||
// meta 中 layout 默认为 true
|
||||
const metaLayoutConfig = route.meta.layout === undefined ? true : route.meta.layout;
|
||||
if (typeof metaLayoutConfig === 'boolean') {
|
||||
config = metaLayoutConfig ? routeLayoutDefault : false;
|
||||
} else if (typeof metaLayoutConfig === 'object') {
|
||||
config = { ...routeLayoutDefault, ...metaLayoutConfig };
|
||||
} else {
|
||||
console.error('[plugin-layout]: meta layout must be object or boolean!');
|
||||
}
|
||||
// query 中 layout 默认为 false
|
||||
const routeQueryLayoutConfig = route.query.layout && JSON.parse(route.query.layout);
|
||||
if (typeof routeQueryLayoutConfig === 'boolean') {
|
||||
config = routeQueryLayoutConfig ? routeLayoutDefault : false;
|
||||
} else if (typeof routeQueryLayoutConfig === 'object') {
|
||||
config = { ...config, ...routeQueryLayoutConfig };
|
||||
} else if (routeQueryLayoutConfig !== undefined) {
|
||||
console.error('[plugin-layout]: query layout must be object or boolean!');
|
||||
}
|
||||
return config;
|
||||
});
|
||||
const siderTheme = computed(() => {
|
||||
if (props.navigation === 'mixin') {
|
||||
@ -174,7 +199,7 @@ export default {
|
||||
siderTheme,
|
||||
currentFixedHeader,
|
||||
route,
|
||||
routeHasLayout,
|
||||
routeLayout,
|
||||
collapsed,
|
||||
siderFixedStuffStyle,
|
||||
headerFixedStyle
|
||||
@ -334,5 +359,21 @@ export default {
|
||||
.layout-footer {
|
||||
text-align: center;
|
||||
}
|
||||
&.main-layout-theme-light{
|
||||
.logo-name{
|
||||
color: rgba(0, 0, 0, 0.65) !important;
|
||||
}
|
||||
&.main-layout-navigation-mixin{
|
||||
.logo-name{
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
&.main-layout-navigation-top{
|
||||
.layout-header {
|
||||
background: #fff;
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-locale",
|
||||
"version": "2.0.0-rc.8",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-locale",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -32,7 +32,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ant-design/icons-vue": "^5.1.6",
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"ant-design-vue": "2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-model",
|
||||
"version": "2.0.0-rc.8",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-model",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -30,7 +30,7 @@
|
||||
"@umijs/utils": "3.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -43,10 +43,10 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10"
|
||||
"@webank/eslint-config-webank": "0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"ant-design-vue": "2.0.0"
|
||||
},
|
||||
|
@ -10,3 +10,22 @@ export const beforeRender = {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const qiankun = {
|
||||
// 应用加载之前
|
||||
async bootstrap(props) {
|
||||
console.log('app1 bootstrap', props);
|
||||
},
|
||||
// 应用 render 之前触发
|
||||
async mount(props) {
|
||||
console.log('app1 mount', props);
|
||||
},
|
||||
// 当 props 更新时触发
|
||||
async update(props) {
|
||||
console.log('app1 update', props);
|
||||
},
|
||||
// 应用卸载之后触发
|
||||
async unmount(props) {
|
||||
console.log('app1 unmount', props);
|
||||
}
|
||||
};
|
||||
|
@ -5,8 +5,8 @@
|
||||
</template>
|
||||
<config>
|
||||
{
|
||||
"name": "index",
|
||||
"title": "home"
|
||||
"name": "test",
|
||||
"title": "test"
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
|
@ -43,10 +43,10 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10"
|
||||
"@webank/eslint-config-webank": "0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"ant-design-vue": "2.0.0"
|
||||
},
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { access as accessApi } from '@fesjs/fes';
|
||||
import PageLoading from '@/components/PageLoading';
|
||||
import Antdv from 'ant-design-vue';
|
||||
import 'ant-design-vue/dist/antd.css';
|
||||
|
||||
export const beforeRender = {
|
||||
loading: <PageLoading />,
|
||||
@ -13,3 +15,7 @@ export const beforeRender = {
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const onAppCreated = ({ app }) => {
|
||||
app.use(Antdv);
|
||||
};
|
||||
|
@ -1,8 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
main
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="Tab 1"><MicroAppWithMemoHistory key="1" name="app1" url="/app1" /></a-tab-pane>
|
||||
<a-tab-pane key="2" tab="Tab 2"><MicroAppWithMemoHistory key="2" name="app1" url="/app1/test" /></a-tab-pane>
|
||||
<a-tab-pane key="3" tab="Tab 3">Content of Tab Pane 3</a-tab-pane>
|
||||
</a-tabs>
|
||||
</div>
|
||||
<MicroAppWithMemoHistory name="app1" :url="url" />
|
||||
</template>
|
||||
<config>
|
||||
{
|
||||
@ -24,6 +28,7 @@ export default {
|
||||
}, 3000);
|
||||
});
|
||||
return {
|
||||
activeKey: ref('1'),
|
||||
url
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-qiankun",
|
||||
"version": "2.0.0-rc.17",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-qiankun",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -38,7 +38,7 @@
|
||||
"npm-run-all": "^4.1.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@webank/fes": "^2.0.0-rc.0",
|
||||
"@webank/fes": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ function modifyRoutesWithAttachMode({
|
||||
export default function modifyRoutes({ api, namespace }) {
|
||||
api.modifyRoutes((routes) => {
|
||||
const { router, base } = api.config;
|
||||
const masterHistoryType = (router && router?.mode) || defaultHistoryType;
|
||||
const masterHistoryType = (router && router.mode) || defaultHistoryType;
|
||||
|
||||
modifyRoutesWithAttachMode({
|
||||
routes,
|
||||
|
@ -165,7 +165,7 @@ export default function (api) {
|
||||
|
||||
api.addEntryCode(
|
||||
() => `
|
||||
export const bootstrap = qiankun_genBootstrap(completeClientRender, app);
|
||||
export const bootstrap = qiankun_genBootstrap(clientRender, app);
|
||||
export const mount = qiankun_genMount('#${api.config.mountElementId}');
|
||||
export const unmount = qiankun_genUnmount();
|
||||
export const update = qiankun_genUpdate();
|
||||
|
@ -38,10 +38,12 @@ function getSlaveRuntime() {
|
||||
// 子应用生命周期钩子Bootstrap
|
||||
export function genBootstrap(oldRender, appPromise) {
|
||||
return async (props) => {
|
||||
if (typeof props !== 'undefined') {
|
||||
const slaveRuntime = getSlaveRuntime();
|
||||
if (slaveRuntime.bootstrap) {
|
||||
await slaveRuntime.bootstrap(props);
|
||||
}
|
||||
}
|
||||
render = oldRender;
|
||||
if (isPromise(appPromise)) {
|
||||
cacheAppPromise = appPromise;
|
||||
@ -61,8 +63,6 @@ export function genMount(mountElementId) {
|
||||
if (slaveRuntime.mount) {
|
||||
await slaveRuntime.mount(props);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新 clientRender 配置
|
||||
const clientRenderOpts = {
|
||||
// 支持通过 props 注入 container 来限定子应用 mountElementId 的查找范围
|
||||
@ -79,6 +79,7 @@ export function genMount(mountElementId) {
|
||||
if(props.onRouterInit){
|
||||
history.onRouterInit = props.onRouterInit;
|
||||
}
|
||||
}
|
||||
|
||||
// 第一次 mount 会自动触发 render,非第一次 mount 则需手动触发
|
||||
if (hasMountedAtLeastOnce) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoryHistory } from '@@/core/coreExports';
|
||||
import { createMemoryHistory, getHistory } from '@@/core/coreExports';
|
||||
import qiankunRender, { clientRenderOptsStack, history } from './lifecycles';
|
||||
|
||||
|
||||
@ -14,16 +14,18 @@ export function modifyClientRenderOpts(memo) {
|
||||
};
|
||||
}
|
||||
|
||||
export function modifyHistroy(memo) {
|
||||
export function modifyCreateHistroy(memo) {
|
||||
if (history.url) {
|
||||
const memoHistroy = createMemoryHistory();
|
||||
memoHistroy.push(history.url)
|
||||
return memoHistroy
|
||||
return createMemoryHistory
|
||||
}
|
||||
return memo;
|
||||
}
|
||||
|
||||
export function onRouterCreated({ router }) {
|
||||
if(history.url) {
|
||||
const memoryHistory = getHistory();
|
||||
memoryHistory.push(history.url)
|
||||
}
|
||||
if(history.onRouterInit){
|
||||
history.onRouterInit(router)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-request",
|
||||
"version": "2.0.0-rc.16",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-request",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -27,10 +27,11 @@
|
||||
"access": "public"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/compiler": "^2.0.0",
|
||||
"axios": "0.21.1"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { Logger } from '@fesjs/compiler';
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const logger = new Logger('fes:plugin-request');
|
||||
|
||||
export default (api) => {
|
||||
api.addRuntimePluginKey(() => 'request');
|
||||
// 配置
|
||||
@ -31,6 +34,11 @@ export default (api) => {
|
||||
api.onGenerateFiles(() => {
|
||||
// 文件写出
|
||||
const { dataField = '', base = '' } = api.config.request;
|
||||
|
||||
if (base) {
|
||||
// DEPRECATED
|
||||
logger.warn('[DEPRECATED]: reqeust base 即将废弃,建议使用 axios baseURL代替:https://github.com/axios/axios');
|
||||
}
|
||||
api.writeTmpFile({
|
||||
path: absoluteFilePath,
|
||||
content: requestTemplate
|
||||
|
@ -46,7 +46,7 @@ const CACHE_TYPE = {
|
||||
|
||||
const CACHE_DATA_MAP = new Map();
|
||||
|
||||
function genInnerKey(key, cacheType) {
|
||||
function genInnerKey(key, cacheType = 'ram') {
|
||||
if (cacheType !== CACHE_TYPE.ram) {
|
||||
return `${CACHE_KEY_PREFIX}${key}`;
|
||||
}
|
||||
@ -121,6 +121,57 @@ function getCacheData({ key, cacheType = 'ram' }) {
|
||||
}
|
||||
}
|
||||
|
||||
// 存储缓存队列
|
||||
const cacheStartFlag = new Map();
|
||||
const cachingQueue = new Map();
|
||||
|
||||
/**
|
||||
* 等上一次请求结果
|
||||
* 1. 如果上一次请求成功,直接使用上一次的请求结果
|
||||
* 2. 如果上一次请求失败,重启本次请求
|
||||
*/
|
||||
function handleCachingStart(ctx, config) {
|
||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
||||
const caching = cacheStartFlag.get(_key);
|
||||
if (caching) {
|
||||
return new Promise((resolve) => {
|
||||
const queue = cachingQueue.get(_key) || [];
|
||||
cachingQueue.set(_key, queue.concat(resolve));
|
||||
});
|
||||
}
|
||||
cacheStartFlag.set(_key, true);
|
||||
}
|
||||
|
||||
// 有请求成功的
|
||||
function handleCachingQueueSuccess(ctx, config) {
|
||||
// 移除首次缓存 flag
|
||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
||||
const queue = cachingQueue.get(_key);
|
||||
if (queue && queue.length > 0) {
|
||||
queue.forEach((resolve) => {
|
||||
resolve({
|
||||
response: ctx.response
|
||||
});
|
||||
});
|
||||
}
|
||||
cachingQueue.delete(_key);
|
||||
cacheStartFlag.delete(_key);
|
||||
}
|
||||
|
||||
// 处理请求失败
|
||||
function handleCachingQueueError(ctx, config) {
|
||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
||||
const queue = cachingQueue.get(_key);
|
||||
if (queue && queue.length > 0) {
|
||||
const firstResolve = queue.shift();
|
||||
firstResolve();
|
||||
cachingQueue.set(_key, queue);
|
||||
} else {
|
||||
cachingQueue.delete(_key);
|
||||
cacheStartFlag.delete(_key);
|
||||
}
|
||||
}
|
||||
|
||||
export default async (ctx, next) => {
|
||||
const { config } = ctx;
|
||||
if (config.cache) {
|
||||
@ -131,17 +182,28 @@ export default async (ctx, next) => {
|
||||
};
|
||||
return;
|
||||
}
|
||||
const result = await handleCachingStart(ctx, config);
|
||||
if (result) {
|
||||
Object.keys(result).forEach((key) => {
|
||||
ctx[key] = result[key];
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
await next();
|
||||
|
||||
if (config.cache) {
|
||||
const requestdata = checkHttpRequestHasBody(config.method) ? config.data : config.params;
|
||||
if (ctx.response && canCache(requestdata) && canCache(ctx.response.data)) {
|
||||
if (!ctx.error && ctx.response && canCache(requestdata) && canCache(ctx.response.data)) {
|
||||
handleCachingQueueSuccess(ctx, config);
|
||||
|
||||
setCacheData({
|
||||
key: ctx.key,
|
||||
data: ctx.response.data,
|
||||
...config.cache
|
||||
});
|
||||
} else {
|
||||
handleCachingQueueError(ctx, config);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1,17 +1,63 @@
|
||||
const requestMap = new Map();
|
||||
|
||||
const mergeRequestMap = new Map();
|
||||
const requestQueue = new Map();
|
||||
|
||||
function handleCachingStart(ctx) {
|
||||
const isRequesting = mergeRequestMap.get(ctx.key);
|
||||
if (isRequesting) {
|
||||
return new Promise((resolve) => {
|
||||
const queue = requestQueue.get(ctx.key) || [];
|
||||
requestQueue.set(ctx.key, queue.concat(resolve));
|
||||
});
|
||||
}
|
||||
mergeRequestMap.set(ctx.key, true);
|
||||
}
|
||||
|
||||
function handleRepeatRequest(ctx) {
|
||||
const queue = requestQueue.get(ctx.key);
|
||||
if (queue && queue.length > 0) {
|
||||
queue.forEach((resolve) => {
|
||||
if (ctx.error) {
|
||||
resolve({
|
||||
error: ctx.error
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
response: ctx.response
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
requestQueue.delete(ctx.key);
|
||||
mergeRequestMap.delete(ctx.key);
|
||||
}
|
||||
|
||||
export default async (ctx, next) => {
|
||||
const key = ctx.key;
|
||||
if (requestMap.get(key)) {
|
||||
if (ctx.config.mergeRequest) {
|
||||
const result = await handleCachingStart(ctx);
|
||||
if (result) {
|
||||
Object.keys(result).forEach((key) => {
|
||||
ctx[key] = result[key];
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (requestMap.get(ctx.key) && !ctx.config.mergeRequest) {
|
||||
ctx.error = {
|
||||
type: 'REPEAT',
|
||||
msg: '重复请求'
|
||||
};
|
||||
return;
|
||||
}
|
||||
requestMap.set(key, true);
|
||||
requestMap.set(ctx.key, true);
|
||||
}
|
||||
|
||||
await next();
|
||||
|
||||
requestMap.delete(key);
|
||||
if (ctx.config.mergeRequest) {
|
||||
handleRepeatRequest(ctx);
|
||||
} else {
|
||||
requestMap.delete(ctx.key);
|
||||
}
|
||||
};
|
||||
|
@ -65,11 +65,12 @@ function getRequestInstance() {
|
||||
addRequestInterceptors(instance, requestInterceptors);
|
||||
addResponseInterceptors(instance, responseInterceptors);
|
||||
|
||||
// 洋葱模型内部应该这是对数据的处理,避免有副作用调用
|
||||
scheduler.use(paramsProcess)
|
||||
.use(genRequestKey)
|
||||
.use(cacheControl)
|
||||
.use(preventRepeatReq)
|
||||
.use(throttle)
|
||||
.use(cacheControl)
|
||||
.use(axiosMiddleware)
|
||||
.use(resDataAdaptor)
|
||||
.use(resErrorProcess)
|
||||
@ -87,7 +88,7 @@ function getRequestInstance() {
|
||||
};
|
||||
}
|
||||
|
||||
// FEATURE 后续优化,使用 axios baseURL
|
||||
// DEPRECATED 废弃,使用 axios baseURL
|
||||
function handleApiPathBase(url, options = {}) {
|
||||
if (url.startsWith('http')) return url;
|
||||
|
||||
@ -120,6 +121,52 @@ function createContext(userConfig) {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function getResponseCode(response) {
|
||||
if (response) {
|
||||
if (response._rawData) return response._rawData.code;
|
||||
if (response.data) return response.data.code;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function skipErrorHandlerToObj(skipErrorHandler = []) {
|
||||
if (!Array.isArray(skipErrorHandler)) {
|
||||
skipErrorHandler = [skipErrorHandler];
|
||||
}
|
||||
|
||||
return skipErrorHandler.reduce((acc, cur) => {
|
||||
acc[cur] = true;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function handleRequestError({
|
||||
errorHandler = {},
|
||||
error,
|
||||
response,
|
||||
config
|
||||
}) {
|
||||
// 跳过所有错误类型处理
|
||||
if (config.skipErrorHandler === true) return;
|
||||
|
||||
const skipObj = skipErrorHandlerToObj(config.skipErrorHandler);
|
||||
const resCode = getResponseCode(response);
|
||||
|
||||
let errorKey = 'default';
|
||||
if (resCode && errorHandler[resCode]) {
|
||||
errorKey = resCode;
|
||||
} else if (error.type && errorHandler[error.type]) {
|
||||
errorKey = error.type;
|
||||
} else if (error.response && errorHandler[error.response.status]) {
|
||||
errorKey = error.response.status;
|
||||
}
|
||||
|
||||
if (!skipObj[errorKey] && errorHandler[errorKey]) {
|
||||
return errorHandler[errorKey](error);
|
||||
}
|
||||
}
|
||||
|
||||
export const request = (url, data, options = {}) => {
|
||||
if (typeof options === 'string') {
|
||||
options = {
|
||||
@ -132,10 +179,11 @@ export const request = (url, data, options = {}) => {
|
||||
const userConfig = userConfigHandler(url, data, options);
|
||||
const context = createContext(userConfig);
|
||||
|
||||
return currentRequestInstance.request(context).then(() => {
|
||||
return currentRequestInstance.request(context).then(async () => {
|
||||
if (!context.error) {
|
||||
return context.config.useResonse ? context.response : context.response.data;
|
||||
}
|
||||
await handleRequestError(context);
|
||||
return Promise.reject(context.error);
|
||||
});
|
||||
};
|
||||
|
@ -1,40 +1,16 @@
|
||||
import { isObject } from './helpers';
|
||||
|
||||
function handleAbnormalCode(errorHandler = {}, code, response) {
|
||||
if (errorHandler[code]) {
|
||||
errorHandler[code](response.data);
|
||||
} else if (errorHandler.default) {
|
||||
// 处理其他异常
|
||||
errorHandler.default({
|
||||
response
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function handleRequestError(errorHandler = {}, error) {
|
||||
if (error.type) {
|
||||
errorHandler[error.type] && errorHandler[error.type](error);
|
||||
} else if (error.response) {
|
||||
errorHandler[error.response.status] && errorHandler[error.response.status](error);
|
||||
} else if (errorHandler.default) {
|
||||
errorHandler.default(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 错误处理等副作用网上提
|
||||
export default async (ctx, next) => {
|
||||
const {
|
||||
error,
|
||||
errorHandler = {},
|
||||
response
|
||||
response,
|
||||
config
|
||||
} = ctx;
|
||||
if (response && isObject(response.data)) {
|
||||
if (!config.closeResDataCheck && response && isObject(response.data)) {
|
||||
const code = response.data.code;
|
||||
if (code !== '0') {
|
||||
handleAbnormalCode(errorHandler, code, response);
|
||||
ctx.error = response; // code 不为零进入 reject
|
||||
}
|
||||
} else if (error) {
|
||||
handleRequestError(errorHandler, error);
|
||||
}
|
||||
|
||||
await next();
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-sass",
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-sass",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -31,6 +31,6 @@
|
||||
"sass-loader": "^11.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0"
|
||||
"@fesjs/fes": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/plugin-vuex",
|
||||
"version": "2.0.0-rc.16",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/plugin-vuex",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
@ -30,7 +30,7 @@
|
||||
"@umijs/utils": "3.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"vuex": "^4.0.0"
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/preset-built-in",
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "2.0.1",
|
||||
"description": "@fesjs/preset-built-in",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
@ -32,7 +32,7 @@
|
||||
"@babel/plugin-proposal-pipeline-operator": "^7.12.13",
|
||||
"@babel/plugin-transform-runtime": "^7.12.13",
|
||||
"@babel/preset-env": "^7.12.13",
|
||||
"@fesjs/compiler": "^2.0.0-rc.5",
|
||||
"@fesjs/compiler": "^2.0.0",
|
||||
"@soda/friendly-errors-webpack-plugin": "^1.8.0",
|
||||
"@umijs/utils": "3.3.3",
|
||||
"@vue/babel-plugin-jsx": "^1.0.2",
|
||||
@ -48,7 +48,7 @@
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"core-js": "^3.8.3",
|
||||
"css-loader": "^5.0.1",
|
||||
"css-minimizer-webpack-plugin": "^1.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"envinfo": "^7.7.3",
|
||||
"file-loader": "^6.2.0",
|
||||
@ -58,7 +58,7 @@
|
||||
"less-loader": "^8.0.0",
|
||||
"mini-css-extract-plugin": "^1.3.5",
|
||||
"mockjs": "^1.1.0",
|
||||
"postcss": "^8.2.4",
|
||||
"postcss": "8.3.0",
|
||||
"postcss-flexbugs-fixes": "^5.0.2",
|
||||
"postcss-loader": "^4.2.0",
|
||||
"postcss-safe-parser": "^5.0.2",
|
||||
|
@ -39,7 +39,7 @@ export default function (api) {
|
||||
try {
|
||||
// clear output path before exec build
|
||||
if (process.env.CLEAR_OUTPUT !== 'none') {
|
||||
if (paths.absOutputPath && existsSync(paths.absOutputPath || '')) {
|
||||
if (paths.absOutputPath && existsSync(paths.absOutputPath)) {
|
||||
logger.debug(`Clear OutputPath: ${paths.absNodeModulesPath}`);
|
||||
rimraf.sync(paths.absOutputPath);
|
||||
}
|
||||
|
@ -21,8 +21,7 @@ function createRules({
|
||||
options,
|
||||
browserslist
|
||||
}) {
|
||||
const rule = webpackConfig.module.rule(lang).test(test);
|
||||
|
||||
function applyLoaders(rule, isCSSModules) {
|
||||
if (isDev) {
|
||||
rule.use('extra-css-loader')
|
||||
.loader(require.resolve('style-loader'))
|
||||
@ -37,9 +36,22 @@ function createRules({
|
||||
|
||||
rule.use('css-loader')
|
||||
.loader(require.resolve('css-loader'))
|
||||
.options({
|
||||
...config.cssLoader
|
||||
});
|
||||
.options(
|
||||
deepmerge(
|
||||
{
|
||||
importLoaders: 1,
|
||||
// https://webpack.js.org/loaders/css-loader/#onlylocals
|
||||
...(isCSSModules
|
||||
? {
|
||||
modules: {
|
||||
localIdentName: '[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
: {})
|
||||
},
|
||||
config.cssLoader || {}
|
||||
)
|
||||
);
|
||||
|
||||
rule.use('postcss-loader')
|
||||
.loader(require.resolve('postcss-loader'))
|
||||
@ -60,6 +72,11 @@ function createRules({
|
||||
.loader(require.resolve(loader))
|
||||
.options(options);
|
||||
}
|
||||
}
|
||||
|
||||
const rule = webpackConfig.module.rule(lang).test(test);
|
||||
applyLoaders(rule.oneOf('css-modules').resourceQuery(/module/), true);
|
||||
applyLoaders(rule.oneOf('css'), false);
|
||||
}
|
||||
|
||||
export default function createCssWebpackConfig({
|
||||
@ -102,9 +119,7 @@ export default function createCssWebpackConfig({
|
||||
if (!isDev) {
|
||||
webpackConfig.optimization
|
||||
.minimizer('css')
|
||||
.use(require.resolve('css-minimizer-webpack-plugin'), [{
|
||||
sourceMap: config.devtool !== false
|
||||
}]);
|
||||
.use(require.resolve('css-minimizer-webpack-plugin'), [{}]);
|
||||
}
|
||||
|
||||
return (options) => {
|
||||
|
@ -28,7 +28,7 @@ export default function (api) {
|
||||
// 修改路由
|
||||
'patchRoutes',
|
||||
// 修改histror
|
||||
'modifyHistroy',
|
||||
'modifyCreateHistroy',
|
||||
// 生成router时触发
|
||||
'onRouterCreated'
|
||||
]
|
||||
|
@ -31,7 +31,7 @@ const renderClient = (opts = {}) => {
|
||||
plugin.applyPlugins({
|
||||
key: 'onAppCreated',
|
||||
type: ApplyPluginsType.event,
|
||||
args: { app },
|
||||
args: { app, routes },
|
||||
});
|
||||
|
||||
if (rootElement) {
|
||||
@ -40,29 +40,7 @@ const renderClient = (opts = {}) => {
|
||||
return app;
|
||||
}
|
||||
|
||||
const getClientRender = (args = {}) => plugin.applyPlugins({
|
||||
key: 'render',
|
||||
type: ApplyPluginsType.compose,
|
||||
initialValue: () => {
|
||||
const opts = plugin.applyPlugins({
|
||||
key: 'modifyClientRenderOpts',
|
||||
type: ApplyPluginsType.modify,
|
||||
initialValue: {
|
||||
initialState: args.initialState,
|
||||
routes: args.routes || getRoutes(),
|
||||
plugin,
|
||||
rootElement: '{{{ rootElement }}}',
|
||||
{{#enableTitle}}
|
||||
defaultTitle: `{{{ defaultTitle }}}`,
|
||||
{{/enableTitle}}
|
||||
},
|
||||
});
|
||||
return renderClient(opts);
|
||||
},
|
||||
args,
|
||||
});
|
||||
|
||||
const beforeRender = async () => {
|
||||
const beforeRender = async ({rootElement}) => {
|
||||
const beforeRenderConfig = plugin.applyPlugins({
|
||||
key: "beforeRender",
|
||||
type: ApplyPluginsType.modify,
|
||||
@ -74,7 +52,7 @@ const beforeRender = async () => {
|
||||
let initialState = {};
|
||||
if (typeof beforeRenderConfig.action === "function") {
|
||||
const app = createApp(beforeRenderConfig.loading);
|
||||
app.mount('{{{ rootElement }}}');
|
||||
app.mount(rootElement);
|
||||
try {
|
||||
initialState = await beforeRenderConfig.action();
|
||||
} catch(e){
|
||||
@ -86,14 +64,31 @@ const beforeRender = async () => {
|
||||
return initialState;
|
||||
};
|
||||
|
||||
const completeClientRender = async () => {
|
||||
const initialState = await beforeRender();
|
||||
const clientRender = getClientRender({initialState});
|
||||
const app = clientRender();
|
||||
return app;
|
||||
};
|
||||
const getClientRender = (args = {}) => plugin.applyPlugins({
|
||||
key: 'render',
|
||||
type: ApplyPluginsType.compose,
|
||||
initialValue: async () => {
|
||||
const opts = plugin.applyPlugins({
|
||||
key: 'modifyClientRenderOpts',
|
||||
type: ApplyPluginsType.modify,
|
||||
initialValue: {
|
||||
routes: args.routes || getRoutes(),
|
||||
plugin,
|
||||
rootElement: '{{{ rootElement }}}',
|
||||
{{#enableTitle}}
|
||||
defaultTitle: `{{{ defaultTitle }}}`,
|
||||
{{/enableTitle}}
|
||||
},
|
||||
});
|
||||
const initialState = await beforeRender(opts);
|
||||
return renderClient({...opts, initialState});
|
||||
},
|
||||
args,
|
||||
});
|
||||
|
||||
const app = completeClientRender();
|
||||
const clientRender = getClientRender();
|
||||
|
||||
const app = clientRender();
|
||||
|
||||
{{{ entryCode }}}
|
||||
|
||||
|
@ -94,24 +94,21 @@ const genRoutes = function (parentRoutes, path, parentRoutePath, config) {
|
||||
// 路由名称
|
||||
const routeName = getRouteName(parentRoutePath, fileName);
|
||||
const componentPath = getComponentPath(parentRoutePath, fileName, config);
|
||||
const routeMeta = routeMetaBlock?.content ? JSON.parse(routeMetaBlock.content) : {};
|
||||
const routeConfig = {
|
||||
path: routePath,
|
||||
component: componentPath,
|
||||
name: routeMeta.name || routeName,
|
||||
meta: routeMeta
|
||||
};
|
||||
if (hasLayout) {
|
||||
if (fileName === 'layout') {
|
||||
layoutRoute.component = componentPath;
|
||||
} else {
|
||||
layoutRoute.children.push({
|
||||
path: routePath,
|
||||
component: componentPath,
|
||||
name: routeName,
|
||||
meta: routeMetaBlock?.content ? JSON.parse(routeMetaBlock.content) : {}
|
||||
});
|
||||
layoutRoute.children.push(routeConfig);
|
||||
}
|
||||
} else {
|
||||
parentRoutes.push({
|
||||
path: routePath,
|
||||
component: componentPath,
|
||||
name: routeName,
|
||||
meta: routeMetaBlock?.content ? JSON.parse(routeMetaBlock.content) : {}
|
||||
});
|
||||
parentRoutes.push(routeConfig);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -166,7 +163,7 @@ const rank = function (routes) {
|
||||
rank(item.children);
|
||||
}
|
||||
});
|
||||
routes = routes.sort((a, b) => b.count - a.count);
|
||||
routes.sort((a, b) => b.count - a.count);
|
||||
};
|
||||
|
||||
const getRoutes = function ({ config, absPagesPath }) {
|
||||
|
@ -3,31 +3,34 @@ import { plugin } from '@@/core/coreExports';
|
||||
|
||||
export function getRoutes() {
|
||||
const routes = {{{ routes }}};
|
||||
|
||||
plugin.applyPlugins({
|
||||
key: 'patchRoutes',
|
||||
type: ApplyPluginsType.event,
|
||||
args: { routes },
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
const ROUTER_BASE = '{{{ routerBase }}}';
|
||||
let router = null;
|
||||
let history = null;
|
||||
export const createRouter = () => {
|
||||
export const createRouter = (routes) => {
|
||||
if (router) {
|
||||
return router;
|
||||
}
|
||||
history = plugin.applyPlugins({
|
||||
key: 'modifyHistroy',
|
||||
const createHistory = plugin.applyPlugins({
|
||||
key: 'modifyCreateHistroy',
|
||||
type: ApplyPluginsType.modify,
|
||||
initialValue: {{{ CREATE_HISTORY }}}(ROUTER_BASE),
|
||||
args: {
|
||||
base: ROUTER_BASE
|
||||
},
|
||||
initialValue: {{{ CREATE_HISTORY }}},
|
||||
});
|
||||
history = createHistory(ROUTER_BASE);
|
||||
// 修改routes
|
||||
plugin.applyPlugins({
|
||||
key: 'patchRoutes',
|
||||
type: ApplyPluginsType.event,
|
||||
args: { routes },
|
||||
});
|
||||
router = createVueRouter({
|
||||
history,
|
||||
routes: getRoutes()
|
||||
routes
|
||||
});
|
||||
|
||||
plugin.applyPlugins({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createRouter } from "./routes";
|
||||
|
||||
export function onAppCreated({ app }) {
|
||||
const router = createRouter();
|
||||
export function onAppCreated({ app, routes }) {
|
||||
const router = createRouter(routes);
|
||||
app.use(router);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/runtime",
|
||||
"version": "2.0.0-rc.5",
|
||||
"version": "2.0.0",
|
||||
"description": "@fesjs/runtime",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
|
@ -1,5 +1,5 @@
|
||||
// fes.config.js 只负责管理 cli 相关的配置
|
||||
import pxtoviewport from 'postcss-px-to-viewport';
|
||||
import pxtoviewport from '@ttou/postcss-px-to-viewport';
|
||||
|
||||
|
||||
export default {
|
||||
@ -10,7 +10,7 @@ export default {
|
||||
publicPath: '/',
|
||||
request: {
|
||||
base: '/ras-mas',
|
||||
dataField: ''
|
||||
dataField: 'result'
|
||||
},
|
||||
html: {
|
||||
title: '拉夫德鲁'
|
||||
|
@ -41,13 +41,14 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10",
|
||||
"postcss-px-to-viewport": "1.1.1"
|
||||
"@webank/eslint-config-webank": "0.3.0",
|
||||
"@ttou/postcss-px-to-viewport": "1.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-icon": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-request": "^2.0.0-rc.0",
|
||||
"debounce": "1.2.1",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/plugin-icon": "^2.0.0",
|
||||
"@fesjs/plugin-request": "^2.0.0",
|
||||
"vue": "^3.0.5"
|
||||
},
|
||||
"private": true
|
||||
|
@ -1,13 +1,18 @@
|
||||
export const request = {
|
||||
errorHandler: {
|
||||
111(responseData) {
|
||||
console.log(responseData);
|
||||
111() {
|
||||
console.log('root:111');
|
||||
},
|
||||
404() {
|
||||
console.log('to 404 page');
|
||||
500() {
|
||||
console.log('500 error');
|
||||
},
|
||||
default(error) {
|
||||
console.log(error.response.data);
|
||||
console.log('default error');
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function patchRoutes() {
|
||||
console.log('patchRoutes');
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
import { request } from '@fesjs/fes';
|
||||
import { debounce } from 'debounce';
|
||||
|
||||
export const debounceRequest = debounce(request, 300);
|
@ -2,38 +2,96 @@
|
||||
<div class="onepiece">
|
||||
fes & 拉夫德鲁<br />
|
||||
<fes-icon :spin="true" class="one-icon" type="smile" @click="clickIcon" />
|
||||
<div v-if="loading" class="loading">loading</div>
|
||||
<div v-else class="data">{{data}}</div>
|
||||
</div>
|
||||
</template>
|
||||
<config>
|
||||
{
|
||||
"title": "首页",
|
||||
"name": "testIndex",
|
||||
"layout": "false"
|
||||
}
|
||||
</config>
|
||||
<script>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRouter, useRequest } from '@fesjs/fes';
|
||||
import { ref } from 'vue';
|
||||
import { request } from '@fesjs/fes';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
const rotate = ref(90);
|
||||
const router = useRouter();
|
||||
onMounted(() => {
|
||||
console.log(router);
|
||||
console.log('mounted1!!');
|
||||
});
|
||||
const clickIcon = () => {
|
||||
console.log('click Icon');
|
||||
};
|
||||
const { loading, data } = useRequest('/api', null, {
|
||||
dataField: false
|
||||
// request('/api', null, {
|
||||
// mergeRequest: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// mergeRequest: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// mergeRequest: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// throttle: 3000,
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
|
||||
// setTimeout(() => {
|
||||
// request('/api', null, {
|
||||
// throttle: 3000,
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// }, 1000);
|
||||
|
||||
// setTimeout(() => {
|
||||
// request('/api', null, {
|
||||
// throttle: 3000,
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// request('/api', null, {
|
||||
// throttle: 3000,
|
||||
// cache: true
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// });
|
||||
// }, 3200);
|
||||
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
request('/api', null, {
|
||||
cache: true
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
|
||||
// request('/api', null, {
|
||||
// // skipErrorHandler: [500]
|
||||
// }).then((res) => {
|
||||
// console.log(res);
|
||||
// }).catch((err) => {
|
||||
// console.log('inner error', err);
|
||||
// });
|
||||
return {
|
||||
loading,
|
||||
data,
|
||||
fes,
|
||||
rotate,
|
||||
clickIcon
|
||||
|
@ -35,6 +35,7 @@ export default {
|
||||
footer: "Created by MumbleFe",
|
||||
multiTabs: false,
|
||||
navigation: "mixin",
|
||||
theme: 'light',
|
||||
menus: [
|
||||
{
|
||||
name: "index",
|
||||
@ -81,4 +82,7 @@ export default {
|
||||
strict: true,
|
||||
},
|
||||
dynamicImport: true,
|
||||
extraBabelPlugins: [
|
||||
['import', { libraryName: 'ant-design-vue', libraryDirectory: 'es', style: 'css' }, 'ant-design-vue'],
|
||||
]
|
||||
};
|
||||
|
@ -43,20 +43,20 @@
|
||||
"access": "public"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@webank/eslint-config-webank": "0.2.10"
|
||||
"@webank/eslint-config-webank": "0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fesjs/fes": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-access": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-layout": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-locale": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-model": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-enums": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-jest": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-vuex": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-request": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-qiankun": "^2.0.0-rc.0",
|
||||
"@fesjs/plugin-sass": "^2.0.0-rc.0",
|
||||
"@fesjs/fes": "^2.0.0",
|
||||
"@fesjs/plugin-access": "^2.0.0",
|
||||
"@fesjs/plugin-layout": "^2.0.0",
|
||||
"@fesjs/plugin-locale": "^2.0.0",
|
||||
"@fesjs/plugin-model": "^2.0.0",
|
||||
"@fesjs/plugin-enums": "^2.0.0",
|
||||
"@fesjs/plugin-jest": "^2.0.0",
|
||||
"@fesjs/plugin-vuex": "^2.0.0",
|
||||
"@fesjs/plugin-request": "^2.0.0",
|
||||
"@fesjs/plugin-qiankun": "^2.0.0",
|
||||
"@fesjs/plugin-sass": "^2.0.0",
|
||||
"ant-design-vue": "2.0.0",
|
||||
"vue": "^3.0.5",
|
||||
"vuex": "^4.0.0"
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<div class="haizekuo">
|
||||
<div :class="$style.red">
|
||||
<a-input placeholder="请输入。。。" />
|
||||
<a-button type="primary">Primary</a-button>
|
||||
<div>国际化 {{t("test")}}</div>
|
||||
fes & 拉夫德鲁 <br />
|
||||
<access :id="accessId"> accessOnepicess1 <input /> </access>
|
||||
@ -22,8 +24,16 @@ import { ref, onMounted } from 'vue';
|
||||
import {
|
||||
useAccess, useRouter, useI18n, locale, enums, request
|
||||
} from '@fesjs/fes';
|
||||
import { Button, Input } from 'ant-design-vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
[Button.name]: Button,
|
||||
[Input.name]: Input,
|
||||
},
|
||||
mounted(){
|
||||
console.log("$style:", this.$style)
|
||||
},
|
||||
setup() {
|
||||
const fes = ref('fes upgrade to vue3');
|
||||
const accessOnepicess = useAccess('/onepiece1');
|
||||
@ -62,8 +72,11 @@ export default {
|
||||
}
|
||||
]
|
||||
});
|
||||
console.log(roles);
|
||||
console.log(enums.get('status', {
|
||||
console.log('enums roles=>', roles);
|
||||
console.log('enums roles[1]=>', enums.get('roles', '1'));
|
||||
console.log('enums status[0]=> ', enums.get('status', 0));
|
||||
console.log('enums status concat', enums.concat('status', [['3', '普通的']], { extend: [{ key: 'name', dir: 'value' }] }));
|
||||
console.log('enums status get extend=>', enums.get('status', {
|
||||
extend: [
|
||||
{
|
||||
key: 'name',
|
||||
@ -120,8 +133,11 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.haizekuo {
|
||||
/* background: url('../images/icon.png'); */
|
||||
<style module>
|
||||
.red {
|
||||
color: red;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@fesjs/fes",
|
||||
"version": "2.0.0-rc.18",
|
||||
"version": "2.0.1",
|
||||
"description": "一个好用的前端管理台快速开发框架",
|
||||
"preferGlobal": true,
|
||||
"scripts": {
|
||||
@ -39,9 +39,9 @@
|
||||
"strong"
|
||||
],
|
||||
"dependencies": {
|
||||
"@fesjs/compiler": "^2.0.0-rc.5",
|
||||
"@fesjs/preset-built-in": "^2.0.0-rc.18",
|
||||
"@fesjs/runtime": "^2.0.0-rc.5",
|
||||
"@fesjs/compiler": "^2.0.0",
|
||||
"@fesjs/preset-built-in": "^2.0.1",
|
||||
"@fesjs/runtime": "^2.0.0",
|
||||
"@umijs/utils": "3.3.3",
|
||||
"resolve-cwd": "^3.0.0"
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user