某社区项目交接文档

某社区项目

本项目技术栈较为陈旧,使用framework7+template7+gulp+less+requireJS。页面也存在很多迭代之后废弃的,故整理起来非常复杂,本文档将从几个方面试图对本项目进行梳理

为了使开发快速高效,使用了以下辅助工具:

建议阅读本文档之前,先学习

1.framework7官方文档
2.template7官方文档

1.目录结构

项目总览

在这里插入图片描述
该项目的静态资源全在app文件下,如果需要全量出包,需要把整个app文件进行替换。其中build文件下有压缩的js和css
在这里插入图片描述
如果页面文件pages和图片文件img未做改动,那么只需要替换buildindex.html即可

具体js文件

在这里插入图片描述
值得注意的是,本项目的会员权益相关的部分,是由林宇使用svelte框架进行重构的,其他文件夹下的membership即是相关的。同时也在gulp中使用了typeScript进行转译

具体js对应具体页面

在这里插入图片描述
在这里插入图片描述
关于页面和JS的对应关系,详见index.controlller.js如下方法:

//初始化事件
    function init() {
        $$(document).on("click", ".views .tip-box a:not(.other), .views .submit-btn", function() {//发送举报
            var report_type = $$(this).data("report_type");
            console.info("report_type:" + report_type);
            if ($$(this).hasClass("submit-btn")) {
                if (!$$("input[name=otherReason]").val().trim()) {
                    f7.alert("请输入举报原因");
                    return;
                }
            }
            var pageName = getCurPage().data("page");//即HTML文件里的data-page属性
            require(["controllers/" + pageName + ".controller"], function(controller) {
                controller.report(report_type);
            });
            cancleSelect();//举报完成,隐藏举报相关内容
        });

在一个HTML页面里,data-page属性即为其对应js的名字

<div class="page tabbar-labels-fixed" id="AddAddressContent" data-page='addAddress'>
  <div class='page-content page-add-address'>

在这里插入图片描述
注意,每个页面下对应的less文件必须在app.less里面注册,

@import 'pages/vip-rule';
@import 'pages/level-up-tips';
@import 'pages/mall-order';
@import 'pages/modify-address';
@import 'pages/earn-integral';
@import 'pages/gift-exchange';

至于与页面一一对应,只需要类名对应即可,格式如下.page-mall-order不再过多阐述

2.关于项目注意事项,见readme.md
开发

要求 Node 在 4.x 的版本以上。

// 克隆至本地
git clone git@git.cairenhui.com:Community/ht-community-h5-s2.git
cd ht-community-h5-s2

// 安装倚赖
npm install

// 运行前必须先打一次包
gulp build
//启动服务器
npm run dev
// 注意:因为后端开发把index.html放入客户端,所以如果想在手机端看效果请在index.ejs配置: if (isDevMode) {
  App_token = '<%= token%>';
  App_accountId = '<%= accountId%>';
}

本项目目前是js文件和HTML文件一一对应的架构,如果需要书写es6标准js,请在es6文件下新建js,会自动转译成es5。命名规则参照html里的data-page属性并加上.controller后缀

自适应各屏幕分辨率

如果index.ejs中没有定义meta name=viewportflexible插件将动态根据各个屏幕的dpr动态改变html的class类名以及meta name=viewport的scale,而基准则是gulpfile中px2rem中的remUnit的值,因为此项目一开始是以按除以二的方式计算距离,所以remUnit的值为现在设计稿750的一半(37.5)

3.接口文档相关

这项目之前的老旧文档都是Excel里的,无法提供一份全的文档,目前新接口以及改造过的老接口已经上线到eolinker地址
具体接口详细文档可以询问后端开发人员陈庆林,金明明。

