---
# System prepended metadata

title: Visual Studio安裝工具

---

# Visual Studio安裝工具
* *Web Compiler(SCSS -> CSS) 專案有在使用, 需安裝(或是自行安裝scss->css 的complier) 已把檔案加在jira(http://jira.evervictory-it.com:8080/browse/TKCMS-336)
* AnkhSVN(非必要)

# MVC簡易概要
一開始由Global.asax(後端MVC)當作進入點，
1. 瀏覽器像伺服器發出request
2. IIS接收封包
3. 轉給Route(Global.asax裡面的RegisterRoutes)
4. Route在決定要交給HttpHandler or MVCHandler來處理

![](https://i.imgur.com/SjQzNHU.png)

專案裡會先由HomeController解析到App.cshtml
然後由於_ViewStart裡面有寫@layout 所以APP.cshtml裡面使用@Renderbody渲染index.cshtml

![](https://i.imgur.com/OddJKLt.png)

可參考: https://dotblogs.com.tw/dog0416/2016/06/09/205427

# FE(前端框架帮助文档)

## 框架设计依据
由于BC(博彩)类的web站点的展示形式，如下图所示，一般为一级导航加二级导航，且都是触发某一导航后，替换某一区域内的html片段，故该框架的核心方法为：

``` js
option = {
    html: "",  //html字符串，如某个<script type="text/html" id="tpl">中的内容
    json: "",   //服务端取数据地址
    param: {},  //请求的参数
    bd: $("#div"),  //通过模板引擎生成好的html放到一个容器中
    ... // 其它請直接翻代碼
};
loadModule(option);
```
![](https://i.imgur.com/ViUStZw.png)

## 框架文件详解

* `template.js` // 模板引擎
  全名ARTtemplate，第三方文件 
  可參考:https://aui.github.io/art-template/zh-cn/docs/

* `framework-init.js` // 框架核心文件
  详细：该文件中产生两个对象，一个是 `Loader` 构造函数，`loadModule` 这个全局方法调用的就是这个构造函数，一个是 `G.util` 的静态方法，用于添加一些常用的静态方法，如生成`guid(G.util.guid)`，编译模板 `G.util.compile`

* `framework-mapping.js`  // 框架配置文件
  配置每个模块，如导航切换需要用到的html模板地址和从服务端地址，如下
    1.   第一種寫法
  ```javascript
    G.map = {
        ssc: {
            rule: ["/Htmls/ssc/rule.html"],
            betdetail: ["/Htmls/betdetail.html", '/Bet/GetBettingSuccess/'],
            history: {
                history: ["/Htmls/history.html", "/Report/GetBetSummary/", format_history('history')],
                date: ["Htmls/history.html", "/Report/GetBetDateSummary/", format_history('date')],
                detail: ["Htmls/history.html", "/Report/GetBetDetail/", format_history('detail')]
            }
        },
        pk10: {
            ...
        },
        "lottery name": {
            "module name": ["template URL", "GET API URL", "callback function"]
        }
    };
  ```
    2.   第二種寫法

    ```javascript
    G.map = {
        betdetail: {
            html: {
                betdetail: "/Htmls/betdetail.html" //html
            },
            json: {
                betdetail: "/Member/GetMemberBetRecord" // api
            },
            format: {
                betdetail: format_betdetail //api回來的值, 再做處理(Ex: 可能畫面跟資料排序不同等等)
            }
        },
        tema: {
            html: {
                tema: "/Htmls/playtype/tema.html"
            },
            json: {
                tema: G.action_odds
            },
            format: {
                tema: format_tema
            }
        }
    ```
  

* 设置页面初始需要加载哪个模块
  ```javascript
  G.InitHash = "#!kuaida?pagesize=10";
  ```

* 设置模板引擎的辅助函数
  ```javascript
  template.helper("format_time", function(){});
  ```

* 设置 `jquery.validate` 插件一些默认配置
   ```javascript
    $.validator.setDefaults({});
   ```

* 设置路由的回调函数
    ```javascript
    G.hashFn = {
        supper: (function () {
            var nav = $("#nav a");
            return function (hash_module) {
                var module = hash_module.module;
                G.util.load({
                    bd: main,
                    module: module,
                    param: hash_module.param || {},
                    html: hash_module.html,
                    json: hash_module.json,
                    hash: hash_module.hash,
                    refresh: hash_module.refresh
                });
                nav.removeClass("on").filter("[name=" + module + "]").addClass("on");
            }
        })()
    };
    $.each(G.map.ssc, function (module) {
        G.hashFn[module] = G.hashFn.supper;
    });
    ```

    注意:导航中添加的模块名，需要添加到这里，才会执行模块加载方法。

* `jquery.hashchange.js`
  浏览器url hash值变化后，调用hashchange事件，单页面浏览器前进后退时用到，第三方插件，调用已集成到`framework-init.js`中

* `jquery.dialog.js`  //弹出框的插件
  提供:
  ` $.alert("text", fn) //提示框 `
  ` $.confirm("text", fn) //确认框 `
  ` $.dialog(option)  //弹出框 `
  弹出框分两种情况：
    1. 普通的用法
        ``` js
        $.dialog({
            html : "<div>aaa</div>"  //html片段
        });
        ```
    1. 加载服务器模板
        ``` js
        $.dialog({
            module: ""  //framework-mapping.js 中配置的 G.map[name]中的name值
            html: ""   //远程模板地址  G.map[name].html[ name2 ] 中   name2的值
            json: ""   //远程模板地址  G.map[name].json[ name3 ] 中  name3的值
            param: {}  //需要用到的参数
        });
        ```

* `jquery.validate.js`  //表单验证插件，第三方
    ```javascript
    $("form").validate({
        submitHandler: function (form) {
            _this.doSave(form);
        }
    });
    ```
    
    現多以 `initialize.call(this);` 取代。

* `jquery.tooltip.js`  //错误冒泡提示
    ``` javascript
    $("input").tooltip({
        html: "这是必填字段"  //冒泡显示的内容
        isFocus: true 是否获取焦点
        isSelect: true  是否选中  
    });
    ```

* `module-*.js`  对应模块的业务处理文件
    ``` javascript
    function A (d) {
        //该形参 d 为一个Html片段中 `<div name="module" id=’a’></div>` 的元素引用
        this.d = d;
    }
    ```
    * module-* 玩法的命名規則通常是以拼音為主
      Ex: module-tema(tema為特碼拼音)
    * `A.prototype.init = function(){}`   //模块加载完成后会自动执行 init 方法

    * `G.modules[moduleid] = A;`   建立 html 与 js 之间的关联
  module id 为 div标签且name="module"的id值

* `module-pager.js` //分页模块 
   ```html
    <div name="module" id="pager" class="pager" action="account.account" hash="#!account" format="callback_function_name" param="a=123&b=567">
        <select name="pagesize" class="pagesize">
            {{pages = [10,20,30,60,100]}}
            {{each pages as page}}
                <option value="{{page}}" {{if Data.PageSize == page}}selected{{/if}}>{{page}}</option>
            {{/each}}
        </select>
        第 <span class="pageindex red">{{Data.PageIndex}}</span> 页
        共 <span class="pagecount red">{{Data.PageCount}}</span> 页
        共 <span class="recordcount red">{{Data.RecordCount}}</span> 条
        <a href="javascript:void(0)" class="fn-first">首页</a>
        <a href="javascript:void(0)" class="fn-prev">上一页</a>
        <a href="javascript:void(0)" class="fn-next">下一页</a>
        <a href="javascript:void(0)" class="fn-last">尾页</a>
        <input type="text" class="input w30 fn-index">
        <input type="button" class="btn w30 fn-go" value="GO" />
    </div>
   ```

  以上为一段分页 html 代码
  當一頁有多個pager的話，記得在module.pager.js最下方多輸出
  ``` javascript
  G.modules.pager = Pager
  G.modules.pager2 = Pager
  G.modules.pager3 = Pager
  G.modules.pager4 = Pager
  ```
  `action:  //需要请求的服务器地址`
  `pagebody:  //需要将分页处理好的html片段放到哪个容器中，值为容器的id`
  `template: //需要用到哪个<script type="text/html" id="tpl">中的值作为分页的模板`
  `param:  //分页需要用到的参数，格式  a=1&b=2`
  ## 完整url解析
当一个导航加上A链接，如 `href=" #!aaa.bbb|ccc?ddd=1 "`
解析成的格式
``` javascript
loadModule({
    module: "aaa",
    html: "bbb",
    json:"ccc",
    param: {ddd : 1}
});
```
當loadModule中有使用到param的話, 對應的html 裡面就可以使用到該資料
例:
module-tema.js
```javasript
loadModule({
   module:"aaa",
   html: "bbb",
   json: "ccc",
   param: {ddd : 1}
})
```
bbb.html 
```htmlmixed
<div name="module">
    <div>
        // Param要用大寫P
        // Param.ddd = 1
        {{Param.ddd}} 
    </div>
</div>
```
`module-tema.js`  //特碼的邏輯代码

先定义一个tema的构造函数
``` javascript
function Tema(d) {
    this.d = $(d);
}
```
一些事件绑定添加到其中，其中扩展方法自由发挥，如
``` javascript
Tema.prototype.init = function () {
    var _this = this;
    this.d.on("click", "#selectAll", function () {
        // do something
    });
    this.d.on("click", ".fn-cancelbet", function () {
        _this.cancelBet();
    });
}

Tema.prototype.cancelBet = function () {
    // do something
};
```


绑定html与js的关联
``` js
G.module.tema = Tema;


* 框架內使用*javascript prototype*的寫法
![](https://i.imgur.com/bnTBZdV.png)

* 共用模塊
有些module-*.js裡面可能包含不同的html, 使用相同的模組 , 甚至不同的html, 不同的模組
舉例(marksix2 > Scripts > module-tema.js)

```javascript

    ...
    
    Tema.prototype.destroy = function () {
        if (this.id == 'zhengtema') {
            doc.triggerHandler("showZheng", [false]);
        }
        if (this.timer_oddsloop) {
            clearInterval(this.timer_oddsloop);
        }
    };

    G.modules.tema = Tema;        // 特碼
    G.modules.zhengma = Tema;     // 正碼
    G.modules.zhengtema = Tema;   // 正特碼
    
    function QuickBet(d) {
        this.d = $(d);
        this.UseLastOdds = false;
        this.data = [d.json.Param];
    }


    QuickBet.prototype.init = function () {
        initialize.call(this);
        this.BetMoney = $("#BetMoney").on("focus", function () {
            this.value = G.pre_set ? G.pre_money : this.value;
        }).val(G.pre_set ? G.pre_money : this.value).input_digits();
    };
    
    ...
    
    QuickBet.prototype.doFailBet = function (message) {
        var data = {}, param = { "List": this.data };
        data.Message = message;
        $.extend(data, param);
        doc.triggerHandler("betfailed", [data]);
    };

    G.modules.quickbet = QuickBet;
```
* html、json兩者互相如何傳遞資料?
以六平台為例
```javascript
    G.map = {
        company: {
            html: {
                company: "/Htmls/company/company.html",
            },
            json: {
                company: "/Company/GetCompanyList",

            }
```
簡單來說，讀取company.html後會打GetCompanyList的api, 然後會進入到在framwork-init.js裡面的Loader, 其中
```javascript
Loader.prototype.getJSON = function(){
        var _this = this;
        jsonurl = /^\/.+/.test(option.json) ? option.json : option.json ? G.map[option.module].json[option.json] : option.module && !option.html ? G.map[option.module].json[option.module] : null;
        if (!jsonurl) {
            this.flag += 1;
            this.flashHTML(option);
            return;
        }
        G.get({
            url: jsonurl,
            data: option.param,
            success: function (json) {
                _this.flag += 1;
                _this.jsondata = json;  **會把值塞到jsondata裡面**
                if (option.jsonSuccess) {
                    _this.jsondata = option.jsonSuccess(json) || json;
                } else {
                    if (!option.html && !option.json) {
                        _this.jsondata = G.map[option.module].format && G.map[option.module].format[option.module] ? G.map[option.module].format[option.module](json) || json : json;
                    } else if (option.module && option.json) {
                        _this.jsondata = G.map[option.module].format && G.map[option.module].format[option.json] ? G.map[option.module].format[option.json](json) || json : json;
                    }
                }
                if(!option.hash || option.hash == G.util.getHash()){
                    _this.flashHTML(option);
                }
            },
}
```
最後在Loader.prototype.flashHTML裡的
```javascript
    this.jsondata.LoginAccount = LOGIN_ACCOUNT; **其他要共用的東西可參照此寫法
    strHTML = G.util.compile(this.template, this.jsondata);
```
再把jsondata跟template compile ，html就會拿到資料

* HTML標籤內驗證
```html=
   <input type="text" class="w60 ime-dis" id="pre_money" lessthan="100">
  ```
lessthan 是設定值小於100,相關設定在framework-mapping.js內
  ```javascript
    $.validator.addMethod("lessthan", function (value, element, param) {
        var val = $.trim($(param).val());
        val = val ? parseFloat(val) : null;
        value = parseFloat(value);
        return this.optional(element) || !val || value <= val;
    }, "搜索的最小值不能超过最大值！");
```
其他驗證有positive(正數)positivedigits(正整數)nonnegative(非負數)...等


