•  

【TFWEB】TFWEB框架开发手册V1.0

发表于 2018-07-10,阅读 1

目录结构

模型

基类 TFAction

get - 获取一行数据

gets - 获取多行数据

getID - 获取数据主键

add - 添加一行数据

mod - 修改一行数据

del - 删除一行数据

getLIID - 获取最新插入数据主键

视图

模板

控制器

路由

介绍

路由入口文件是项目根目录上的 RouteMap.php 和 RouteMapConsole.php

其中 RouteMap.php 用于 WebServer 的路由程序

然后 RouteMapConsole.php 用于控制台 的路由程序

RouteMap

内容如下

// load config file
if(strstr(getenv('OS'),'Windows')) define('OS_WINNT', 1);
define('PATH_SLASH', (defined('OS_WINNT')) ? '\\' : '/');
define('DOC_ROOT_DIR', dirname(__FILE__). PATH_SLASH);
define('WEB_INF', DOC_ROOT_DIR. 'WEB-INF'. PATH_SLASH);
define('REQ_URI', $_SERVER['QUERY_STRING']);
include(WEB_INF. 'WebConfig.inc.php');

// load entry
RouteTool::addEntry('api', RouteTool::T_ENTRY_REST, 'REST', 'api/');
RouteTool::addEntry('admin', RouteTool::T_ENTRY_HTML, 'Admin', 'admin/');
RouteTool::addEntry('demo', RouteTool::T_ENTRY_HTML, 'Demo', 'demo/');
RouteTool::mapEntry();

路由规则

TFWEB的路由是根据请求路径(request uri)进行匹配的,我们可以根据请求路径前缀(request uri prefix)进行不同的路由转向。


每一组路由规则都是由一个名称,一个类型,一个入口程序文件名,一个请求路径前缀组成的。

RouteTool::addEntry(
    'demo', // 表示入口的名称,重复会被覆盖
    RouteTool::T_ENTRY_HTML, // 入口的类型,目前支持 HTML 和 REST
    'Demo', // 入口的程序文件名称
    'demo/' // 入口匹配的请求地址前缀
);

默认规则

通常情况下我们可以不设置任何规则,使用默认路由规则进行处理。


系统会自动添加如下规则,用以匹配全部请求地址

RouteTool::addEntry('Default', RouteTool::T_ENTRY_HTML, "Default", "");

入口程序

入口程序保存在 WEB-INF/Classes/Controllers/Route/ 目录下


可以通过复制现有的入口程序进行简单修改来创建新的入口程序

请求路径

介绍

请求路径规范可以参考RESTFul规范,我们的请求路径也是按照这个规范设计的。


即:[资源1][参数1][资源2][参数2]...

示例

/user - 用户列表

/user/3 - 用户3的详情

/categ/6/news - 分类6下面的新闻列表

/categ/6/news/10010 - 分类6下面的新闻10010的详情

映射视图

介绍

每一个请求路径都对应这一套负责处理的视图


一套视图包括程序逻辑和前端模板两个部分

对应关系

示例1

/user

WEB-INF/Classes/Views/user/index.inc.php

WEB-INF/Templates/Tpl/user/index.html

示例2

/user/3

WEB-INF/Classes/Views/userDetail.inc.php

WEB-INF/Templates/Tpl/userDetail.html

RESTFul

默认项目根目录会有一个 api 目录,该目录下面会有一个 REST.php 路由程序

这个程序用来实现 RESTFul 风格的接口

路由入口文件 REST.php 内容

class TFREST extends FieldSystemRest {
    
    public function __construct($opts){
        parent::__construct($opts);
    }
    
    protected function prepareData(){
        $myRESTLoaderObj = new TFRESTLoader($this->PEO);
        $myRESTLoaderObj->auth(
                
                // enable auth
                true,
                
                // rules
                array(
                
                    // default auth method
                    'default'=>"authDefault",
                    
                    // other auth methods
                    'matches'=>array(
                        
                        "user.add"=>"authAdmin", // add for user use authAdmin auth method
                    
                    ),
                    
                    // no auth models
                    'noAuthModels'=>array(
                    
                        "user.get"=>true, // get of user is public
                        
                        "demo"=>true, // all of demo is public
                    ),
                    
                )
            );
        $myRESTLoaderObj->load($this->PEO->input->server->TFREST);
        return $myRESTLoaderObj->getData();
    }
}

$pageObj = new TFREST(array(

    ));
$pageObj->OP();

前端UI

基础

前端UI框架基于MVVM的Vue开发,驱动文件是 js/plugins/UI.Vue.js


每一个前端UI的实例都是一整套实现表格(table)、表单(form)、对话框(dialog)等等元素渲染的组件库


这里我们提供了一个PC版本的库,一个移动版本的库


