HC小区管理系统项目前端页面开发流程梳理

2024-06-13 19:01:33 浏览数 (2)

前言

在我之前写的文章你一定没见过这样高度适配的接口,HC小区管理系统后端项目源码难点梳理 中我们一起梳理了后端项目MicroCommunity的开发流程和难点,当时前端项目MicroCommunityWeb尚未梳理,而前端项目MicroCommunityWeb对于

初学者来说也容易懵逼。因为MicroCommunityWeb 项目是一个同时集成了vuelayuivcFramworkbootstrap 等不同的 js框架,里面开发页面的写法也与 仅仅集成了 VueElement-UI 框架的项目大部相同。

开发新页面

MicroCommunityWeb项目中的页面组件几乎全部都在src/public/pages目录下,我们也可以在这个目录下新建自己的页面组件。

pages目录下的任何一个大类子目录下(如fee目录,费用相关)新建一个页面子目录,然后在该子目录下新建页面相关的htmljs 文件。例如申请发票页面对应的两个文件invoiceApply.htmlinvoiceApply.js

页面 html 文件

html页面中可以使用vue语法,而数据和函数则定义在与之对应的js文件中。invoiceApply.html文件源码如下:

代码语言:javascript复制
<div>
    <div class="row">
        <div class="col-md-2 padding-r-0">
            <div class=" border-radius ">
                <div class="margin-xs-r  treeview attendance-staff">
                    <ul class="list-group text-center border-radius">
                        <li class="list-group-item node-orgTree " v-for="(item,index) in invoiceApplyInfo.states" :key="index" @click="swatchState(item)" :class="{'vc-node-selected':invoiceApplyInfo.conditions.state == item.state}">
                            {{item.stateName}}
                        </li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="col-md-10">
            <div class="row">
                <div class="col-lg-12">
                    <div class="ibox ">
                        <div class="ibox-title">
                            <h5>
                                <vc:i18n name="查询条件"></vc:i18n>
                            </h5>
                            <div class="ibox-tools" style="top:10px;"></div>
                        </div>
                        <div class="ibox-content">
                            <div class="row">
                                <div class="col-sm-2">
                                    <div class="form-group">
                                        <input type="text" :placeholder="vc.i18n('请填写发票号','invoiceApply')" v-model="invoiceApplyInfo.conditions.invoiceCode" class="form-control">
                                    </div>
                                </div>
                                <div class="col-sm-2">
                                    <select class="custom-select" v-model="invoiceApplyInfo.conditions.invoiceType">
                                        <option selected value="">
                                            请选择发票类型
                                        </option>
                                        <option value="1001">个人</option>
                                        <option value="2002">企业</option>
                                    </select>
                                </div>
                                <div class="col-sm-2">
                                    <div class="form-group">
                                        <input type="text" :placeholder="vc.i18n('请选择业主名称','invoiceApply')" v-model="invoiceApplyInfo.conditions.ownerName" class=" form-control">
                                    </div>
                                </div>
                                <div class="col-sm-2">
                                    <div class="form-group">
                                        <input type="text" :placeholder="vc.i18n('请选择申请人','invoiceApply')" v-model="invoiceApplyInfo.conditions.createUserName" class=" form-control">
                                    </div>
                                </div>
                                <div class="col-sm-2">
                                    <div class="form-group">
                                        <input type="text" :placeholder="vc.i18n('请选择申请人电话','invoiceApply')" v-model="invoiceApplyInfo.conditions.applyTel" class=" form-control">
                                    </div>
                                </div>
                                <div class="col-sm-1">
                                    <button type="button" class="btn btn-primary btn-sm" style="min-width: 50px;" v-on:click="_queryInvoiceApplyMethod()">
                                        <i class="glyphicon glyphicon-search"></i> <span>
                                            <vc:i18n name="查询"></vc:i18n>
                                        </span>
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12">
                    <div class="ibox">
                        <div class="ibox-title">
                            <h5>
                                <vc:i18n name="申请发票" namespace="invoiceApply"></vc:i18n>
                            </h5>
                            <div class="ibox-tools" style="top:10px;">
                                <button type="button" class="btn btn-primary btn-sm" @click="_invoiceApply">
                                    <vc:i18n name="申请"></vc:i18n>
                                </button>
                            </div>
                        </div>
                        <div class="ibox-content">
                            <table class="footable table table-stripped toggle-arrow-tiny" data-page-size="15">
                                <thead>
                                    <tr>
                                        <th class="text-center">
                                            <vc:i18n name='编号' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='发票类型' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='业主名称' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='申请人' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='发票名头' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='纳税人识别号' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='地址、电话' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='申请金额' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='发票号' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='审核状态' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='申请时间' namespace='invoiceApply'></vc:i18n>
                                        </th>
                                        <th class="text-center">
                                            <vc:i18n name='操作'></vc:i18n>
                                        </th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr v-for="invoiceApply in invoiceApplyInfo.invoiceApplys">
                                        <td class="text-center">{{invoiceApply.applyId}}</td>
                                        <td class="text-center">{{invoiceApply.invoiceType == '1001'?'个人':'企业'}}</td>
                                        <td class="text-center">{{invoiceApply.ownerName}}</td>
                                        <td class="text-center">
                                            {{invoiceApply.createUserName}}({{invoiceApply.applyTel}})</td>
                                        <td class="text-center">{{invoiceApply.invoiceName}}</td>
                                        <td class="text-center">{{invoiceApply.invoiceNum}}</td>
                                        <td class="text-center">{{invoiceApply.invoiceAddress}}</td>
                                        <td class="text-center">{{invoiceApply.invoiceAmount}}</td>
                                        <td class="text-center">{{invoiceApply.invoiceCode || '未上传'}}</td>
                                        <td class="text-center">{{invoiceApply.stateName}}</td>
                                        <td class="text-center">{{invoiceApply.createTime}}</td>
                                        <td class="text-center">
                                            <div class="btn-group" v-if="invoiceApply.state == 'W'">
                                                <button class="btn-white btn btn-xs"  v-on:click="_openInvoiceAuditModel(invoiceApply)">
                                                    <vc:i18n name='审核'></vc:i18n>
                                                </button>
                                            </div>
                                            <div class="btn-group" v-if="invoiceApply.state == 'U'">
                                                <button class="btn-white btn btn-xs" v-on:click="_openInvoice(invoiceApply)">
                                                    <vc:i18n name='开票'></vc:i18n>
                                                </button>
                                            </div>
                                            <div class="btn-group">
                                                <button class="btn-white btn btn-xs" v-on:click="_openDeleteInvoiceApplyModel(invoiceApply)">
                                                    <vc:i18n name='删除'></vc:i18n>
                                                </button>
                                            </div>
                                            <div class="btn-group">
                                                <button class="btn-white btn btn-xs"
                                                    v-on:click="_openInvoiceApplyDetail(invoiceApply)">
                                                    <vc:i18n name='详情'></vc:i18n>
                                                </button>
                                            </div>
                                        </td>
                                    </tr>
                                </tbody>
                                <tfoot>
                                    <tr>
                                        <td colspan="7">
                                            <ul class="pagination float-right"></ul>
                                        </td>
                                    </tr>
                                </tfoot>
                            </table>
                            <!-- 分页 -->
                            <vc:create path="frame/pagination"></vc:create>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <vc:create path="fee/deleteInvoiceApply"></vc:create>
    <vc:create path="fee/uploadInvoicePhoto"></vc:create>
    <vc:create path="fee/wirteInvoiceEvent"></vc:create>
    <vc:create path="common/audit" callBackListener="invoiceApply" callBackFunction="notifyAuditInfo"></vc:create>
