2026年9月3日 星期四

V60202 – [儲存位置]- 依[庫房]欄位值,過濾[儲存位置] - url 特殊字元(#,?,&)處理 - encodeURIComponent - encode,decode - Uri.UnescapeDataString

目的:  V60202 – [儲存位置]- 依[庫房]欄位值,過濾[儲存位置]  - url 特殊字元(#,?,&)處理  -

處理說明: 1>url 若含有 # 送至後端會錯誤, 瀏覽器會把#當成url分隔符號,不會傳給伺服器
                       -->所以 '../get_SPPick?WH=17# , 送至後端,17# 變成 17 , #不會傳給後端
                       -->url(含中文字,Ex:庫房),瀏覽器會自動將中文字編成%xx,送至後端
                  2>*.js 參數編碼:  encodeURIComponent() 
                       --> 所有特殊字元(#,?,&,庫房),均會編碼(%xx)
                      var Tmp_url = "../api/V60202API/get_SPPick?WH=" 
                                           + encodeURIComponent(Tmp_WH);     
                  3>*.cs 後端[HttpPost]  
                      --> *.cs 參數會自動將 %xx 還原成原始字元(#,?,&,庫房)
                       [HttpPost]
                       //前端 WH: 17%23      --> 後端  WH: 17#
                        //前端 WH: 17%2523  --> 後端 WH: 17%23 
                                                              --> Uri.UnescapeDataString(17%23) -- 17#
                      public dynamic get_SPPick(string SP = "", string WH="" ,int isComplete = 0)
                     {                   


1>*.js
 Ext.getCmp('btn_SP').on("click", function () {
        var Tmp_WH = Ext.getCmp("WH").getValue();  //庫房可能含 17#
        //1>url='../get_SPPick?WH= 17#', 傳至後端,會 錯誤 ,   -->  url 需改成 17%23 傳至後端
        //17#  , encodeURIComponent(Tmp_WH)  --> 17%23
        var Tmp_url = "../api/V60202API/get_SPPick?WH=" + encodeURIComponent(Tmp_WH);                
        var win = EditPickx('儲存位置', Tmp_url, ['SP',], ['SP'], J_pickstore_SP, J_pickcolumns_SP);
        win.show();
    });

2>*.cs
[HttpPost]
        //前端 WH: 17%23      --> 後端  WH: 17#
        //前端 WH: 17%2523  --> 後端 WH: 17%23  ,前端以 %23編碼 --> 後端還原成 %23
        public dynamic get_SPPick(string SP = "", string WH="" ,int isComplete = 0)
        {
            
            string Tmp_Sql = " SELECT  DISTINCT SP , WH  "
                                       + "  FROM   AMM_COMP "
                                       + "  WHERE  1=1 "
                                       + "    AND      SP IS NOT NULL "
                                       + "    AND      STAT='A'   ";
            if (!myfunc.checkisnull(WH))
            {                
                Tmp_Sql = Tmp_Sql + " AND    WH=" + myfunc.AA(WH);
            }
                
            Tmp_Sql = Tmp_Sql + " ORDER  BY SP ";
            string n = funId + "s_SP";
            DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "AMM_COMP" });
            if (SP != null && !SP.Equals(""))
            {
                if (isComplete == 1)
                {
                    ds = getPickDsbyCondi(n, "SP='" + SP + "'");
                }
                else
                {
                    ds = getPickDsbyCondi(n, "SP  LIKE '%" + SP + "%'");
                }
            }
            return ds;
        }  // end of  get_SPPick

url特殊字元(#)的處理 -*.js encodeURIComponent , encodeURI的用法 -*.cs Uri.EscapeDataString Uri.UnescapeDataString 的用法

 目的:  encodeURIComponent , encodeURI的用法
實際範例: 參考 V60202 - get_SPPick(string SP = "", string WH="" ,)

 處理說明: 1>encodeURIComponent 

                        → 用於單一參數值,會編碼大部分特殊字元(包括 ?, &,#,=,庫房)

Ex: encodeURIComponent(17#) --> 17%23

2>encodeURL--> 用於整個 URL,只編碼不合法字元,但會保留 ?, &, #,=,字元

Ex: encodeURL(17#) --> 17# , 保留#
3> *.cs    Uri.UnescapeDataString  --> 它會把 %xx 格式的字元還原成原始文字
                           Ex: Uri.UnescapeDataString(17%23) -- 17#
                                  Uri.UnescapeDataString(%E5%BA%AB%E6%88%BF) -- 庫房
                  4> *.cs    Uri.escapeDataString  --> 它會把 原始文字 編碼成 %xx 格式
                           Ex: Uri.escapeDataString('17#') --  17%23
                                  Uri.escapeDataString('庫房') --  %E5%BA%AB%E6%88%BF

                  5>url參數傳至後端 [HttpPost]  --> 會自動解碼, %xx --> 字元(%23 --> #)
                        [HttpPost] 
                        //前端 WH: 17%23 --> 後端 WH: 17#
                        //前端 WH: 17%2523 --> 後端 WH: 17%23 (原本 %23去編碼 --> 還原成 %23)
                        public dynamic get_SPPick(string SP = "", string WH="" ,int isComplete = 0)
                       {
                          
                          string Tmp_Sql = " SELECT  DISTINCT SP , WH  "
                                                    + "  FROM   AMM_COMP "
                                                    + "  WHERE  1=1 "
                                                    + "    AND      SP IS NOT NULL "
                                                    + "    AND      STAT='A'   ";
                        if (!myfunc.checkisnull(WH))
                       {
                           //WH: 17#      , Uri.UnescapeDataString(WH) --> 17#
                           //WH: 17%23, Uri.UnescapeDataString(WH)  --> 17#
                           WH = Uri.UnescapeDataString(WH);
                           Tmp_Sql = Tmp_Sql + " AND    WH=" + myfunc.AA(WH);
                        }                
                       Tmp_Sql = Tmp_Sql + " ORDER  BY SP ";
                       string n = funId + "s_SP";
                       DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "AMM_COMP" });
                       if (SP != null && !SP.Equals(""))
                      {
                        if (isComplete == 1)
                       {
                           ds = getPickDsbyCondi(n, "SP='" + SP + "'");
                        }
                        else
                       {
                         ds = getPickDsbyCondi(n, "SP  LIKE '%" + SP + "%'");
                        }
                  }
              return ds;
        }  // end of  get_SPPick


2026年9月2日 星期三

V60202 – 屆期日期 = 製表日期+3年 -js - 日期格式 - Tmp_SDS_EDT = Ext.Date.add(new Date(Tmp_SDSDT), Ext.Date.YEAR, 3);

 目的: V60202 – 屆期日期 = 製表日期+3年

處理說明 1>屆期日期 = 製表日期+3年
                      var Tmp_SDSDT = Ext.getCmp("SDSDT").getValue();
                      if (!checkisnull(Tmp_SDSDT)) {
                           var Tmp_SDS_EDT = Ext.Date.add(new Date(Tmp_SDSDT), Ext.Date.YEAR, 3);
                           Ext.getCmp("SDS_EDT").setValue(Ext.Date.format(Tmp_SDS_EDT, "Y/m/d"));
                    }    


1>*.js
//[SDS製表日期]異動時  -->  [SDS屆期日期]=[SDS製表日期]+3年
    Ext.getCmp("SDSDT").on('blur', function (me, eOpts) {
        var Tmp_SDSDT = Ext.getCmp("SDSDT").getValue();
        // blur 時,才顯示  顯示[SDS屆期日期]= [SDS製表日期]+3年
        // 加 3 年
        if (!checkisnull(Tmp_SDSDT)) {
            var Tmp_SDS_EDT = Ext.Date.add(new Date(Tmp_SDSDT), Ext.Date.YEAR, 3);
            Ext.getCmp("SDS_EDT").setValue(Ext.Date.format(Tmp_SDS_EDT, "Y/m/d"));
        }        
    });
    

V60202 – 編輯欄位 [庫房]– 挑選

 目的: V60202 – 編輯欄位 [庫房]– 挑選

處理說明: 1> 加入挑選 btn
{
xtype: "fieldcontainer", fieldLabel: "庫房", labelWidth: 128, layout: "hbox", items: [
{ id: "WH", name: "WH", xtype: "textfield", width: 100, padding: "0 4 0 0", maxLength: 10 },
{ id: "btn_WH", name: "btn_WH", xtype: "button", text: "..." }
]
},
                 2>設定挑選資料
                     Ext.getCmp('btn_WH').on("click", function () {
                     var win = EditPickx('庫房', '../api/V60202API/get_WHPick', ['WH'], ['WH'], 
                                                        J_pickstore_WH, J_pickcolumns_WH);
                     win.show();
                   });
                3>挑選資料
        //- [庫房(WH)]欄位挑選
        [HttpPost]
        public dynamic get_WHPick(string WH = "", int isComplete = 0)
        {
            string Tmp_Sql = " SELECT  DISTINCT WH  "
                                       + "  FROM   AMM_COMP "
                                       + "  WHERE  1=1 "
                                       + "    AND      WH IS NOT NULL "
                                       + "    AND      STAT='A'   "
                                       + " ORDER  BY WH ";
            string n = funId + "s_WH";
            DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "AMM_COMP" });
            if (WH != null && !WH.Equals(""))
            {
                if (isComplete == 1)
                {
                    ds = getPickDsbyCondi(n, "WH='" + WH + "'");
                }
                else
                {
                    ds = getPickDsbyCondi(n, "WH  LIKE '%" + WH + "%'");
                }
            }
            return ds;
        }  // end of  get_WHPick  



1>*_json.js
{
   xtype: "fieldcontainer", fieldLabel: "規範", labelWidth: 128, layout: "hbox", items: [
  { id: "NORM", name: "NORM", xtype: "textfield", width: 200, padding: "0 4 0 0", maxLength: 50 }
]
},
{
    xtype: "fieldcontainer", fieldLabel: "庫房", labelWidth: 128, layout: "hbox", items: [
   { id: "WH", name: "WH", xtype: "textfield", width: 100, padding: "0 4 0 0", maxLength: 10 },
   { id: "btn_WH", name: "btn_WH", xtype: "button", text: "..." }
]
},

//SP - 儲存位置 - 依畫面.庫房 - 過濾SP
    Ext.getCmp('btn_SP').on("click", function () {
        var Tmp_WH = Ext.getCmp("WH").getValue();
        var Tmp_url = '../api/V60202API/get_SPPick?WH=' + Tmp_WH;
        var win = EditPickx('儲存位置', Tmp_url, ['SP',], ['SP'], J_pickstore_SP, J_pickcolumns_SP);
        win.show();
    });

//CLASS - 類別
    Ext.getCmp('btn_CLASS').on("click", function () {
        var win = EditPickx('類別', '../api/V60202API/get_CLASSPick', ['CLASS','CLASS_'], ['CLASS','CLASS_'], J_pickstore_CLASS, J_pickcolumns_CLASS);
        win.show();
    });


2>*.cs
//編輯欄位  - 挑選
        //- [庫房(WH)]欄位挑選
        [HttpPost]
        public dynamic get_WHPick(string WH = "", int isComplete = 0)
        {
            string Tmp_Sql = " SELECT  DISTINCT WH  "
                                       + "  FROM   AMM_COMP "
                                       + "  WHERE  1=1 "
                                       + "    AND      WH IS NOT NULL "
                                       + "    AND      STAT='A'   "
                                       + " ORDER  BY WH ";
            string n = funId + "s_WH";
            DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "AMM_COMP" });
            if (WH != null && !WH.Equals(""))
            {
                if (isComplete == 1)
                {
                    ds = getPickDsbyCondi(n, "WH='" + WH + "'");
                }
                else
                {
                    ds = getPickDsbyCondi(n, "WH  LIKE '%" + WH + "%'");
                }
            }
            return ds;
        }  // end of  get_WHPick

//- [儲存位置(SP)]欄位挑選 - 依畫面.庫房過濾
        [HttpPost]
        public dynamic get_SPPick(string SP = "", string WH="" ,int isComplete = 0)
        {
            string Tmp_Sql = " SELECT  DISTINCT SP , WH  "
                                       + "  FROM   AMM_COMP "
                                       + "  WHERE  1=1 "
                                       + "    AND      SP IS NOT NULL "
                                       + "    AND      STAT='A'   ";
            if (!myfunc.checkisnull(WH))
                Tmp_Sql = Tmp_Sql + " AND    WH=" + myfunc.AA(WH);
            Tmp_Sql = Tmp_Sql + " ORDER  BY SP ";
            string n = funId + "s_SP";
            DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "AMM_COMP" });
            if (SP != null && !SP.Equals(""))
            {
                if (isComplete == 1)
                {
                    ds = getPickDsbyCondi(n, "SP='" + SP + "'");
                }
                else
                {
                    ds = getPickDsbyCondi(n, "SP  LIKE '%" + SP + "%'");
                }
            }
            return ds;
        }  // end of  get_SPPick