PC版本的库风格为 Inspinia 前端框架风格(该前端框架原基于Bootstrap实现),库文件是 js/plugins/UI.Vue.Inspinia.js


移动版本的库风格为 SUI Mobile 前端框架风格,库文件是 js/plugins/UI.Vue.SuiMobile.js


在前端组件库基础之上我们就可以组件自己的项目组件库了,我们的官方项目 TFHome 的组件库文件是 js/UI.Vue.Template.js 和 js/UI.Vue.TemplateM.js,分别对应的PC版本和移动版本


在后面就是我们的业务层的实现了,这里面还是以DOM风格的jQuery为基础,对应的文件是 js/UI.Vue.TFHome.js 和 js/UI.Vue.TFHomeM.js,分别对应的PC版本和移动版本

入门

我们提供了几个方法用来管理组件库当中的组件,用于方便的调用组件,实例化组件

系统组件

表单

<!-- 输入框 -->
<form-text :elem="elem"></form-text>

<!-- 密码框 -->
<form-password :elem="elem"></form-password>

<!-- 单选框 -->
<form-radios :elem="elem"></form-radios>

<!-- 复选框 -->
<form-checkboxs :elem="elem"></form-checkboxs>

<!-- 下拉框 -->
<form-select :elem="elem"></form-select>

<!-- 多行输入框 -->
<form-textarea :elem="elem"></form-textarea>

<!-- 文件上传框 -->
<form-file :elem="elem"></form-file>

<!-- 提交按钮 -->
<form-submit :elem="elem"></form-submit>

<!-- 普通按钮 -->
<form-button :elem="elem"></form-button>

<!-- 单照片 -->
<form-photo :elem="elem"></form-photo>

<!-- 验证码 -->
<form-vrycode :elem="elem"></form-vrycode>

<!-- TFEditor -->
<form-tftb :elem="elem"></form-tftb>

<!-- 表单项目容器(单行) -->
<form-row-box :elem="elem"></form-row-box>

<!-- 表单项目容器(提交行) -->
<form-row-boxright :elem="elem"></form-row-boxright>

<!-- 表单 -->
<form-box :info="info" :hiddens="hiddens" :callbacks="callbacks" :validators="validators"></form-box>

<!-- 对话框 -->
<dialog-box :args="args"></dialog-box>

用户组件

自定义表单示例

Vue.component('form-example', {
        props: {
            indlg: {
                default: false
            }
        },
        data: function () {
            return {
                info: {
                    title: '测试表单',
                    descript: '测试表单',
                    method: 'post',
                    action: $.U('api/demo/_form_formExample')
                },
                validators: {
                    text: {triggers: ['blur'], rules: [{min: 4, msg: '用户名最少4个字符'}, {max: 20, msg: '用户名最多20个字符'}]},
                    password: {triggers: ['blur'], rules: [{min: 4, msg: '密码最少4个字符'}]}
                },
                elements: {
                    text: {
                        label: '用户名',
                        name: "text",
                        placeholder: "enter a word",
                        error: ""
                    },
                    password: {
                        label: '密码',
                        name: "password",
                        placeholder: "enter a password",
                        error: ""
                    },
                    submit: {
                        name: "submit",
                        value: "提交"
                    },
                    button: {
                        name: "button",
                        value: "关闭"
                    }
                },
                callbacks: {
                    success: function (d) {
                        alert(JSON.stringify(d));
                    },
                    ready: function () {

                    }
                }
            }
        },
        methods: {
            validate: function (obj, name, msg) {
                if (msg != null) {
                    this.elements[name].error = msg;
                }
                else {
                    this.elements[name].error = '';
                }
            },
            closeParentDlg: function () {
                VueGEC.$emit('closeDlg');
            }
        },
        template: '<form-box :info="info" :callbacks="callbacks" :validators="validators" @validate="validate">' +
        '<form-row-box :elem="elements.text">' +
        '   <form-text :elem="elements.text"></form-text>' +
        '</form-row-box>' +
        '<form-row-box :elem="elements.password">' +
        '   <form-password :elem="elements.password"></form-password>' +
        '</form-row-box>' +
        '<form-row-boxright>' +
        '   <form-submit :elem="elements.submit"></form-submit> ' +
        '   <form-button :elem="elements.button" :fnclick="closeParentDlg" v-if="indlg == true"></form-button>' +
        '</form-row-boxright>' +
        '</form-box>'
    });

加载组件

我们可以使用 $.componentLoad( [组件名称], [组件实例id], [组件实例化参数对象] ) 调用一个组件