</div>

v-ifv-forv-modelvue指令在页面的html文件中可以无障碍使用。这里可以看到,页面的js文件并不需要通过script标签的src属性引入。因为在vcFramework.js 框架中会自动将页面的js文件嵌入到相同目录下的页面html文件中去。

除此之外还能看到很多vc:i18nvc:create标签, vc:i18n 表示国际化标签;而vc:create 表示页面内嵌的弹窗子组件,path属性值表示位于public/components目录下的弹窗组件位置,callBackListenercallBackFunction的值分别表示弹窗子组件中的两个构造参数。而 path="common/audit" 代表的子组件为public/components/common/audit 目录下表示的弹窗组件。

audit.html文件源码如下:

代码语言:javascript复制
<div id="auditModel" class="modal fade" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-body">
                <h3 class="m-t-none m-b ">
                    <vc:i18n name="审核信息" namespace="audit"></vc:i18n>
                </h3>
                <div class="ibox-content">
                    <div class="form-group row">
                        <label class="col-sm-2 col-form-label">
                                <vc:i18n name="审核状态" namespace="audit"></vc:i18n>
                        </label>
                        <div class="col-sm-10">
                            <select class="custom-select" v-model="auditInfo.state">
                                <option selected disabled value="">{{vc.i18n('请审核','audit')}}</option>
                                <option value="1100">{{vc.i18n('同意','audit')}}</option>
                                <option value="1200">{{vc.i18n('拒绝','audit')}}</option>
                            </select>
                        </div>
                    </div>
                    <div class="form-group row">
                        <label class="col-sm-2 col-form-label">
                            <span>
                                <vc:i18n name="原因" namespace="audit"></vc:i18n>
                            </span>
                        </label>
                        <div class="col-sm-10">
                            <textarea :placeholder="vc.i18n('必填,请填写原因','audit')" class="form-control"
                                v-model="auditInfo.remark">
                                    </textarea>
                        </div>
                    </div>
                    <div class="ibox-content">
                        <button class="btn btn-primary float-right" type="button" v-on:click="_auditSubmit()">
                            <i class="fa fa-check"></i>&nbsp;提交
                        </button>
                        <button type="button" class="btn btn-warning float-right" style="margin-right:20px;"
                            data-dismiss="modal">
                            <i class="fa fa-times"></i>&nbsp;取消
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

