fes.js/packages/fes-doc/docs/guide/directory-structure.md
2020-09-25 17:59:15 +08:00

367 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 目录结构
在[快速入门](#/guide/play)中,大家对框架应该有初步的印象,接下来我们了解下目录结构。
## 目录规范
Fes.js遵循 **“约定优于配置”** 的原则,推荐的目录结构如下:
```
fes-project
├── .eslintrc.js
├── fes.config.js
├── mock.js(可选)
├── webpack.config.js(可选)
├── package.json
└── src
├── app.js
├── assets
│   ├── images
│   │   ├── bg.png
│   │   └── logo.png
│   ├── styles
│   │   ├── main.scss
│   │   └── variables.scss
│   └── utils.js
├── components
│   ├── fesHeader.vue
│   ├── fesLeft.vue
│   └── wbDate.vue
├── pages
│   ├── home
│   │   └── index.vue
│   └── list
│   ├── edit
│   │   └── index.vue
│   └── index.vue
└── static
└── favicon.ico
```
## fes.config.js
配置文件
```javascript
module.exports = {
// 是否采用行内 sso 登录
sso: false,
// 可选有vertical、horizontal默认vertical
mode: 'vertical',
// 可选有blue、dark默认blue
theme: 'blue',
// 项目名称
fesName: 'xx 运营平台',
// 图标,可以将 favicon.ico 文件放入 src/static
favicon: 'static/favicon.ico',
// 是否显示左侧区域默认true
FesLeft: true,
// 是否显示头部区域默认为false
FesHeader: false,
// 环境变量配置, 默认使用local环境
env: {
// 本地开发环境
local: {
api: ''
},
// 开发环境 fes [dev/build] --env=develop
develop: {
api: 'http://h.adm-test.webank.io'
},
// 生产环境 fes [dev/build] --env=prod
prod: {
api: 'http://adm.webank.io'
}
},
// 配置角色控制显示的菜单内容和路由权限使用FesApp.setRole('unLogin')来修改当前用户的角色
roles: {
unLogin: ['/home'],
service: ['/list'],
admin: ['/list', '/api/fes']
},
// 数据字典
map: {
status: [['1', '成功'], ['2', '失败']]
},
// 左侧菜单配置,仅支持二级菜单
menu: [
{
// 一级菜单支持配置icon
icon: 'static/bell.png',
// 菜单名称
title: '接口',
// 菜单对应的路由
path: '/api',
// 子菜单
subMenu: [
{
title: 'Fes',
path: '/api/fes'
},
{
title: 'FesApp',
path: '/api/fesApp'
}
]
}
],
// 国际化 默认为zh-cn
i18n: {
locale: 'en',
messages: {
'zh-cn': {
menu: {
interface: '接口'
},
overview: '概述',
i18n: {
internationalization: '国际化,基于',
achieve: '实现。',
ui: 'UI组件'
},
title: '标题'
},
en: {
menu: {
interface: 'interface'
},
overview: 'Overview',
i18n: {
internationalization: 'internationalizationbase on',
achieve: 'to achieve.',
ui: 'UI components'
},
title: 'title'
}
}
}
};
```
## mock.js
当运行环境`--env=local`时fes.js启动mock模拟后台服务配置如下
```javascript
module.exports = function(cgiMock, Mock, faker) {
var Random = Mock.Random;
//前缀,全局(可选)
cgiMock.prefix = '';
// 返回一个数字
cgiMock('/number', 123);
// 返回一个json
cgiMock({
url: '/json',
result: {
"code": "400101",
"msg": "不合法的请求:Missing cookie 'wb_app_id' for method parameter of type String",
"transactionTime": "20170309171146",
"success": false
}
});
//利用mock.js 产生随机文本
cgiMock('/text', Random.cparagraph());
// 返回一个字符串 利用mock.js 产生随机字符
cgiMock('/string', Mock.mock({
"string|1-10": "★"
}));
// 正则匹配url, 返回一个字符串
cgiMock(/\/abc|\/xyz/, 'regexp test!');
// option.result 参数如果是一个函数, 可以实现自定义返回内容, 接收的参数是是经过 express 封装的 req 和 res 对象.
cgiMock(/\/function$/, function (req, res) {
res.send('function test');
});
// 返回文本 fs.readFileSync
cgiMock('/file', cgiMock.file('./test.json'));
// 更复杂的规则配置
cgiMock({
url: /\/who/,
method: 'GET',
result: function (req, res) {
if (req.query.name === 'kwan') {
res.json({'kwan': '孤独患者'});
}
else {
res.send('Nooooooooooo');
}
},
headers: {
'Content-Type': 'text/plain',
'Content-Length': '123',
'ETag': '12345'
},
cookies: [
{name: 'myname', value: 'kwan', maxAge: 900000, httpOnly: true}
],
//接口随机延迟
timeout: Mock.mock({
"number|1000-5000": 1000
}).number
});
// 转发所有请求到指定URL可以解决跨域
cgiMock.proxy('http://test-adm.weoa.com/xxx')
}
```
如果希望部分接口使用Mock其他接口使用请求转发
```js
module.exports = function(cgiMock, Mock, faker) {
//新的接口 走数据模拟
cgiMock('new', function(req, res){
)}
//老的接口直接调后台接口
cgiMock.proxy('http://test-adm.weoa.com/xxx')
}
```
## app.js
`fes-core` 初始化内部逻辑后执行导出的函数,建议在`app.js`中编写全局设置,如引入其他第三方插件、注册全局事件、设置应用权限等。
```js
import Vue from 'vue';
import somePlugin from 'somePlugin'
import './assets/styles/main.scss';
Vue.use(somePlugin)
export default function () {
setTimeout(() => {
this.FesApp.setRole('admin', false);
}, 1000);
// 设置路由钩子
this.FesApp.setBeforeRouter((from, to, next) => {
next();
});
this.FesApp.setAfterRouter((route) => {
console.log(`您浏览到了${route.path}`);
});
// 设置AJAX配置
this.FesApi.option({
});
// 设置响应结构
this.FesApi.setResponse({
successCode: '0',
codePath: 'code',
messagePath: 'msg',
resultPath: 'result'
});
}
```
## src/assets
存放公共静态资源,例如样式文件、图片资源等。
## src/components
在这个目录下的*.vue组件在编译后会自动注册为全局组件可以直接在vue单文件的`<template></template>`中使用。
### 规则
读取文件名称作为组件名称进行注册,例如`src/components/message.vue`注册的全局组件名称为`message`
### 特殊组件
`fesHeader.vue`
用于自定义页面头部。参数`FesHeader`控制`fesHeader.vue` 是否显示。在`fes.config.js`中配置`FesHeader`定义全局的,也可以在页面组件中单独配置`FesHeader`
`fesLeft.vue`
用于自定义菜单栏。配置参数`FesLeft`控制`fesLeft.vue` 是否显示。在`fes.config.js`中配置`FesLeft`定义全局的,也可以在页面组件中单独配置`FesLeft`
## src/pages
`pages`目录下编写页面,`Fes.js`会根据`pages`目录以及文件结构自动生成[Vue-router](https://router.vuejs.org/zh-cn/)路由配置。
### 规则
```dir
pages
├── index.vue # 根路由页面 路径 index.html#/
├── a.vue # 路径 /a
├── b # 文件夹b
│ ├── index.vue # 路径 /b
│ ├── @id.vue # 动态路由 /b/:id
│ └── c.vue # 路径 /b/c
└── layout.vue # 根路由下所有page共用的外层
```
1. 如果目录下有`layout.vue`,则子目录对应的路径是当前目录对应路径的子路由。如果没有则子目录对应的路径和当前目录对应路径是平级的。
2. 带参数的路径使用`@id.vue`的形式
### 编译
编译后在`.cache`目录下生成`routeConfig.js`,内容如下:
```js
import layout from 'D:\\git\\fes-template\\src\\pages\\layout.vue';
import index from 'D:\\git\\fes-template\\src\\pages\\index.vue';
import a from 'D:\\git\\fes-template\\src\\pages\\a.vue';
import b_index from 'D:\\git\\fes-template\\src\\pages\\b\\index.vue';
import b__id from 'D:\\git\\fes-template\\src\\pages\\b\\@id.vue';
export default {
'/': {
component: layout,
subRoutes: {
'/' : {
name: 'index', component: index
},
'/a' : {
name: 'a', component: a
},
'/b' : {
name: 'b_index', component: b_index
},
'/b/:id' : {
name: 'b__id', component: b__id
}
}
}
};
```
## src/static
不需要经过webpack编译处理的静态资源可以在页面中通过 URL(static/xxx) 直接引用。
例如有文件`src/static/1.txt`,在页面中使用如下:
```html
<a target="_blank" href="static/1.txt">
点击下载 1.txt
</a>
```
## webpack.config.js
自定义`webpack`配置
`mode`是编译命令,`configs`则是编译中的默认配置
```js
const CspHtmlWebpackPlugin = require('csp-html-webpack-plugin');
module.exports = function (mode, configs, webpack) {
if (mode === 'build') {
return {
plugins: [new CspHtmlWebpackPlugin({
'base-uri': "'self'",
'object-src': "'none'",
'script-src': [
"'self'"
],
'style-src': [
"'self'"
],
'connect-src': [
"'self'",
'http://adm.webank.io'
],
'img-src': [
'data:',
"'self'"
]
})]
};
}
return {};
};
```
## 自定义目录结构
除了上述目录结构,也可以根据自己的需要增加其他目录,但不能更改现有的目录结构。