2023年10月12日 星期四

Get & Post - 網頁傳遞參數的方式 - 1>編碼 & 解碼處理 2>序列化 & 反序列化

目的: 網頁傳遞參數的方式 - Get & Post -

處理說明:
一.編碼 & 解碼處理
1>在網頁上提交內容時,可以將內容作為參數傳遞透過GET或POST請求方式到後端。
這些有中文或特殊符號的參數(非ASCII碼)會自動進行編碼,以便它們可以在網絡上進行傳輸。
2>中文字符會以UTF8轉成16進制去做編碼,
     若遇特殊情況(&#)就沒額外處理,則導致參數無法正確傳輸或解析
--> 透過params可以將中文和符號進行編碼,
      但是&# (代表Unicode編碼開頭) 的組合是無法進行編碼,會有錯誤

二.序列化  & 反序列化
序列化:將物件狀態轉換為可傳輸格式
反序列化:將資料流轉換成物件



一.編碼 & 解碼處理

[HttpPost]
public string send()
{
     HttpContext c = HttpContext.Current;
     NameValueCollection nvc =                                                        
     c.Request.Form;               
     string english_tf = nvc["english_tf"];
     string chinese_tf = nvc["chinese_tf"];
     string text = english_tf + " ; " + chinese_tf;
     return text;
}

[HttpGet]
public string send()
{
    NameValueCollection nvc = 
    c.Request.QueryString;
    string english_tf = nvc["english_tf"];
    string chinese_tf =nvc["chinese_tf "];
    string text = english_tf + " ; " + chinese_tf;
    return text;
}


解決方法:
    1>前端先編碼,再送至後端(encodeURIComponent)
    2>後端先解碼,再取得原始欄位值(HttpUtility.UrlDecode)



二.序列化  & 反序列化












2023年10月10日 星期二

V120602E – 取得/設定RadioGroup欄位值(Ext.getCmp("sub_PRN").getValue()) 為 Object {sub_PRN: ‘A’} - V20305

目的: V120602E –取得/設定RadioGroup欄位值(Ext.getCmp("sub_PRN").getValue())為Object {sub_PRN: ‘A’} 

處理說明: 1>前端 RadioGroup欄位值(Ext.getCmp("sub_PRN").getValue())為Object

                  2>前端取得 RadioGroup欄位值必需 Object.sub_PRN

                  3>設定 RadioGroup checked
                      Ext.getCmp("s_STAUOCD").items.items[2].setValue(true); 


 1>*.js
        //更新單況   
                    var Tmp_url = "";
                        var np1 = {};
                    np1["sub_PRE_DATE"] = Ext.getCmp("sub_PRE_DATE").getValue();                        
                    np1["sub_PRN"] = (Ext.getCmp("sub_PRN").getValue()).sub_PRN;                        
                    if (np1["sub_PRN"] == 'A')  ////列印 & 儲存目前 QDR現況
                        Tmp_url = '../../api/V120602EAPI/UPDATE_PRN_QDR';
                    else //僅列印
                        Tmp_url = '../../api/V120602EAPI/XlsOut';
                    f_downloadFile('EX_DFile', Tmp_url, np1, 'POST', function () {
                        var r = r_cookies('EX_DFile');
                        if (!checkisnull(r))
                            mysuccessalert(r);
                    });


var cmp_PRN = get_cmp_rdgrp1('列印選項', 'sub_PRN', 80);
    var cmp_PRN1 = get_cmp_rd0('列印並儲存目前QDR現況', 'sub_PRN', 250, 'A');
    var cmp_PRN2 = get_cmp_rd0('僅列印', 'sub_PRN', 250, 'B');
    cmp_PRN.items.push(cmp_PRN1, cmp_PRN2);
    cmp_PRN.flex = 10;
    cmp_PRN1.width = 200;  //避免 radio字折行
    cmp_PRN1.checked = true;

    // [Call_V120602E]鈕  - 子畫面欄位
    var J_formFields_V120602E = [
        {
            bodyStyle: "background-color:transparent;", border: false, layout: { type: 'vbox', align: 'stretch' }, padding: "5",
            items: [cmp_PRE_DATE, 
                          {
                    xtype: 'panel', id: 'sub_panel1', layout: { type: 'vbox', align: 'stretch' }, flex: 20, border: 0,
                              items: [cmp_PRN,],
                },  // end of sub_panel1
                {
                    xtype: 'panel', id: 'sub_panel2', layout: { type: 'vbox', align: 'stretch' }, flex: 10, border: 0,
                    items: [],
                },  // end of sub_panel1
            ],
        }  //end of  J_formFields_Sub1 , items[{
    ]      //end of  J_formFields_Sub1 , items[


Sample: V20305 - 設定 checkboxgroup  為true


 //請料提出   checkboxgroup - STAUOCD
    var cmp_STAUOCD = get_cmp_rdgrp1('請料狀態', 's_STAUOCD', 80);    
    var cmp_STAUOCD1 = get_cmp_rd0('未提出', 's_STAUOCD', 50, 'A');
    var cmp_STAUOCD2 = get_cmp_rd0('已提出', 's_STAUOCD', 50, 'B');
    var cmp_STAUOCD3 = get_cmp_rd0('全部', 's_STAUOCD', 50, 'ALL');
    cmp_STAUOCD1.checked = true;
    cmp_STAUOCD.items.push(cmp_STAUOCD1, cmp_STAUOCD2, cmp_STAUOCD3);
Ext.getCmp("s_STAUOCD").items.items[2].setValue(true);



2>*.cs
 //查詢 - 列印並儲存目前QDR現況
        [HttpPost]
        public void UPDATE_PRN_QDR()
        {
            var c = HttpContext.Current;
            NameValueCollection nvc = c.Request.Form;
            string Tmp_Str;
            string Tmp_PRE_DATE = nvc["sub_PRE_DATE"];
            string Tmp_sub_PRN = nvc["sub_PRN"];
            if (Tmp_sub_PRN == "A")
                Tmp_Str = "列印並儲存目前QDR現況";
            else
                Tmp_Str = "僅列印";

2023年9月26日 星期二

V120602 – [匯入][匯出]鈕 - 匯出所有資料 – New – V120602A() , V120602B()

 目的: V120602 – [匯入][匯出] – New – V120602A() , V120602B()

處理說明:  1>匯出 
                        1>> 將目前Grid 所有的資料,存成 Tmp_DataAry1, 以 np 傳至後端
                                --> 但是欄位值含HTML(
..) , 會出現錯誤訊息..
                               -->  所以改至後端直接讀取 DataSet ds = V120602Controller.getGridData_M(false);
                        2>>將 ds.Tables["T1"] 寫入 *.xlsx
                   2>匯入
                        //範例: V20301 - [批次新增]鈕
                        {
                           xtype: 'button', text: '批次新增', id: 'BatchAddBtn',
                           listeners: {
                           click: function (me,e,eOpts) {
                                //挑選檔案,傳入 CallBack函式(按OK時的處理函式 - Ok_process)
                                SelectFile(Ok_process);
                             }
                          }
                      },


                           




1>V120602.js
//按鈕 :  [匯入] [匯出][維護 Delay Notification Form] [QDR Report][可施工統計表]
    var BtnAry = [
        {
            xtype: 'button', text: '匯入', id: 'XlsInBtn', iconCls: 'icon-check',
            listeners: {
                click: function () {
                    //XlsInBtn_click() ;
                    //[匯入]鈕 ,    xtype: 'filefield',   以 file輸入元件 , 將檔案傳送至後端 , form.submit;
                    Call_V120602A();
                }
            }
        }, //end of  匯入
        {  //以 將目前 Master 的資料,傳送至後端取得資料匯出 
            xtype: 'button', text: '匯出', id: 'XlsOutBtn',
            listeners: {
                click: function () {
                    //console.log(" 1 匯出EXCEL: ");
                    //XlsOutBtn_click();  // - 將目前 Master 的資料,傳送至後端取得資料匯出 
                    Call_V120602B();
                }
            }
        },        
    ];


2>>V120602B.js
//[匯出]鈕 -  - 只匯出資料,無子畫面
function Call_V120602B() {
    var Tmp_Grid = Ext.getCmp('grid_Single');
    var cur_recs, cur_rec;
    var Tmp_SAPNO, Tmp_PN, Tmp_QTY, Tmp_EOCND, Tmp_RMK;
    var Tmp_data_JSON = "";  //將store資料轉成 JSON 的字串
    var Tmp_sub_np = {};
    let Tmp_DataAry1 = [];
    var Tmp_Str = "";
    //cur_recs = Tmp_Grid.getView().selModel.getSelection();
    //console.log("cur_recs:", cur_recs);
    if (Tmp_Grid.store.length == 0) {
        mywarnalert("目前主檔無資料,無法匯出 EXCEL 檔案");
        return;
    }
    //取得目前所勾選資料,再匯出
    for (var i = 0; i < Tmp_Grid.store.getCount(); i++) {
        cur_rec = Tmp_Grid.store.getAt(i);
        console.log("i : ", i);
        console.log("cur_rec :", cur_rec);
        console.log("cur_rec.data :", cur_rec.data);
        if (!(JSON.stringify(cur_rec.data) === '{}')) {
            Tmp_DataAry1.push(cur_rec.data);
        }
    }


    // 將目前子畫面的資料(Table)轉成 JSON字串
    //let Tmp_DataString1 = JSON.stringify(Tmp_DataAry1);
    //console.log("Tmp_DataString1:", Tmp_DataString1);
    //因為[備註]欄位 有/n .. 等特殊字元 ,  JSON.stringify 會 Error

    var np = {};
    var np = s_JSON('s_form'); //TMFunction.js, 組合form上的查詢條件為json參數傳遞                                                       
    np["s_STAT"] = Ext.getCmp('s_STAT').getValue();
    //np = {
    //    DataString1: Tmp_DataString1,
    //};

    Ext.getCmp('s_form').submit({
        //Ext.Ajax.request({
        url: '../../api/V120602BAPI/XlsOut',
        method: 'POST',
        async: false,
        standardSubmit: true, //若要傳送檔案至前端, standardSubmit必需設為 true  
        params: np,
    });
    //顯示結果訊息..

    var mask = new Ext.LoadMask(Ext.getBody(), {
        msg: '處理中,請稍待...'
    });

    mask.show();//使用 mask 需手動呼叫show() 方法下
    //每1秒檢核一次,是否已完成, 若已完成,則不再檢核
    var timer = setInterval(function () {
        var r = r_cookies('EX_DFile');
        //console.log("r_cookies=", r);
        if (!checkisnull(r)) {
            mysuccessalert(r);
            clearInterval(timer);
            mask.hide();
            timer = null;
        }
    }, 1000);  //1000ms = 1sec
}  // end of  function Call_V120602B() {


1.5>V20301.js  SelectFiles()
//[選擇檔案]子畫面. [確認匯入]鈕 , 處理
function Ok_process(me, e, eOpts) {
    //取得 [檔案上傳].檔名
    var Tmp_FileObj = Ext.getCmp('FName');
    console.log("FName Obj:", Tmp_FileObj);
    var Tmp_Str = "";
    var np = {
        FName: Ext.getDom(Tmp_FileObj.inputId).value
    };
    console.log("FName: ", np.FName);
    //submit會將fileUploadForm裡面input name送到後端
    //Ext.getCmp('btn_FileIn').getForm().submit({
    me.up("form").submit({
        //standardSubmit: false,    //default:false
        url: '../api/V20301API/uploadFileToDB',
        method: 'POST',
        headers: { 'Content-type': 'multipart/form-data' },
        params: np,
        success: function (response, opts) {
            console.log("success opts.response.responseText:", opts.response.responseText);
            var obj = Ext.decode(opts.response.responseText);
            console.log("obj:", obj);
            if (obj["success"]) {
                Tmp_Str = "[匯入]完成 !! <br>"
                    + obj['Rtn_Msg'];
                mysuccessalert(Tmp_Str);
                console.log("success=true , Tmp_Str=", Tmp_Str);
                me.up("window").close();
                me.up("window").destroy();
                Ext.getCmp('btn_Show').fireHandler();
            }
            else {
                Tmp_Str = "[匯入]失敗 !! <br>"
                    + obj['Rtn_Msg'];
                mywarnalert(Tmp_Str);
                //Tmp_Sql = " Tmp_sql :<br> "
                //                 +obj['Tmp_Sql'];
                //mywarnalert(Tmp_Str);
                console.log("success=false , Tmp_Str=", Tmp_Str);
                me.up("window").close();
                me.up("window").destroy();
            };
        },
        failure: function (response, opts) {
            console.log(" failure opts.response.responseText:", opts.response.responseText);
            var obj = Ext.decode(opts.response.responseText);
            console.log("obj:", obj);
            Tmp_Str = "[匯入]失敗!! <br>"
                + "(" + obj['FName'] + ") <br>"
                + obj['Rtn_Msg'];
            mywarnalert(Tmp_Str);
            me.up("window").close();
            me.up("window").destroy();
        }
    });
};  // end of Ok_process() {  //批次新增



2>*.cs
     1>>匯出
            V120602APIController V120602Controller = new V120602APIController();
            DataSet ds = V120602Controller.getGridData_M(false);
            DataTable dt1 = ds.Tables["T1"];

    2>>匯入  
              foreach (string cur_FName in Request.Files)
            {
                 Stream file_Strm = Request.Files[cur_FName].InputStream;
 
             } 
          

2023年9月25日 星期一

V120602 - 欄位值編碼/解碼 - 具有潛在危險的Request.Form的值 - 欄位值含特殊符號(HTML, ) -

目的: V120602 - 具有潛在危險的Request.Form的值
                          - 傳至後端欄位值含特殊符號(HTML,&#x0D)
                          - .NET4.0 會出現錯誤訊息(避免駭客執行 javascript/..)

處理說明: 1>因為原本的欄位值含有 HTML 字元/ javascript(&#x0D)
                        .NET 4.0 避免駭客,所以出現錯誤訊息 (讀取  nvc["DESCPT"] 時)
                  2>前端資料送至後端前先編碼 , 再送至後端
                        - S_DB.add_np = {
                                'DFDCPTN': encodeURIComponent(Ext.getCmp("DFDCPTN").getValue()),
                                                    }

                  3>後端資料先解碼,再 assign  給欄位
                       nvc1["DFDCPTN"] = HttpUtility.UrlDecode(nvc["DFDCPTN"]);



1>*.js
 //修改的存檔
    Ext.getCmp('btn_save').beforeEdit = function () {
        //因[缺失說明][進度說明]欄位值含有 &#x0D, ..等HTML字元, 必需先編號再送至後端
        S_DB.add_np = {
            'DFDCPTN': encodeURIComponent(Ext.getCmp("DFDCPTN").getValue()),
            'STATDCPTN': encodeURIComponent(Ext.getCmp("STATDCPTN").getValue()),
        }
        isCheck = S_DB.doSave('Update');
        return isCheck;
    };


2>*.cs
 [HttpPost]
        public void Update()
        {
            var c = System.Web.HttpContext.Current;
            NameValueCollection nvc = c.Request.Form;
            string[] arrCondition = getPK();
            NameValueCollection nvc1 = new NameValueCollection();
            foreach (string k in nvc.Keys)
            {
                nvc1[k] = nvc[k];
            }
            //2023/09/26 因欄位值含 HTML字元, 必需先編碼再傳送, 後端接收後,必需先解碼
            nvc1["DFDCPTN"] = HttpUtility.UrlDecode(nvc["DFDCPTN"]);
            nvc1["STATDCPTN"] = HttpUtility.UrlDecode(nvc["STATDCPTN"]);

            //nvc1["ITM"] = GET_NEXT_ITMNO();
            nvc1["UPPER"] = LoginUserModel.LoginUserId;
            nvc1["UPDT"] = DateTime.Now.ToString("yyyy/MM/dd");
            excuteUpdate(nvc1, DBTable, arrCondition);
        }

--> 刪除時, 依 PK 刪除, 所以後端讀欄位值時, 只讀 PK欄位, 不讀其他欄位

 [HttpPost]
        public void Delete()
        {
            var c = System.Web.HttpContext.Current;
            NameValueCollection nvc = c.Request.Form;
            string[] arrCondition = getPK();
            NameValueCollection nvc1 = new NameValueCollection();
            //因為  Delete 只用到 PK 去刪除 ,所以只需傳入 PK 欄位值即可
            nvc1["ITM"] = nvc["ITM"];
            excuteDelete(nvc1, DBTable, arrCondition);
        }



2023年9月11日 星期一

WPM全機維修模組 – 視窗的Title會亂碼

目的: WPM全機維修模組 – 視窗的Title會亂碼

處理說明:  1>登入畫面的 Title  及  Showmessage 時, 視窗的標題均抓  Application.Title 
                   2>Application.Title 設定位置如下:
                      Delphi IDE選項>Project>Options>Application Settings>Title  








2023年9月8日 星期五

V120401 -日期時間 –在Local電腦執行OK, 但在測試區執行卻出現錯誤訊息, - 在應為數值的位置發現非數值的 -日期時間

 目的: V120401 – 在Local電腦執行OK, 但在測試區執行卻出現錯誤訊息, 

            -在應為數值的位置發現非數值的

處理說明: 1> 在後端下 SQL 時, 出現錯誤 ,顯示 Tmp_Sql 欄位值
                  2>  因為 SQL 取[日期]欄位值 , 在 Local電腦不含時間
                                                                        但在測試區主機含時間, 
                         -->以致 insert SQL  日期欄位錯誤
                  3> 將日期時間字串,轉換成 日期字串
                       Tmp_rtnDT= DateTime.Parse(par_DateTMStr).ToString("yyyy/MM/dd");
                        Tmp_VNDTXY =  DateTime.Parse(dr1["VNDTXY"].ToString()).ToString("yyyy/MM/dd");


1>*.cs
Tmp_Sql = "  SELECT   NATIXX,LGTPXX,TMNOXX, OWN_DEP, "
                                     + "    ITEMXY,VNTPXD,VNDTXY,VNPGXY,DOREXY,REMKXY,"
                                     +"    VNVFXY  "
                                     + "   FROM     TM_XY@TLS_245 "
                                     + "  WHERE   OWN_DEP='L'   "
                                     + "   AND       TMNOXX=" + myfunc.AA(Tmp_TMNOXX)
                                     + "   AND       NATIXX=" + myfunc.AA(Tmp_NATIXX)
                                     + "   AND       LGTPXX=" + myfunc.AA(Tmp_LGTPXX);
                        Tmp_dt1 = myfunc.SqlOpen(Tmp_dt1, Tmp_Sql);
                        foreach (DataRow dr1 in Tmp_dt1.Rows)
                        {
      
                            Tmp_ITEMXY = dr1["ITEMXY"].ToString();
                            //String.Format("{0:yyyy/MM/dd}", DateTime.Parse(dr1["VNDTXY"].ToString()))
                            //Tmp_VNDTXY = dr1["VNDTXY"].ToString();
                            //if (!myfunc.checkisnull(dr1["VNDTXY"].ToString()))
      Tmp_VNDTXY = String.Format("{0:yyyy/MM/dd}", DateTime.Parse(dr1["VNDTXY"].ToString()));
      Tmp_VNDTXY =  DateTime.Parse(dr1["VNDTXY"].ToString()).ToString("yyyy/MM/dd");
                            //else
                            //    Tmp_VNDTXY = "";
                            Tmp_VNDTXY = myfunc.getDateStr(dr1["VNDTXY"].ToString());
                            Tmp_VNTPXD = dr1["VNTPXD"].ToString();

2023年9月6日 星期三

V120602 – [新增]鈕–項次=MAX+1 –[存檔]鈕 – nvc1,nvc1[ITM]=get_NEXT_ITM();

 目的: V120602 –  [新增]項次=MAX+1 –[存檔] – nvc1,nvc1[ITM]=get_NEXT_ITM();

處理說明: 1>[新增]鈕 - 設定必填/唯讀/計算欄位 , setFieldsCls()
                  2>前端欄位預設值: Ext.getCmp("STAT").setValue("A"); 
                                                     Ext.getCmp("STAT_").setValue("未結案");
                  3>[存檔]鈕 - 項次=max(項次)+1



1>*.js
 //新增
    Ext.getCmp('btn_add').on("click", function () {
        setFieldsCls('myform', 
         ['ITM', 'ACNO', 'DEPID', 'QDRNO', 'CURP'], ['ITM', 'UPPER', 'UPDT', 'STAT'], 
['ITM', 'ACNO', 'DEPID', 'QDRNO', 'REVDT', 'CURDEP', 'CURP', 'REFNO', 'DIRNO', 'REL_DIR_NO', 'WKD', 'PCMPDT', 'STATDCPTN', 'DFDCPTN', 'STAT', 'UPPER', 'CAU']);
        Ext.getCmp("STAT").setValue("A");
        Ext.getCmp("STAT_").setValue("未結案");
        is_add = true;
    });

2>*.cs
[HttpPost]
        public void Insert()
        {
            var c = System.Web.HttpContext.Current;
            NameValueCollection nvc = c.Request.Form;
            NameValueCollection nvc1 = new NameValueCollection();
            foreach (string k in nvc.Keys)
            {
                nvc1[k] = nvc[k];
            }            
            nvc1["ITM"] = GET_NEXT_ITMNO();
            nvc1["UPPER"] = LoginUserModel.LoginUserId;
            nvc1["UPDT"] = DateTime.Now.ToString("yyyy/MM/dd");
            excuteInsert(nvc1, DBTable);          
        }

 //取得  AMM_QDR.ITM  最大值
        [HttpPost]
        public string GET_NEXT_ITMNO()
        {
            string Tmp_Sql;         
            Int32 Tmp_MAX_ITMNO, Tmp_NEXT_ITMNO;
            string Tmp_NEXT_ITMNO_Str;
            Tmp_Sql = " SELECT  MAX(CAST(ITM as integer ))  "
                            +"  FROM   AMM_QDR   " ;
            Tmp_MAX_ITMNO = int.Parse(myfunc.SqlValue(Tmp_Sql));
            if (myfunc.checkisnull(Tmp_MAX_ITMNO.ToString()))
            {
                Tmp_NEXT_ITMNO = 1;
            }
            else
            {                
                Tmp_NEXT_ITMNO = Tmp_MAX_ITMNO+1;
            };
            Tmp_NEXT_ITMNO_Str = Tmp_NEXT_ITMNO.ToString();
            return Tmp_NEXT_ITMNO_Str;
        }