可以看到html文件中通过role="dialog" 指定这是一个弹窗,通过aria-hidden="true"指定弹窗默认隐藏。html文件中定义的class的样式都可以在public/css/vc-ui.css文件中定义。

页面js 文件

定义组件中的数据以及页面按钮绑定的函数都在页面的js文件中完成,invoiceApply.js 文件源码如下:

代码语言:javascript复制
(function (vc) {
    var DEFAULT_PAGE = 1;
    var DEFAULT_ROWS = 10;
    vc.extends({
        data: {
            invoiceApplyInfo: {
                invoiceApplys: [],
                total: 0,
                records: 1,
                moreCondition: false,
                applyId: '',
                states:[{
                    stateName:'全部',
                    state:'',
                },{
                    stateName:'待审核',
                    state:'W',
                },{
                    stateName:'待上传',
                    state:'U',
                },{
                    stateName:'审核失败',
                    state:'F',
                },{
                    stateName:'带领用',
                    state:'G',
                },{
                    stateName:'已领用',
                    state:'C',
                }],
                conditions: {
                    applyId: '',
                    invoiceCode:'',
                    invoiceType: '',
                    ownerName: '',
                    applyTel: '',
                    createUserName: '',
                    state: '',
                },
                audit:{}
            }
        },
        _initMethod: function () {
            $that._listInvoiceApplys(DEFAULT_PAGE, DEFAULT_ROWS);
        },
        _initEvent: function () {
            vc.on('invoiceApply', 'notifyAuditInfo', function (_auditInfo) {
                $that._auditInvoiceState(_auditInfo);
            });
            vc.on('invoiceApply', 'listInvoiceApply', function (_param) {
                $that._listInvoiceApplys(DEFAULT_PAGE, DEFAULT_ROWS);
            });
            vc.on('pagination', 'page_event', function (_currentPage) {
                $that._listInvoiceApplys(_currentPage, DEFAULT_ROWS);
            });
        },
        methods: {
            _listInvoiceApplys: function (_page, _rows) {
                $that.invoiceApplyInfo.conditions.page = _page;
                $that.invoiceApplyInfo.conditions.row = _rows;
                $that.invoiceApplyInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                let param = {
                    params: $that.invoiceApplyInfo.conditions
                };
                //发送get请求
                vc.http.apiGet('/invoice.listInvoiceApply',
                    param,
                    function (json, res) {
                        let _json = JSON.parse(json);
                        $that.invoiceApplyInfo.total = _json.total;
                        $that.invoiceApplyInfo.records = _json.records;
                        $that.invoiceApplyInfo.invoiceApplys = _json.data;
                        vc.emit('pagination', 'init', {
                            total: $that.invoiceApplyInfo.records,
                            currentPage: _page
                        });
                    }, function (errInfo, error) {
                        console.log('请求失败处理');
                    }
                );
            },
            _openDeleteInvoiceApplyModel: function (_invoiceApply) {
                vc.emit('deleteInvoiceApply', 'openDeleteInvoiceApplyModal', _invoiceApply);
            },
            _queryInvoiceApplyMethod: function () {
                $that._listInvoiceApplys(DEFAULT_PAGE, DEFAULT_ROWS);
            },
            _moreCondition: function () {
                if ($that.invoiceApplyInfo.moreCondition) {
                    $that.invoiceApplyInfo.moreCondition = false;
                } else {
                    $that.invoiceApplyInfo.moreCondition = true;
                }
            },
            swatchState:function(_state){
                $that.invoiceApplyInfo.conditions.state = _state.state;
                $that._listInvoiceApplys(DEFAULT_PAGE, DEFAULT_ROWS);
            },
            _invoiceApply:function(){
                vc.jumpToPage('/#/pages/fee/ownerApplyInvoice')
            },
            _openInvoiceApplyDetail:function(_invoiceApply){
                vc.jumpToPage('/#/pages/fee/invoiceApplyDetail?applyId=' _invoiceApply.applyId);
            },
            _openInvoiceAuditModel(_invoiceApply) {
                $that.invoiceApplyInfo.audit = _invoiceApply;
                vc.emit('audit', 'openAuditModal', {});
            },
            _auditInvoiceState: function (_auditInfo) {
                $that.invoiceApplyInfo.audit.state = _auditInfo.state;
                $that.invoiceApplyInfo.audit.remark = _auditInfo.remark;
                vc.http.apiPost(
                    '/invoice.auditInvoiceApply',
                    JSON.stringify( $that.invoiceApplyInfo.audit), {
                        emulateJSON: true
                    },
                    function (json, res) {
                        let _json = JSON.parse(json);
                        if (_json.code == 0) {
                            $that._listInvoiceApplys(DEFAULT_PAGE, DEFAULT_ROWS);
                            vc.toast("审核成功");
                            return;
                        } else {
                            vc.toast(_json.msg);
                        }
                    },
                    function (errInfo, error) {
                        vc.toast(errInfo);
                    });
            },
            _openUploadInvoicePhoto: function(_apply){
                vc.emit('uploadInvoicePhoto', 'openInvoicePhotoModal',_apply);
            },
            _openUserGetInvoice:function(_apply){
                vc.emit('wirteInvoiceEvent', 'openWirteInvoiceModal',_apply);
            },
            _openInvoice: function(invoiceApply){
                vc.jumpToPage('/#/pages/fee/openInvoice');
                sessionStorage.setItem('invoiceApply', JSON.stringify(invoiceApply));
            }
        }
    });
})(window.vc);