//編輯欄位- [類別(CLASS)]欄位挑選
        [HttpPost]
        public dynamic get_CLASSPick(string CLASS = "", int isComplete = 0)
        {
            string Tmp_Sql = " SELECT KEY_CODE as  CLASS ,DESCPT as CLASS_ "
                                        + " FROM   KEYCODE   "
                                        + " WHERE TBL_NAME = 'AMM_COMP'   "
                                        + " AND       KEY_NAME = 'CLASS'  ";
            string n = funId + "s_CLASS";
            DataSet ds = setupPickDs(n, Tmp_Sql, new string[] { "KEYCODE" });
            if (CLASS != null && !CLASS.Equals(""))
            {
                if (isComplete == 1)
                {
                    ds = getPickDsbyCondi(n, "CLASS='" + CLASS + "'");
                }
                else
                {
                    ds = getPickDsbyCondi(n, "CLASS  LIKE '%" + CLASS + "%'");
                }
            }
            return ds;
        }  // end of  get_CLASSPick

2026年9月1日 星期二

V60202 – combox - label - 唯讀 - 日期區間

 目的: V60202 – combox  - label  - 唯讀   - 日期區間

處理說明:  1>combox: 
                        var cmp_SAPDB = get_cmp_combox1("SAPDB", "s_SAPDB", 50, 80, Tmp_Store);

                        var Tmp_Store = Ext.create("Ext.data.Store", {
                                        fields: ["value", "displayName"],
                                         data: [            
                                                     { value: "ERPI", displayName: "ERPI", },
                                                     { value: "SAP", displayName: "SAP", },           
                                                 ]
                                     }
                                     );
                    2>唯讀: 
                        Ext.getCmp("s_CLASS_").setReadOnly(true);
                        Ext.getCmp("s_CLASS_").fieldCls= "readonly"; //顯示底色: 灰色
                   3>日期起迄
                        var cmp_CHKDT = get_cmp_dt1('盤點日期', 's_CHKDT1', 80, 100);
                        var cmp_CHKDT_lbl = get_cmp_lbl0(" ~ ", 20);
                        var cmp_CHKDT2 = get_cmp_dt0('s_CHKDT2', 100);
                        cmp_CHKDT.items.push(cmp_CHKDT_lbl, cmp_CHKDT2);
                  4>Label:
                       var cmp_Panel_LBL = get_cmp_panel1(150, 10, ""); //顯示文字
                       var cmp_SPACE = get_cmp_lbl0('', 30);
                       var cmp_BLUE = get_cmp_lbl0('藍色字:延測中', 130);
                       cmp_BLUE.style = { color: 'blue', fontSize: '13pt', };
                        var cmp_RED = get_cmp_lbl0('紅色字:時限器材將逾期', 220);
                        cmp_RED.style = { color: 'red', fontSize: '13pt',};
                        cmp_Panel_LBL.items.push(cmp_SPACE,cmp_BLUE, cmp_RED);




