# 目录结构

快速入门中,大家对框架应该有初步的印象,接下来我们了解下目录结构。

# 目录规范

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
    │       ├── components
    │       │   └── common.vue
    │       ├── edit
    │       │   └── index.vue
    │       └── index.vue
    └── static
        └── favicon.ico

# fes.config.js

配置文件

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,
    // 是否开启路由懒加载
    lazyRouter: false,
    // 是否开启 gzip 压缩,也可以传一个 obj 声明压缩参数
    compress: 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: 'internationalization,base on',
                    achieve: 'to achieve.',
                    ui: 'UI components'
                },
                title: 'title'
            }
        }
    }
};

# mock.js

当运行环境--env=local时fes.js启动mock模拟后台服务,配置如下:

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,其他接口使用请求转发:

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中编写全局设置,如引入其他第三方插件、注册全局事件、设置应用权限等。

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 (opens new window)路由配置。

# 规则

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,内容如下:

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,在页面中使用如下:

<a target="_blank" href="static/1.txt">
    点击下载 1.txt
</a>

# webpack.config.js

自定义webpack配置
mode是编译命令,configs则是编译中的默认配置

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 {};
};

# 自定义目录结构

除了上述目录结构,也可以根据自己的需要增加其他目录,但不能更改现有的目录结构。

上次编辑时间: 5/25/2022, 2:59:01 AM