可以看到invoiceApply.js 文件中定义了一个闭包函数,里面的vc参数表示public/vc-core/core.js文件中定义的工具对象。

通过vc.extends 方法定义页面的数据和生命周期函数。

  • data 对象中定义页面双向绑定的数据;
  • _initMethod 方法中定义页面加载后需要调用的函数;
  • _initEvent 方法中监听关联组件通过vc.emit方法触发与本组件的通信;
  • methods 对象中则可以自定义页面按钮绑定的函数或其他需要用到的函数。

例如 vc.emit('audit', 'openAuditModal', {}); 方法触发打开审批对话框,调用该方法会进入public/components/audit/audit.js文件中_initEvent方法中下面这段逻辑。

代码语言:javascript复制
 vc.on('audit', 'openAuditModal', function () {
                $('#auditModel').modal('show'); // 显示对话框
            });

vc.emit 方法中的前两个参数与vc.on方法中的前两个参数保持一致,vc.emit 方法中的第三个参数为vc.on回调函数中的参数。

如:vc.emit('uploadInvoicePhoto', 'openInvoicePhotoModal',_apply); 对应 public/components/fee/uploadInvoicePhoto/uploadInvoicePhoto.js 文件中_initEvent方法中对应的源码

代码语言:javascript复制
vc.on('uploadInvoicePhoto', 'openInvoicePhotoModal', function(_param) {
                vc.copyObject(_param,$that.uploadInvoicePhotoInfo);
                $('#uploadInvoicePhotoModel').modal('show');
            });

回调函数中的_param 变量就是 vc.emit方法中的_apply参数。除此之外下面几个vc对象的方法也是常用到的

  • vc.jumpToPage 方法可以完成页面跳转,传入的参数为目标页面对应的url;
  • vc.http.postvc.http.get 方法可分别完成向后台发送postget 类型的http请求;
  • vc.toast 方法可完成弹出提示消息。
源码分析

vc 对象的源码都写在src/public/vcCore/vc-core.js文件中可查看到

1)vc.emit 方法源码