下面详细介绍接口的定义规则,在api.ts里定义,如下:

 var API = {

    // 获取数据失败标志位
    failed: 'failed',

    // 用于签名校验
    appKey: 'cairenhuiweixin',
    //所有接口都传以下参数
    appParams: function () {
      return {
        appKey: this.appKey,
        timestamp: new Date().getTime(),
        appVersion: App_version,
        clientType: App_clientType
      };
    },
    // 赞
    support: function (data) {
      data = Utils.extend(data, this.appParams());
      data = Utils.serialize(data);
      return Http.post(App_data_domain + 'ajaxQueryPraise.json?' + data)
        .then(handleSuccess, handleError);
    },

在具体页面里调用接口之前,需要先在API对象里定义对应的成员方法,然后如下调用即可:

 API.json2309({//加载文章内容
            articleId: articleId,
            accountId: App_accountId,
            source: source,
            token: App_token
        }).then(function(result){
            var data = result.resultMap;
            if(data.status === '2'){//状态2表示已下架,显示该文章已经删除
                $$('.empty-article-wrap').show();
                return;
            }

具体的ajax方法是在http.js里定义的,通过promise对象,如果返回的是reject,则调用api.js里的handleError

 //出错的时候调用自己的出错页面----如果有错误信息则弹窗提示
  function handleError(data) {
    f7.hideIndicator();
    if (data.error_no == '-9') {
      //跳转到提示升级页面即可
      mainView.loadPage(App_domain + 'page/level-up-tips.html');
      return
    } else if (data.error_no == '-10') {
      //返回-10,需要登出
      App_accountId = null;
      App_token = null;
      window.changeHref(window.hrefParam.function_exit);
      return
    }
    var msg = data.error_info;
    if (msg == 'goMaintainPage' || msg.indexOf('Bad Gateway') >= 0) {

      mainView.loadPage(App_domain + 'page/maintain-page2.html'); //跳转到‘系统维护升级中2’页面
    } else if (msg || msg != '') {
      f7.alert(msg);
    } else if (msg == '客户端版本过低,请升级后使用') {
      return
    }
    return API.failed;
  }

在这个方法里 可以对一些错误进行拦截和处理

4.客户端交互相关

这里的代码基本都是定义在js/controllers下的index.controller.js,这个文件会在项目初始化时直接调用。见app.js

 		Index.init();
        Router.init(); 

本项目作为H5与原生APP端交互的方法是这样定义的:

    window.hrefParam = {//调用app原生接口的url
        'close_needRefresh': 'ht_square_function_close_needRefresh',//关闭页面--效果同下面那个
        'close': 'ht_square_function_close',//关闭页面
        'loginSquare': 'ht_square_function_loginSquare',//跳转到登录页面
        'function_params': 'ht_square_function_params',//相当于当前的webView重新加载一次社区
        'reloadViewList': 'ht_square_function_reloadViewList',//重新加载观点列表,用于观点列表页面
        'function_height': 'ht_square_function_@height',//ht_square_function_  这个webView会拦截,并调用@后调用方法
        'function_exit': 'ht_square_function_exit',//退出社区,主页在用
        'function_checkFund': 'ht_square_function_checkFund',//no--没在用
        'function_opensjkh': 'ht_square_function_opensjkh',//no--没在用
        'backView': 'ht_square_function_backView',//返回上个页面,并调用对应的方法,传入对应参数,用于观点列表页面
        'checkFund_request': 'ht_square_function_checkFund_request',//彩虹主页打开绑定资金账号页面
        'function_share': 'ht_square_function_@share',
        'function_errorPage': 'ht_square_function_@errorPage=true&@height',
        'edit_nickname': 'ht_square_function_edit_nickname',//打开编辑昵称页面
        'edit_image': 'ht_square_function_edit_image',//打开编辑头像页面
        'infoDetail': 'ht_square_function_@infoDetail',//打开资讯页面
        'openLocalUrl': 'ht_square_function_openLocalUrl_request',//打开一个新的webview
        'openAdvertisement': 'ht_square_function_openAdvertisement_',//打开对应的广告页面
        'gotoUpdate':'ht_square_function_gotoUpdate',//提示版本升级页点击调用客户端方法跳转应用市场
        'openYlMarket': 'no_decode_ht_square_function_openAdvertisement_'//打开怡乐商城

    }

这是调用客户端的方法,如window.changeHref(window.hrefParam.loginSquare);就是调用跳转到登录页面的方法

如果要客户端调用我们的方法,则如下定义即可:

    window.htsecBack = leftBtnEvent;//暴露返回方法给全局调用

还有一点值得介绍的是,本项目把返回按钮的方法都改写了,可以根据历史记录长度和具体页面编号来进行拦截处理

 //点击返回按钮时-----全部改成自己控制路由
    function leftBtnEvent(event){
        //如果是维护页面,按返回键直接关闭社区,退回到app里----
        if(ehtescObj.pageCode == 'maintain-page2'||ehtescObj.pageCode == 'level-up-tips'){
            window.changeHref(window.hrefParam.close);
            return;
        }

        var param;
        if(mainView.history.length <= 2){//如果小于2则证明是退出社区,或者是其他特别的处理
            if(ehtescObj.pageCode == 'home' || ehtescObj.pageCode == 'mall.index' || ehtescObj.pageCode == 'mall-game'
                    || ehtescObj.pageCode == 'scoreMine' || ehtescObj.pageCode == 'signIn') {
                window.changeHref(window.hrefParam.close_needRefresh,'=refreshData');
            }else if(ehtescObj.pageCode == 'send-comm' || ehtescObj.pageCode == 'reply' || ehtescObj.pageCode == 'sendComment') {
                window.changeHref(window.hrefParam.backView,'@loadNewData@' + window.ehtescObj.backRefreshFlag);
            }else if(ehtescObj.pageCode == 'comment-detail'){
                window.changeHref(window.hrefParam.backView,'@loadNewData@'+ viewRefreshFlag);
            }else if(ehtescObj.pageCode == 'personalcenter'){
                if (personalFlag == 0) {
                    param = '@loadNewData@-2'
                } else {
                    param = '@loadNewData@-1'
                }
                window.changeHref(window.hrefParam.backView,param);
            }else if(ehtescObj.pageCode == 'refresh-comlist'){
                if (publishViewFlag == 1) {
                    param = '@loadNewData@-1'
                } else {
                    param = '@loadNewData@-2'
                }
                window.changeHref(window.hrefParam.backView,param);
            }else if(ehtescObj.pageCode == 'acct-binding' && window.localStorage.getItem("backPointReloadPage") == 'yes'){
                window.changeHref('ht_square_function_finishAndInvokJS_reloadPointPage');
            }else if(ehtescObj.pageCode === 'modify'){//修改页面回退应该回退到主页
                mainView.history = [mainView.history[0],'page/personal-message.html',mainView.history[1]];
                mainView.router.back();
            }else{//默认就直接关闭页面
                window.changeHref(window.hrefParam.close);
            }
        }else{//如果大于2则直接使用f7框架的返回
            // window.changeHref('ht_square_function_go_back');

            if(ehtescObj.pageCode == 'kline'){
                if (modalFlag) {
                    return;
                  }
                  modalFlag = true;
                  f7.modal({
                    text: '确定要退出K线英雄游戏?',
                    buttons: [{
                      text: '继续游戏',
                      onClick: function() {
                        modalFlag = false;
                        return;
                      }
                    }, {
                      text: '不想玩了',
                      onClick: function() {
                        API.kLineOver({
                            token: App_token,
                            accountId: App_accountId,
                            endTime: window.ehtescObj.overTime,
                            endPrice: window.ehtescObj.sellPriceLast
                        }).then(function(data) {
                            //退出操作,不做任何回调
                        });
                        modalFlag = false;
                        mainView.router.back();
                        return;
                      }
                    }]
                  })
                  return;

由于本项目是嵌在APP里的H5项目,故需要模拟登陆参数,目前是通过URL拼接的方法,如下:比如我要访问彩虹俱乐部界面,就可以在地址栏输入:

http://localhost:8000/?request=rainbow&accountId=1000185789&token=d49478f04b2f24a8ae30d2239e50e9fb0706138260d8db44b80369a50f859356ef806bc599af22b56f00a5b98cc2e86be9604d457f7195d0493db0cdd1443dadd9bc183708c8b0725460de719c853e11691741f91292ebcb89ef63e753e9a305ed0d708c7bee939031d4623d6cc93e0245c615a75dae6aa673e30e29fd885b3e&topicCode=TOP002

注意,所有页面都需要带上accountIdtoken,如果想要知道具体页面需要什么参数,可以看下面这个方法,在入口文件index.ejs里定义的:

  function getUrlParam(name) {
      //var htsecUrl = decodeURIComponent(window.location.search);
      //var htsecUrl = window.location.search;
      //alert(decodeURIComponent(window.location.search));
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
        //var r = window.location.search.substr(1).match(reg);  //匹配目标参数
        var r = htsecUrl.substr(1).match(reg);
        if (r != null) return r[2]; return undefined; //返回参数值
    }
```js
方法的主要作用就是,在url里获取到指定属性名的值,所以如果想要知道具体页面需要哪些传参,只要关注上面这个方法就行:

App_userId=App_userId||getUrlParam('user_id');

5.路由跳转相关

本项目内部路由使用的是framework7的路由,内部跳转方式如下:

 mainView.router.load({
                url: App_domain + 'page/community-personalcenter.html?user_id=' + to_user_id,
                animatePages: false
            })

或者(其实就是一个方法)

            mainView.router.loadPage(App_domain + "page/my-community.html");

如果想要直接通过地址栏url进行跳转,则输request=文件名即可,在router.js里定义的方法如下:

// 前面的都没匹配的且有 request
      // 统一默认处理 request 对应 page
      var pageUrl = App_domain + 'page/' + request + '.html';
      request
        ? mainView.router.load({
            url: pageUrl,
            animatePages: false
          })
        : mainView.router.load({
            url: firstPage + '?time=' + new Date().getTime(),
            animatePages: false
          });

如果想要内部路由传参,则需要拼接query参数,如下:

url: App_domain + 'page/community-personalcenter.html?user_id=' + articleUserId,
user_id=' + articleUserId

这一块儿在下一个页面里的init方法里通过query可以取到,如下:

 function init(query){
        pageNum = 0;
        loading = false;
        loadOver = false;//是否已加载完所有的数据
        hasMore = 1;
        lastViewId = undefined;
    

        template.bind(bindings);//绑定页面上的事件
        articleId = query.articleId || getUrlParam('articleId');

5.gulp相关

出包
  1. gulp clean
  2. gulp build
如果有第三方js引入需求
gulp.task('jsmin', () => {
  //压缩这几个导入的第三方包
  pump([
    gulp.src([
      'app/js/libs/flexible_css.debug.js',
      'app/js/libs/flexible.debug.js',
      'app/js/libs/clipboard.min.js',
      'app/js/vendors/crypto-js.js',
      'app/js/vendors/require.js',
      'app/js/libs/vconsole.min.js'
    ]),
    uglify(),
    header(banner, {
      pkg: require('./package.json')
    }),
    gulp.dest('app/build/libs')
  ]);
});

将路径添加进这里,并在index.ejs里通过<script>引用即可

  <script src="build/libs/crypto-js.js"></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值