$.componentLoad('form-user-login', 'form-user-login', {

    // compBox 参数用来指定新组件实例放置的父容器的selector
    // 也就是说你要告诉系统你想把这个组件创建在什么位置上
    compBox : '#user-login',

    // compBoxCB 当父容器无法描述为一个selector的时候就要用到这个参数了
    // 回调函数的唯一参数 o 就是新组件的句柄,你可以通过任意方式将其移动到指定位置上
    compBoxCB : function(o){
        $('.user-icon').after(o);
    },

    // bindData 想组件传入参数,注意这里面设置的任何参数都会添加到组件实例的属性里
    // 记得不要忘记在组件定义的时候用 props 接收一下哦~~
    bindData : {
        args : {

        }
    }
});

更新组件

$.componentUpdate( [组件实例id], [更新数据] )

$.componentUpdate('form-user-login', {
    args : {

    }
});

批量更新组件

$.componentMultiUpdate( [多组件实例id的匹配正则表达式], [更新数据] )

$.componentMultiUpdate( /^form\-user/ , {
    args : {

    }
});

异步组件

form-xxx

声明

Vue.component('form-login', function (resolve, reject) {
    resolve(TFHomeUI._makeAsyncFormComponent('login'));
});

form-xxx异步组件通过TFHomeUI._makeAsyncFormComponent得到组件参数,而真正的组件参数在TFHomeUI对象内部设定

参数

window.TFHomeUI = {

        asyncDialogFormCompoents : {

            ...

            forms: {

                //////// login ////////
                login: {
                    info: {
                        title: '用户登录',
                        descript: '用户登录',
                        method: 'post',
                        action: $.U('model/user/login')
                    },
                    validators: {
                        user: {triggers: ['blur'], rules: [{min: 2, msg: '用户名最少2个字符'}, {max: 20, msg: '用户名最多20个字符'}]},
                        pwd: {triggers: ['blur'], rules: [{min: 6, msg: '密码最少6个字符'}]},
                        vrycode: {triggers: ['blur'], rules: [{regex: /^[0-9]{4}$/, msg: '验证码错误'}]}
                    },
                    elements: {
                        user: {
                            type: 'text',
                            label: '用户名',
                            name: "user",
                            placeholder: "用户名",
                            error: ""
                        },
                        pwd: {
                            type: 'password',
                            label: '密码',
                            name: "pwd",
                            placeholder: "密码",
                            error: ""
                        },
                        vrycode: {
                            type: 'vrycode',
                            label: "验证码",
                            name: "vrycode",
                            imgUrl: $.U('plugins/verifycode'),
                            error: ""
                        }
                    },
                    submitButtons: {
                        submitLabel: '登录'
                    }
                },
            }
        }
    }
}

以上是一个登录表单的参数,如果未定义则会调用失败

模板

<form-box :info="info" :hiddens="args.hiddens" :callbacks="args.callbacks" :validators="validators" @validate="validate"></form-box>

可以看到form-xxx的模板就是系统组件form-box

参数info:用来表示表单基本信息的,默认值来自TFHomeUI

参数validators:用来做表单验证规则的,默认值来自TFHomeUI

方法validate:用来将错误信息处理转交给调用层自行处理的,默认值来自TFHomeUI

参数args.hiddens:可以设置默认隐藏表单域内容

参数args.callbacks:可以设置回调方法

其他参数:如果要传入其他参数请通过args带入

调用

$.componentLoad('form-login', 'form-login', {
    compBox : '#user-login',
    bindData : {
        myArg : "myArg"
    }
});

dialog-xxx

声明

Vue.component('dialog-login', function (resolve, reject) {
    resolve(TFHomeUI._makeAsyncDialogComponent('login'));
});

dialog-xxx异步组件通过TFHomeUI._makeAsyncDialogComponent得到组件参数,而真正的组件参数在TFHomeUI对象内部通过对应的表单获得

也就是说要创造dialog-xxx就必须先有form-xxx,而TFHomeUI._makeAsyncDialogComponent的参数就是xxx,也就是一个表单实例名称

参数

window.TFHomeUI = {

        asyncDialogFormCompoents : {

            ...

            dialogs: {

                login : {}                
            }
        }
    }
}

以上是一个对话框的参数,默认都是空对象,如果未定义则会调用失败

模板

<dialog-box :args="args">
    <form-xxx :args="args"></form-xxx>
</dialog-box>

大家可能已经发现了dialog-xxx的内部只有一个slot就是form-xxx,而且只传递了一个参数args,也就是说其他参数info、validators和方法validate都是不能从外面设置的,只能通过TFHomeUI对象内部进行初始化设定

异步组件dialog-xxx的最外层用的是系统组件dialog-box

参数args:唯一参数,这里面有个重要的参数就是args.info.visible,它控制对话框是否显示,默认为false

其他参数:如果要传入其他参数请通过args带入

调用

$.componentLoad('dialog-login', 'dialog-login', {
    bindData : {
        args : {
            visible : true,
            myArg : "myArg"
        }
    }
});


鬼谷子叔叔
  • 日志:127
  • 回复:13

进入ta的主页