1>*.js

//combox : SAPDB --> ERPI/SAP
    var Tmp_Store = Ext.create("Ext.data.Store", {
        fields: ["value", "displayName"],
        data: [            
            { value: "ERPI", displayName: "ERPI", },
            { value: "SAP", displayName: "SAP", },           
        ]
    }
    );
    //function get_cmp_combox1(par_caption, par_id, par_l_width, par_width, par_store, par_flex) {
    var cmp_SAPDB = get_cmp_combox1("SAPDB", "s_SAPDB", 50, 80, Tmp_Store);

//設定 combox 的預設值
Ext.getCmp("s_SAPDB").setValue("ERPI");


//設定欄住唯讀 - 底色: 灰色
Ext.getCmp("s_CLASS_").setReadOnly(true);
Ext.getCmp("s_CLASS_").fieldCls= "readonly"; //顯示底色: 灰色

//盤點日期 - 起~迄
    var cmp_CHKDT = get_cmp_dt1('盤點日期', 's_CHKDT1', 80, 100);
    var cmp_CHKDT_lbl = get_cmp_lbl0(" ~ ", 20);
    var cmp_CHKDT2 = get_cmp_dt0('s_CHKDT2', 100);
    cmp_CHKDT.items.push(cmp_CHKDT_lbl, cmp_CHKDT2);