代码语言:javascript复制
/**
     事件触发
     **/
    vc.emit = function () {
        var _namespace = "";
        var _componentName = "";
        var _value = "";
        var _param = undefined;
        if (arguments.length == 4) {
            _namespace = arguments[0];
            _componentName = arguments[1];
            _value = arguments[2];
            _param = arguments[3];
        } else if (arguments.length == 3) {
            _componentName = arguments[0];
            _value = arguments[1];
            _param = arguments[2];
        } else {
            console.error("执行on 异常,vc.on 参数只能是3个 或4个");
            return;
        }
        if (vc.debug) {
            console.log("监听emit事件", _namespace, _componentName, _value, _param);
        }
        if (vc.notNull(_namespace)) {
            vc.component.$emit(_namespace   "_"   _componentName   '_'   _value, _param);
            return;
        }
        vc.component.$emit(_componentName   '_'   _value, _param);
    };

可以看到在我们的页面js文件中大多是传了3个参数到vc.emit方法中,最终是走了vc.component.$emit(_componentName '_' _value, _param);这行代码。而vc.component 通过下面这段源码可以看到它是一个vue实例。

代码语言:javascript复制
(function (vc, vmOptions) {
    console.log("vmOptions:", vmOptions);
    vc.component = new Vue(vmOptions);
})(window.vc, window.vc.vmOptions);

2)vc.on方法源码

代码语言:javascript复制
 /**
     事件监听
     **/
    vc.on = function () {
        var _namespace = "";
        var _componentName = "";
        var _value = "";
        var _callback = undefined;
        if (arguments.length == 4) {
            _namespace = arguments[0];
            _componentName = arguments[1];
            _value = arguments[2];
            _callback = arguments[3];
        } else if (arguments.length == 3) {
            _componentName = arguments[0];
            _value = arguments[1];
            _callback = arguments[2];
        } else {
            console.error("执行on 异常,vc.on 参数只能是3个 或4个");
            return;
        }
        if (vc.notNull(_namespace)) {
            vc.component.$on(_namespace   "_"   _componentName   '_'   _value,
                function (param) {
                    if (vc.debug) {
                        console.log("监听ON事件", _namespace, _componentName, _value, param);
                    }
                    _callback(param);
                }
            );
            return;
        }

        vc.component.$on(_componentName   '_'   _value,
            function (param) {
                if (vc.debug) {
                    console.log("监听ON事件", _componentName, _value, param);
                }
                _callback(param);
            }
        );
    };

vc.component.emit 方法会触发vc.on方法,而我们的页面js文件中调用vc.on方法时统一传了3个参数,前两个参数共同组成监听的事件名称,后一个参数为回调函数。最终会走了vue实例的on方法监听事件方法,也就是下面这段代码逻辑。

代码语言:javascript复制
vc.component.$on(_componentName   '_'   _value,
            function (param) {
                if (vc.debug) {
                    console.log("监听ON事件", _componentName, _value, param);
                }
                _callback(param);
            }
        );

最后会通过回调函数_callback和传过来的参数param在监听事件中完成业务逻辑,可以通过在源码中 debugger 断点追踪到。

vue对象 执行初始化方法的源码在vc-core.js文件中

代码语言:javascript复制
(function (vc) {
    vc.initEvent.forEach(function (eventMethod) {
        eventMethod();
    });
    vc.initMethod.forEach(function (callback) {
        callback();
    });
    vc.namespace.forEach(function (_param) {
        vc[_param.namespace] = vc.component[_param.namespace];
    });
})(window.vc);

3)发送http请求方法源码

源码位置:src/public/vcCore/vcFramework-0.4.js

代码语言:javascript复制
 vcFramework.http = {
        apiPost: function (api, param, options, successCallback, errorCallback) {
            let _api = '';

            if (api.indexOf('/') >= 0) {
                _api = '/app'   api;
                Vue.http.headers.common['APP-ID'] = '8000418004';
                Vue.http.headers.common['TRANSACTION-ID'] = vcFramework.uuid();
                Vue.http.headers.common['REQ-TIME'] = vcFramework.getDateYYYYMMDDHHMISS();
                Vue.http.headers.common['SIGN'] = ''; 
            } else {
                _api = '/callComponent/'   api;
            }
            vcFramework.loading('open');
            Vue.http.post(_api, param, options)
                .then(function (res) {
                    try {
                        let _header = res.headers.map;
                        //console.log('res', res);
                        if (vcFramework.notNull(_header['location'])) {
                            window.location.href = _header['location'];
                            return;
                        };
                        successCallback(res.bodyText, res);
                    } catch (e) {
                        console.error(e);
                    } finally {
                        vcFramework.loading('close');
                    }
                }, function (res) {
                    try {
                        if (res.status == 401 && res.headers.map["location"]) {
                            let _header = res.headers.map;
                            //console.log('res', res);
                            window.location.href = _header['location'];
                            return;
                        }
                        if (res.status == 404) {
                            window.location.href = '/user.html#/pages/frame/login';
                            return;
                        }
                        errorCallback(res.bodyText, res);
                    } catch (e) {
                        console.error(e);
                    } finally {
                        vcFramework.loading('close');
                    }
                });
        },
        apiGet: function (api, param, successCallback, errorCallback) {
            //加入缓存机制
            let _getPath = '';
            if (api.indexOf('/') != 0) {
                _getPath = '/'   api;
            }
            if (vcFramework.constant.GET_CACHE_URL.includes(_getPath)) {
                let _cacheData = vcFramework.getData(_getPath);
                //浏览器缓存中能获取到
                if (_cacheData != null && _cacheData != undefined) {
                    successCallback(JSON.stringify(_cacheData), { status: 200 });
                    return;
                }
            }

            let _api = '';

            if (api.indexOf('/') >= 0) {
                _api = '/app'   api;
                Vue.http.headers.common['APP-ID'] = '8000418004';
                Vue.http.headers.common['TRANSACTION-ID'] = vcFramework.uuid();
                Vue.http.headers.common['REQ-TIME'] = vcFramework.getDateYYYYMMDDHHMISS();
                Vue.http.headers.common['SIGN'] = ''; 
            } else {
                _api = '/callComponent/'   api;
            }
            if(vcFramework.hasOwnProperty('loading')){
                vcFramework.loading('open');
            }

            Vue.http.get(_api, param)
                .then(function (res) {
                    try {

                        successCallback(res.bodyText, res);
                        if (vcFramework.constant.GET_CACHE_URL.includes(_getPath) && res.status == 200) {
                            vcFramework.saveData(_getPath, JSON.parse(res.bodyText));
                        }
                    } catch (e) {
                        console.error(e);
                    } finally {
                        if(vcFramework.hasOwnProperty('loading')){
                            vcFramework.loading('close');
                        }
                    }
                }, function (res) {
                    try {
                        if (res.status == 401 && res.headers.map["location"]) {
                            let _header = res.headers.map;
                            //console.log('res', res);
                            window.location.href = _header['location'];
                            return;

                        }
                        if (res.status == 404) {
                            window.location.href = '/user.html#/pages/frame/login';
                            return;
                        }
                        errorCallback(res.bodyText, res);
                    } catch (e) {
                        console.error(e);
                    } finally {
                        vcFramework.loading('close');
                    }
                });
        }

     }

可以看到 vcFramework.http对象中封装了apipostapiGet 请求方法,分别对应POSTGET 类型的 http 请求。

小结

相信有了本文的梳理后,在HcCommunityWeb项目已有代码的基础上开发新的页面功能也不会有太大的难度了。主要是模仿已有的页面组件开发新的页面功能,但是如果对于一些工具方法不理解它的含义也很难模仿。重要的是我们要做到大体理解vm.emitvm.on这些用于组件之间通信的用法和传入的每个参数的含义。下面是笔者模仿别的页面源码开发出来的在线开票页面,开票和冲红发票的完整功能还有待完善。

需要注意的是后台没新开发一个新的@Java110Cmd标注的接口都需要将接口信息加入到c_servicec_route表中,否则后台会报没有权限访问接口。示例脚本如下:

代码语言:javascript复制
insert into c_service(id, service_id, service_code, business_type_cd, `name`, seq, messageQueueName, is_instance, url, method, timeout, retry_count, provide_app_id, create_time, status_cd)
values(1867, '982024032389830038', 'invoice.saveInvoice', 'API', '开电子发票', 1, '', 'CMD', 'http://fee-service', 'POST', 60, 3, '8000418002', '2024-04-23 00:09:17', '0');

insert into c_route(app_id, service_id, order_type_cd, invoke_limit_times, invoke_model, create_time, status_cd)
values('8000418004', '982024032389830038', 'D', '1000', 'S', CURRENT_TIMESTAMP, '0');

c_service表中service_code列的值为@Java110Cmd注解中serviceCode属性对应的值, is_instance列为固定值CMDmethod 列的值为接口对应的请求类型GETPOST

HC小区物业系统前端项目MicroCommunityWeb代码仓库地址如下:

https://gitee.com/java110/MicroCommunityWeb

对源码感兴趣的读者朋友可自行克隆下载。

0 人点赞