//顯示文字
var cmp_Panel_LBL = get_cmp_panel1(150, 10, ""); //顯示文字
    var cmp_SPACE = get_cmp_lbl0('', 30);
    var cmp_BLUE = get_cmp_lbl0('藍色字:延測中', 130);
    cmp_BLUE.style = { color: 'blue', fontSize: '13pt', };
    var cmp_RED = get_cmp_lbl0('紅色字:時限器材將逾期', 220);
cmp_RED.style = { color: 'red', fontSize: '13pt',};
    cmp_Panel_LBL.items.push(cmp_SPACE,cmp_BLUE, cmp_RED);

2026年8月26日 星期三

V20301- [複製]鈕- 複製勾選資料後,停留在最後一筆資料

 目的: V20301- [複製]- 複製勾選資料後,停留在最後一筆資料

處理說明: 1>store.on("load",function(store.records){
store.on('load', function (store, records) { //20260826 yalan 將標記跑到最後一筆 
 if (records.length > 0) {
     var lastRecord = records[records.length - 1];
       // 選取最後一筆
       grid.getSelectionModel().select(lastRecord);

}
}, this, {
single: true
});



1>*.js
                //因為複製後, 按[顯示資料]鈕, 並不會顯示剛才新增的資料,& Local 新增的資料    
                 //20260826 將標記移至最後一筆
                    var grid = Ext.getCmp('grid_Single');
                    var store = grid.getStore();
                    store.on('load', function (store, records) {  //20260826 yalan 將標記跑到最後一筆
                        if (records.length > 0) {
                            var lastRecord = records[records.length - 1];
                            // 選取最後一筆
                            grid.getSelectionModel().select(lastRecord);
                        }
                    }, this, {
                        single: true
                    });

                    Ext.getCmp('btn_Show').fireHandler();

V20301-[刪除]鈕- 刪除目前所勾選的資料 , 必需清空 PK_LIST & ALL_LIST

 目的: V20301-[刪除]- 刪除目前所勾選的資料 , 必需清空 PK_LIST & ALL_LIST

處理說明: 1> var cur_recs = CHK_PK_OBJ.ALL_LIST;
                       for (var i = 0; i < CHK_PK_OBJ.PK_LIST.length; i++) {
                              cur_rec = CHK_PK_OBJ.ALL_LIST[i];
                               Tmp_DataAry1.push(cur_rec);
                        }

                    let Tmp_DataString1 = JSON.stringify(Tmp_DataAry1);
                    var np = {};
                    np["DataString1"] = Tmp_DataString1;
                    Tmp_url = '../../api/V20301API/Delete_1';
                    Tmp_RtnStr = getUrlStr(Tmp_url, np, "刪除 勾選的[交修件單號] 資料");
                    if (!checkRtnOK(Tmp_RtnStr)) {
                        mywarnalert(Tmp_RtnStr);
                        return;
                    }


1>*.js
Ext.getCmp("btn_del").on('click', function (me, e, eOpts) {
        parent.onclick = function () { };
        var cur_recs = CHK_PK_OBJ.ALL_LIST;
        var cur_rec;        
        if (cur_recs.length == 0)
        {
            buttonModel.modelType = 0;
            mywarnalert('請先勾選要刪除的資料!!');
        }
        else {
            me.delMessage = "確定刪除勾選的資料嗎?";
            Ext.Msg.confirm('提醒', me.delMessage, callBackFunc);
            function callBackFunc(id) {
                if (id == 'yes') {
                    console.log("cur_recs.length:", cur_recs.length);
                    var gridstore = Ext.getCmp('grid_Single').store;
                    //刪除勾選.FMNO
                    var Tmp_DataAry1 = [];
                    for (var i = 0; i < CHK_PK_OBJ.PK_LIST.length; i++) {
                        cur_rec = CHK_PK_OBJ.ALL_LIST[i];
                        Tmp_DataAry1.push(cur_rec);
                    }
                    //2026/08/26 刪除後,必需將 PK_LIST & ALL_LIST 清空
                    CHK_PK_OBJ.PK_LIST = [];
                    CHK_PK_OBJ.ALL_LIST = [];
                    let Tmp_DataString1 = JSON.stringify(Tmp_DataAry1);
                    var np = {};
                    np["DataString1"] = Tmp_DataString1;
                    Tmp_url = '../../api/V20301API/Delete_1';
                    Tmp_RtnStr = getUrlStr(Tmp_url, np, "刪除 勾選的[交修件單號] 資料");
                    if (!checkRtnOK(Tmp_RtnStr)) {
                        mywarnalert(Tmp_RtnStr);
                        return;
                    }
                    else
                        mysuccessalert(Tmp_RtnStr);
                    //for (let i = 0; i <= cur_recs.length - 1; i++) {
                    //    console.log("i:", i);                        
                    //    //Ext.getCmp('grid_Single').getSelectionModel().select(cur_recs[i]); //grid select指向所選的資料
                    //    //cur_rec = Ext.getCmp('grid_Single').getSelectionModel().getSelection();
                    //    cur_rec = CHK_PK_OBJ.ALL_LIST[i];
                    //    console.log("cur_rec: ", cur_rec);                        
                    //    if (Ext.getCmp('btn_del').afterDel() == false) {
                    //        return;
                    //    }                                                
                    //} //  end of for (let i=0,)
                    //資料庫均刪除完成後, 才由 gridstore 移除資料
                    //for (let i = 0; i <= cur_recs.length - 1; i++) {
                    //    gridstore.remove(cur_recs[i]); //畫面上隱藏刪除列                     
                    //} //  end of for (let i=0,)
                    var toRemove = [];
                    Ext.getCmp('grid_Single').store.each(function (rec) {
                        if (rec.get('CHECK') == true)
                            toRemove.push(rec);
                            //gridstore.remove(rec); //畫面上隱藏刪除列  -->改成一次 remove all
                    });
                    gridstore.remove(toRemove); // remove all at once

                    Ext.getCmp('grid_Single').getView().refresh();
                    buttonModel.modelType = 0;
                }  // end    if (id == 'yes')             
            }  // end of callbackfunc
        }  //else { of if length>0            
    }) // end of click function