[Logo]  E3系統 開發.操作.問題 討論區 
[Search] 搜尋主題 [Recent Topics] 最新主題 [Hottest Topics] 熱門主題 [Members] 會員列表 [Groups] E3首頁
[Register] 會員註冊 [Login] 會員登入
文章發表人是: e3Admin
討論區首頁 » 個人資料 e3Admin » 文章發表人是 e3Admin
發表人 內容
E3系統核心功能已經過客戶的使用多年,
已經很穩定, 歡迎有興趣做行業別實作產品
的Java人加入.

可能你有行業別知識跟經驗, 又不想重頭
開發一套新的產品, 用一般市面的Java EE
架構, 又顯的太過龐大, 可以和我們一起研
究如何實作你們自己的行業產品.

有對E3任何技術問題, 都可以在這個論壇中
做發問.

加入的按鍵會在編輯畫面的上面, 主要用於加入
一般的工作按鍵, 來輔助編輯作業.

我們還是以 E3/SDK示範項目 "郵遞區號編輯" 做
程式加入解說. 這裡會加入二個按鍵 "列印發票",
"發票編輯".
src/com/dasam/e3010001/client/edit/CmzZipCode.java

在程式的import區要加入:
import com.dasam.java.XButton;

看下面程式碼, 在 doWorkInit() 中加入按鍵的layout,
同時設定要執行的 function 名稱.

    public void doWorkInit(HashMap map) throws Exception {
        super.doWorkDefault(map,this);
        this.moveRecord("init", XLet.getString(map.get("#link_edit_initValue")));

		//加入功能按鍵,
		XButton btnOutInvoice = this.getButton("printInvoice"," 列印發票 ", "exePrintInvoice",null, "view");//"view"表示在查詢狀態才enable
        xlay.setLocationAdd(btnOutInvoice, xlay.left+xlay.getTipLabelWidth(), 5);
        XButton btnInvoiceEdit = this.getButton("linkInvoiceEdit"," 發票編輯 ", "doLinkInvoiceEdit",null, "view");
        xlay.addComH(btnOutInvoice,btnInvoiceEdit, "3c","");//距 列印發票 鍵,3個字寬 

        //..............中間程式省略
    }


    //==========================================================================
    //列印發票 
    public void exePrintInvoice() throws Exception {
        //加入功能程式
    }

    //==========================================================================
    //發票編輯 
    public void doLinkInvoiceEdit() throws Exception {
        //加入功能程式
    }



單表單編輯, 或雙表單編輯, 的型板有一個
工具列的標準功能, "新增匯入", 可以匯入
excel的資料到新增資料中, 操作請看E3的
操作手冊.

標準匯入資料是以字串為主, 如果資料較複製
或是要先做調整再匯入時, 可以設定一個中間
的調整function, 來做資料加工程式. 尤其是
出貨單, 進貨單..等, 的雙表單匯入, 很難用標
準模式匯入, 都要依客戶的需求做匯入.

我們以 E3/SDK示範項目 "郵遞區號編輯" 做
加入匯入功能, 先看以下的程式碼.


A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java, 加入 "newimp" 權限細項
x.add2(rs,1,"D",".郵遞區號編輯","edit.CmzZipCode",1,"edit_1",2,"newimp");


B. 標準匯入功能
src/com/dasam/e3010001/client/edit/CmzZipCode.java
行47~50先做加入 新增匯入 的工具列按鍵, 記得加好, 要先打開群組權限.
行10 是設定那些是參照欄位, 寫入前會先檢查是否有參照筆.
public class CmzZipCode extends XFrameEditI {

    public CmzZipCode() throws Exception {
        this.isVoidWorkMode=true;
        this.isUnvoidWorkMode=true;
        this.convLangTables = "cmzZipCode,x";
        this.filterList = uiFilter("filter");
        this.serviceClassId = "edit.CmzZipCode";
		//this.importRefreFields = "deparId"; //匯入時要參照欄位,
        //this.adjustImportData = new com.dasam.work.XMethod(this,"exeAdjustImportData",null);
    }

    //==========================================================================
    public void doWorkInit(HashMap map) throws Exception {
        super.doWorkDefault(map,this);
        this.moveRecord("init", XLet.getString(map.get("#link_edit_initValue")));

		//editor layout
        //"主碼"
        XEText eId = new XEText(tbl("id"),10,this,"id");
        xlay.add(eId,0,0);
        eId.setFindRecord(this);
        //資料視窗
        XButton2 btnView = XTool.getViewButton("CmzZipCodeView",eId,this,"id", xwbar.getButton("first"));
        xlay.addComH(eId,btnView,1,0);
        editMap.put(btnView,"view");

        //"名稱"
        XEText eName = new XEText(tbl("name"),20,this,"name");
        xlay.add(eName,0,0);

        //"備註"
        XEText eMemo = new XEText(tbl("memo"),20,this,"memo");
        xlay.add(eMemo,0,0);

        this.addEditStateLabel("v",0,0,0);

        this.viewPack();
        setWorkObjectValue(DATA_RS);
        setWorkObjectEditStatus("view");
    }

    
	//==========================================================================
	//加入"匯入"的按鍵
	public HashMap getWorkBarMap() throws Exception {
		if (!this.isPassCtrl("newimp")) return super.getWorkBarMap();//無新增匯入權限,
		return XTool.getImportWorkBarMap(super.getWorkBarMap());//加入 '匯入',
	}

    //==========================================================================
    //excel匯入調整,
    /*public void exeAdjustImportData(boolean isData, XRowSet rs, org.apache.poi.hssf.usermodel.HSSFRow row) throws Exception {
        if (isData){
        	//id, excel第1欄
            Object id = XExport.getCellValue(row.getCell(row.getFirstCellNum()));
            rs.setObject("id",id);
            //name, excel第2欄
            Object name = XExport.getCellValue(row.getCell((short)(row.getFirstCellNum()+1)));
            rs.setObject("name",name);
        }
    }*/
    
}


C. 匯入功能加工
以上面的程式碼, 把行11及 行54~63的備註拿掉,
就可以自行設計 exeAdjustImportData() 中的程式
碼, 做匯入前的資料加工了.



資料速查是一個類似excel的格式查詢畫面,
直接點二下資料筆, 可以連結到編輯畫面, 我
們用SDK的示範項目 "郵遞區號資料", 來做說明.


A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java, 新加入行2
x.add2(rs,1,"E",".會員郵寄標籤","rpt.CmzMemberMailLabel",1,"report_3",3,null);
x.add2(rs,1,"F",".郵遞區號速查","edit.CmzZipCodeList",1,"list_1",0,"field_cfg",1);//加這行
x.addLine(rs,1);


B. 設定條件欄位
resource/com/dasam/e3010001/client/res/lang/cmz_ui.ppt
# edit.CmzZipCodeList 
edit.CmzZipCodeList.filter = [@edit.CmzZipCode.filter]


C. Client程式
src/com/dasam/e3010001/client/edit/CmzZipCodeList.java
   public CmzZipCodeList()  throws Exception {
		//frame設定
        this.convLangTables = "cmzZipCode,x";
        this.filterList = uiFilter("filter");
		this.serviceClassId = "edit.CmzZipCodeList";
		//this.setPageRecord(15);
        this.fieldStyle = "{id=wd:10c;ha:c}{name=wd:15c}{memo=wd:15c}{creater=wd:10c}{createTime=wd:15c;ha:c}{updater=wd:10c}{updateTime=wd:15c;ha:c}";
		this.defaultFieldList = "id,name,memo,creater,createTime,updater,updateTime";
        this.fieldList = com.dasam.client.gui.XDlgFieldCfg.getFieldList(getClassFileName(), fieldStyle, defaultFieldList);
		this.linkEditClassId = "edit.CmzZipCode";
        this.isReturnNullClear = true;
    }

	//==========================================================================
	//重載,起始
	public void doWorkInit(HashMap map) throws Exception {
        map.put("xwbar.icon.width","30"); //加大icon
        super.doWorkDefault(map,this); 
		this.viewPack();
	}

    //==========================================================================
    //資料顯示前加工,
    public void doAdjustReturnRs(XRowSet rs) throws Exception {
    	rs.getField("creater").setLangName("建檔人");//欄名
    	//rs.printData(); //debug
    }
    
}


D. Server程式
src/com/dasam/e3010001/server/edit/CmzZipCodeList.java
public class CmzZipCodeList extends XServiceListI {


    //==========================================================================
    public HashMap doWorkInit(HashMap map) throws Exception {
        setXUserInformationObject(map, true); //建立user

        setLastUpdateTime(map); //設定查詢筆數參數
        setPageRecord(map); //頁筆數
        this.viewTableName = "cmzZipCode";
        //查詢時用到的參數設定
        if (filterString==null) filterString = XLet.getString(map.get("filter"));
        this.viewSelect = "select a.*  from cmzZipCode a  ";
        this.viewIdField = "id";

        HashMap ret = defaultFunctions(map);
        return ret;
    }

}


一般在做網站訂單時, 常會有收件人的姓名, 電話, 行動,
收貨地址, 跟一般進銷存的出貨單不太一樣.

這裡用重載出貨單程式的方式加入這些欄位, 分成以下
的步驟來實作.

A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java
        x.setExtendId(data, new String[]{
            "edit.OutStk", //加入出單重載
            "edit.Item",
            "edit.Member",
        }, "_2");


B. 建立資料庫
resource/cmz.sql
加好後再用維護指令執行 database.update.cmz
alter table `outStk` add `recName` varchar(50) not null default ''; --收件人
alter table `outStk` add `recTel` varchar(50) not null default ''; --收件人電話
alter table `outStk` add `recMobile` varchar(50) not null default ''; --收件人行動電話
alter table `outStk` add `recAddr` varchar(100) not null default ''; --收件人地址


C. 資料庫欄名中文對照
resource/com/dasam/e3010001/client/res/lang/cmz_table.ppt
加入以下欄名對照.
#出貨單-----------------
outStk.recName = 收件人
outStk.recTel = 電話
outStk.recMobile = 手機
outStk.recAddr = 收貨地


D. Client出貨單編輯重載
src/com/dasam/e3010001/client/edit/OutStk_2.java
public class OutStk_2 extends OutStk {

    public OutStk_2() throws Exception {
        if (isOutStk){
        	//加入搜尋條件,可以省略
    		this.filterList += ";收件人,a.recName,1;收件地址,a.recAddr,1";
    	}
    }

    //==========================================================================
    //overload客制化,
    public void doAdjustLayout(com.dasam.java.XTabbedPane xtab) throws Exception {
    	if (!isOutStk) return; //退貨單不加
        //整個往下移欄位,
        xlay.moveY(this,"1.2h","memo,creater,createTime,updater,updateTime,subtotal_sum,discount,"
            +"tax,recable,disct,cancelNo,cancelOk,subtotalCost_sum,accDate,itemQty_sum,"
            +this.DETAIL_ITEM);
        xlay.innerHeight += xlay.CHAR_HEIGHT*1.2;

        //"收件人"
        XEText recName = new XEText(tbl("recName"),8,this,"recName");
        xlay.addV(getXEdit("hrId"),recName,0,0);
        //"收件人電話"
        XEText recTel = new XEText(tbl("recTel"),10,this,"recTel");
        xlay.addH(recName,recTel,"-1c","0");
        //"收件人行動電話"
        XEText recMobile = new XEText(tbl("recMobile"),10,this,"recMobile");
        xlay.addH(recTel,recMobile,"-1c","0");
        //"收件人地址"
        XEText recAddr = new XEText(tbl("recAddr"),25,this,"recAddr");
        xlay.addH(recMobile,recAddr,"-1c","0");

        //編輯順序
        this.insertFocusList("outOrderId","recName,recTel,recMobile,recAddr");
    }

}

這裡用重載商品編輯的方式來做修改,
我們以SDK示範項目做修改, 直接改
src/com/dasam/e3010001/client/edit/Item_2.java


setResize(true) 時, setImageSize(250,250) 才有作用.
如果不設 setImageSize, 會以編輯框大小為主.
    public void doAdjustLayout(XTabbedPane xtab) throws Exception {
        if (xtab==null){
            //修改圖片2設定
        	XEImage eImg2 = (XEImage)this.getXEdit("isImg2");
        	eImg2.setLimitDataLen(1000*1000); //最大1M,
        	eImg2.setResize(false);//不縮圖,原尺寸,
        	//eImg2.setImageSize(250,250);//縮為250x250,
        	return;
        }

        this.addWorkXPage(xtab,"bom","  組合  ");
        //..... 以下程式省略


這裡再標準程式中, 直接加入一種新的出貨簽單,
這裡會在原來的出貨簽單程式, 用重載的方式做
加入程式. 我們加入到SDK的示範專案.

直接下載文章後的附檔.


A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java
        x.setExtendId(data, new String[]{
            "rpt.OutStkSign",    //加入這一行,重載原程式設定
            "edit.Item",
            "edit.Member",
        }, "_2");


B. Client程式
src/com/dasam/e3010001/client/rpt/OutStkSign_2.java
會在畫面多出一個樣式選項: 標準樣式, 客制樣式.
public class OutStkSign_2 extends OutStkSign {


    public OutStkSign_2() throws Exception {
        this.reportFormats = new String[]{"標準樣式","","客制樣式","_2"};
        this.serviceClassId = "rpt.OutStkSign_2";
    }

    //==========================================================================
    //<重載>
    public void doWorkInit(HashMap map) throws Exception {
        super.doWorkInit(map);
        getXEdit("reportFormats").setStatic(true);
    }

    //==========================================================================
    public void doMakeReportExtParam() throws Exception {
        super.doMakeReportExtParam();
        if (isOutStk){//改變子報表名稱,只有出貨單,
            String fmt = getXEdit("reportFormats").getValue().toString();
            addReportExtParam("#subreport",  "sys.OutStkDetail2"+fmt); //subreport檔名,
        }
    }

    //==========================================================================
    //報表資料加工,
    public void doAdjustReportRs(XProgressWork xpw, XRowSet rs, HashMap rptParam) throws Exception {
        super.doAdjustReportRs(xpw, rs, rptParam);
        //2009.10.20改為只有在客制樣式時.
        if (this.getReportFormatEditor().getSelectedIndex()==0) return;
        rs.getField("tsDate").setLen(100);
        for (rs.beforeFirst(); rs.next();){
            XRowSet d = rs.getRs("detail_item");
            //明細自動補足7的倍數.
            int ar = d.getRowCount() % 7;
            if (ar>0){ ar=7-ar; for(int i=0; i<ar; i++) d.insertRow(); }
            //加入明細備註
            d.insertField(new XField("cmzMemo",XField.TYPE_STRING,100)); 
            String[] m = XLet.getStringArray(rs.getString("memo"),12);
            for (int i=0; i><m.length; i++) if (d.setRowIndex(i)) d.setString("cmzMemo",m[i]);
            //加入判斷是否結束欄位
            d.insertField(new XField("isEnding",XField.TYPE_STRING,5));
            d.last();
            d.setString("isEnding","1");//不為null表示為ending,
            //日期字串轉換
            String[] dt = rs.getString("tsDate").split("[-]");
            rs.setString("tsDate", dt[0]+" 年 "+dt[1]+" 月 "+dt[2]+" 日");
        }
        //表尾條文轉為字串,
        com.dasam.work.XArrayReport xa = (com.dasam.work.XArrayReport)rptParam.get("ending");
        rptParam.put("ending",xa.getDataString());
        //加入logo圖形
        byte[] logo = com.dasam.work.XFio.readData(XSystem.getSysResource(XSystem.getResourceName("res/logo/logo.jpg")).openStream());
        rptParam.put("logo_img", logo);
    }

}


C. Server程式
src/com/dasam/e3010001/server/rpt/OutStkSign_2.java
加入select欄位.
public class OutStkSign_2 extends OutStkSign {

    public OutStkSign_2(){
        this.adjustMainField = ",d.unitTitle 'cust_unitTitle'";
        this.adjustDetailField = ",b.specif 'itemSpec'";
    }
}


D. copy公司logo圖片
放到
resource/com/dasam/e3010001/client/res/logo/logo.jpg


E. 編譯報表format檔
resource/com/dasam/e3010001/client/rpt/fmt/sub/OutStkDetail2_2.xml
開啟ireport後, 按[File] / [Open], 讀取xml後, 再按 [Build] / [Compile]
表頭的公司資料要改成你們公司的名稱跟地址.



在E3/SDK中, 分為client,server用的class, 分類大致如下:

Client端用class:
com.dasam.client.*
com.dasam.work.*
com.dasam.java.*
com.dasam.bjnet.client.*
com.dasam.e3010001.client.*

Server端用class:
com.dasam.server.*
com.dasam.work.*
com.dasam.db.*
com.dasam.bjnet.server.*
com.dasam.e3010001.server.*

所以套件會用在網路執行時, 要特別注意package的引用.


Client編輯畫面的架構:
client的編輯元件為com.dasam.client.edit.*
會以XEdit介面實作. 每個操作畫面的editor
再用XEditCollection 集合在一起.




雙表單編輯是指做MySQL二個資料表以上的編輯工作,
一般都是一對多的關係, 就是會有一筆表頭對應多筆明
細的情況, 例如: 進貨單, 出貨單, 報價單..等.

這裡用比較簡單的雙表單 "產品組合單建立" 做範本
請先看SDK的示範專案. 要先了解 單表單編輯 再研
究雙表單, 會較容易理解.


A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java
x.add2(rs,1,"A",".產品組合單建立","edit.CmzBomItem",1,"edit_2",2,null);


B. 建立資料庫
resource/cmz.sql
--** BOM筆狀態
insert ignore bjn_tableState values('cmzBomItem',0,0,0,''); --bom結構

--** BOM結構
create table if not exists `cmzBomItem` (
	`id` varchar(30) not null default '', --商品主碼
	`memo` varchar(250) not null default '', --備註
	`swDel` tinyint unsigned not null default 0, --作廢, 1=yes,

	`creater` varchar(20) not null default '', --建立人員
	`createTime` datetime not null default '0-0-0', --建立時間
	`updater` varchar(20) not null default '', --修改人員
	`updateTime` datetime not null default '0-0-0', --修改時間

	primary key (id)
) type=InnoDB ;

--** 結構明細
create table if not exists `cmzBomItemDetail` (
	`rela` varchar (30) not null default '', --相關欄,
	`no` smallint unsigned not null default 0, --序號,
	`itemId` varchar (30) not null default '', --商品主碼
	`qty` decimal(9,4) not null default 0, --組合數量

	primary key (rela,no),
	index `ix_itemId` (itemId)
) type=InnoDB;


C. Client程式
src/com/dasam/e3010001/client/edit/CmzBomItem.java
public class CmzBomItem extends XFrameEditII {

    public CmzBomItem() throws Exception {
        this.convLangTables = "cmzBomItem,x";
        this.filterList = null;
        this.serviceClassId = "edit.CmzBomItem";
        this.itemReferId = "simpleItem";
        this.idField = "id";
        this.editFirstFieldName = null;
        this.editObjectDisable = null;
        this.displayInsertMsg = null;
        this.isCloseTimeWorkMode = false;
        this.isVoidWorkMode = false;
	}

    //==========================================================================
    public void doWorkInit(HashMap map) throws Exception {
		map.put("xwbar.icon.width","32"); //icon size
        super.doWorkDefault(map,this);

        this.moveRecord("init", XLet.getString(map.get("#link_edit_initValue")));

        //layout editor
        XEText eId = new XEText(tbl("id"),15,this,"id");
        xlay.add(eId,0,0);
        eId.setFindRecord(this);
        this.doReference(eId, "cmzBomItem","item_name,name,item_unit,unit");
        //視窗
        XButton2 btnView = XTool.getViewButton("CmzBomItemView",eId,this,"id", xwbar.getButton("first"));
        xlay.addComH(eId,btnView,1,0);
        editMap.put(btnView,"view");
        //商品視窗,
        XButton2 btnItemView = XTool.getViewButton("ItemView",eId,editMap,"id,id,item_name,name,item_unit,unit");
        xlay.addComH(btnView,btnItemView,5,0);
        editMap.put(btnItemView, "new,newas");

        //品名
        XEText eItemName = XEText.createLabelText(null,25,this,"item_name",0,0);
        xlay.addComV(eId,eItemName,0,0);
        //單位
        XEText eItemUnit = XEText.createLabelText(null,6,this,"item_unit",0,0);
        xlay.addComH(eItemName,eItemUnit,5,0);

        //detail
        XEGrid eDetail = getDetailGrid(DETAIL_ITEM);
        xlay.add(eDetail,0,0,0,5);
        //"備註"
        XEText eMemo = new XEText(tbl("memo"),40,this,"memo");
        xlay.add(eMemo,0,0);


        this.addEditStateLabel("v",0,0,0);

        this.viewPack();
        setWorkObjectValue(DATA_RS);
        setWorkObjectEditStatus("view");

    }

    //==========================================================================
    //新筆,資料起始,"new","newas"
    public void setNewRecordData(String workId) throws Exception {
        if (workId.equals("newas")){
            getXEdit(idField).setValue("");
        }
    }

    //==========================================================================
    //相關欄位參照驗証檢查,主要針對"save_edit","save_new","save_newas"
    public boolean isValidateData(String workId) throws Exception{
        if (XLet.isFindId("save_edit,save_new,save_newas",workId)){
            //參照驗証,
            if (!isValidateText("x2,cmzBomItem","id,e,r")) return false;
            //grid驗証,
            if (!((XEGrid)getXEdit(DETAIL_ITEM)).isCheckValidCount("itemId")) return false;
            if (!((XEGrid)getXEdit(DETAIL_ITEM)).isCheckReference("itemId")) return false;
            //檢查子商品內是否有父商品,(只檢查第一階,多階檢查在server端)
            XRowSet rs = ((XEGrid)getXEdit(DETAIL_ITEM)).getGridRowSet("itemId");
            if (rs.isFindRow("itemId", getXEdit("id").getValue().toString().trim())){
                xmsg.err("組合子產品中包含了主產品!","");
                return false;
            }
        }
        return true;
    }

    //======================================================================
    //明細grid,
    public XEGrid getDetailGrid(String fieldName) throws Exception {
        //取得rs表結構,
        XRowSet rs = new XRowSet((HashMap)mainRs.getObject(DETAIL_ITEM));
        //column
        XEGridColumn[] cols = new XEGridColumn[]{
            new XEGridColumn(tbl("itemId"), new XEText(rs.getField("itemId")),14,0),//"品 碼"
            new XEGridColumn(tbl2("itemName"), null, rs.getField("itemName"),24,0), //"品 名"
            new XEGridColumn(tbl("qty"), new XEText(rs.getField("qty")),8,0),//"數量"
            new XEGridColumn(tbl("unit"), null, rs.getField("itemUnit"),6,0), //"單位"
        };
        //建立grid
        XEGrid g = new XEGrid("", cols, 10, 300, this, fieldName);
        g.setReturnFields("#itemId,qty");
        g.getColumn("itemId").setViewButton(XTool.getViewButton("ItemView",this,"exeDetailItemView",new Object[]{g,""}));
		((XEText)g.getColumn("itemId").editor).setLinkEditClassId("edit.Item");
        ((XEText)g.getColumn("qty").editor).setMinEditValue(new Integer(1));
		//開始建構grid
        g.makeWorking();

        g.addChangeValueAction(this,"exeDetailChangeValue",null);
        g.setLinkEditClassId("itemId;edit.Item");
		return g;
    }

    //==========================================================================
    //設定一筆資料,
    //isId : 是否設定主碼,
    //ixData : 目前編輯的row index
    public void setDetailItemData(XEGrid g, XRowSet rs, int ixData, boolean isId) throws Exception {
		if (isId) g.getColumn("itemId").setValue(ixData, rs==null? "" : rs.getString("id"));
        if (ixData==g.getDataIndex()) g.getColumn("itemId").editor.setReference(rs!=null); //要設定editor,否則setValue()時會重設setReference(),
        g.getColumn("itemId").setReference(ixData, rs!=null); //若有檢查要設定參照成功,
        g.getColumn("itemName").setValue(ixData, rs==null? "" : rs.getString("name"));
        g.getColumn("qty").setValue(ixData, rs==null? "" : "1");
        g.getColumn("itemUnit").setValue(ixData, rs==null? "" : rs.getString("unit"));
    }


}



D. Server程式
src/com/dasam/e3010001/server/edit/CmzBomItem.java
public class CmzBomItem extends XServiceEditII {

    private static final String editDetailTableName = "cmzBomItemDetail";

    public CmzBomItem(){
        this.tableStateId = "cmzBomItem";
        this.editTableName = tableStateId;
        this.editIdField = "id";
        this.editSelect="select a.*, b.name 'item_name', b.unit 'item_unit' from cmzBomItem a   left join item b on b.id=a.id ";
        this.editSelectDetail="select a.itemId,a.qty, concat(if(b.swDel=1,'*',''),b.name) as 'itemName', b.unit 'itemUnit' from cmzBomItemDetail a  left join item b on b.id=a.itemId ";
        this.editProperty = "CLS_MAIN,id, CLS_MUSTX,updateTime"; //必要上傳欄位,
        //個別設定
        this.setDeleteWorkMode(true); //用刪除,
        this.isCloseTimeWorkMode = false; //不使用結帳日,
        this.isAutoSortListNo = false; //新增時,不自排單碼
        this.editOrderBy="a.id"; //找資料排序碼,
    }

    //==========================================================================
    public HashMap doWorkInit(HashMap map) throws Exception {
        setXUserInformationObject(map, true); //建立user

        setLastUpdateTime(map);
        if (filterString==null) filterString = XLet.getString(map.get("filter"));

        HashMap ret = defaultFunctions(map);
        return ret;
    }

    //==========================================================================
    //只執行明細,main在XServiceEditII.insertRecord_detail()會處理
    //己有作trans的指令,
    public void insertRecord_detail(HashMap map, XRowSet rs) throws Exception {
        //detail
        XRowSet rs2 = new XRowSet((HashMap)rs.getObject(DETAIL_ITEM));
        String rela = rs.getString("id");
        String[] values = XSql.getValues(null,rs2,null,false,false,false); //讀取所有set組字串,

        for (int i=0; rs2.setRowIndex(i); i++){
			//新增一筆明細
			String fixValues = new StringBuffer("'").append(rela).append("',")//額外加入insert sql
				.append(i+1).toString();
			String insert = new StringBuffer("insert ").append(editDetailTableName).append(" ")
				.append( XSql.toInsert(values[i],"rela,no",fixValues) )
				.append(";").toString();
			xdb().exeSql(insert); //執行新增
        }

        //多階檢查子品中,是否包含子品,
        XRowSet bom = CmzBomLevelList.getBomData(xdb(),rela);
        if (XLet.getInt(bom.max("lvl"))>10) throwWorkException(">組合子產品超過了10個階層!");
        if (bom.isFindRow("itemId",rela)){//子產品中,找到有母品存在,
            int lvl = bom.getInt("lvl");
            String bomPath = rela;
            while(bom.previous()){
                //if (bom.getInt("lvl")<1) break;//為root階層,
                if (bom.getInt("lvl")<lvl){
                    lvl=bom.getInt("lvl");
                    bomPath = bom.getString("itemId")+"\n"+bomPath;//結構路徑
                }
            }
            bomPath = rela+"\n"+bomPath;
            throwWorkException(">組合子產品中包含了主產品! 結構:  \n"+bomPath);
        }
    }

    //==========================================================================
    //更新作業,
    public void updateRecord_detail_old(HashMap map, XRowSet rs) throws Exception {
        String idValue = rs.getString(editIdField);
        deleteRecord_detail(map, idValue); //做回帳,及刪除,
    }

    //--------------------------------------------------------------------------
    //新資料,直接用insert,
    public void updateRecord_detail_new(HashMap map, XRowSet rs) throws Exception {
        insertRecord_detail(map, rs);
    }

    //==========================================================================
    //會先回帳,再刪除,
    public void deleteRecord_detail(HashMap map, String idValue) throws Exception {
        voidRecord_detail(map, idValue);
        //刪除明細
        String sql = new StringBuffer("delete from ").append(editDetailTableName)
            .append(" where rela='").append(idValue).append("';").toString();
        xdb().exeSql(sql);
    }

    //==========================================================================
    //作廢明細筆. 主要是依idValue做明細筆的回帳,
    public void voidRecord_detail(HashMap map, String idValue) throws Exception {
    }


}


這裡的單資料是指只要下一句SQL語法就可以產出
所要資料的標準型報表的製作. 例如: 產品列表,
客戶名冊, 廠商名冊..等.

這裡以SDK示範專案 "會員年費單列表" 作範本.
遇同類型的報表設計可以依照流程複製, 再做修改
就可以產生新的報表.


A. 主選單項目
x.add2(rs,2,"B",".會員年費單列表","rpt.CmzMemberYearFeeList",1,"report_1",3,null);


B. Client報表程式
src/com/dasam/e3010001/client/rpt/CmzMemberYearFeeList.java
一開始設計, 報表操作介面, 有那些報表範圍條件, 表尾條文..等
行9, 可以在沒有報表fmt檔時做測試執行
行52, 測試select的資料,到client的實際情況,做第一步除錯
public class CmzMemberYearFeeList extends XFrameReport {


    public CmzMemberYearFeeList() throws Exception {
        //this.langTableId = "rpt";
        this.convLangTables = "cmzMemberYearFee,member,x";
        this.serviceClassId = "rpt.CmzMemberYearFeeList";
        //this.isViewDebug = true;
    }

    //==========================================================================
    //重載,起始
    public void doWorkInit(HashMap map) throws Exception {
        super.doWorkDefault(map,this);

        //編輯項目
        this.addXETextRange("年度",6,"tsYear",DATE_Y,20,true,"time",null);
        XLib.memberId(this,true,"會員");
        XLib.sw(this,true,"狀態","swState","swState.def","{def=255}{left=2}{right=2}");

        setOtherFilterBegin();//----------
		XLib.tsDate(this,true,"收款日");
        XLib.swDel(this,true);
		setOtherFilterEnd();//----------

        addEndingAndFormats();
        this.viewPack();
        this.doWorkBarAction("init");

    }

    //==========================================================================
    //組合報表的條件式文字,
    public void doMakeReportExtParam() throws Exception {
        this.addReportExtParam("filter1", getFilters("@tsYear, &&, @memberId"));
        this.addReportExtParam("filter2", getFilters("@tsDate, &&, swState"));
        this.addReportExtParam("filter3", getFilters("&&, swDel"));
    }

    //==========================================================================
    //報表資料加工,
    public void doAdjustReportRs(XProgressWork xpw, XRowSet rs, HashMap rptParam) throws Exception {
        HashMap state = this.tblMap("swState.def");
        //加入主表欄位,
        rs.insertField(new XField("state_txt", XField.TYPE_STRING,50));
        rs.insertField(new XField("del_txt", XField.TYPE_STRING,50));
        for (int i=0; rs.setRowIndex(i); i++){
            rs.setObject("state_txt", state.get(rs.getString("swState"))); //狀態,
            rs.setString("del_txt", rs.getBoolean("swDel")?"**":""); //作廢文字
        }
        //rs.printData();
    }

}


C. Server報表程式
src/com/dasam/e3010001/server/rpt/CmzMemberYearFeeList.java
主要是由client的操作條件來select資料庫的資料
行62 會依client條件欄,組合SQL的Where子句
public class CmzMemberYearFeeList extends XServiceReport {

    //==========================================================================
    //make,
    public HashMap makeReport(HashMap map) throws Exception {
        XRowSet rs = XRowSet.getRowSet(map);
        String where = XSql.getWhere(rs,"a.tsYear=@, a.memberId=@, a.recDate:tsDate=@, a.swState==, a.swDel==");
        String sql = new StringBuffer()
            .append("select a.id, a.tsYear, a.memberId, a.money, a.swState, a.recDate, a.swDel, b.name 'member_name' ")
            .append("from cmzMemberYearFee a ")
            .append("left join member b on b.id=a.memberId ")
            .append(where).toString();
        xdb().exeSql(sql);
        return this.getReturnMapReport(rs);
    }

}


D. 設計報表輸出樣式
resource/com/dasam/e3010001/client/rpt/fmt/CmzMemberYearFeeList.xml
這裡的樣式是用ireport工具來做設計, 原始碼是一個xml檔,
但設計完成可以編譯儲存為fmt檔, E3是整合執行fmt檔.
可以直接執行 C:\dasamx_dev\ireport.bat 再開啟xml檔做編譯.
開啟ireport後, 按[File] / [Open], 讀取xml後, 再按 [Build] / [Compile]
要先看 E3/SDK安裝説明 設好JAVA_SDK_PATH.



單一表單編輯是指做MySQL一個資料表的編輯工作,
一般都是做參照的基本資料表.
這裡用SDK專案的 "郵遞區號編輯" 功能的分析設計
步驟. 這裡的原碼行號是標示作用, 並非原始檔的行號.
主要是做討論標示用.

所以如果要新增一個單表單的編輯程式, 可以照這些
步驟copy一次, 再修改要編輯的各欄位值.


A. 主選單項目
src/com/dasam/e3010001/client/SystemDataCmz.java
x.add2(rs,1,"D",".郵遞區號編輯","edit.CmzZipCode",1,"edit_1",2,null);


B. 建立資料庫
resource/cmz.sql
要注意, 行2,行4的資料表名稱要同步. 如何執行cmz.sql請看 E3/SDK安裝説明
insert ignore bjn_tableState values('cmzZipCode',0,0,0,'');

create table if not exists `cmzZipCode` (
	`id` varchar(10) not null default '',
	`name` varchar(50) not null default '', --簡稱
	`memo` varchar(100) not null default '', --備註
	`swDel` tinyint unsigned not null default 0, --作廢, 1=yes,

	`creater` varchar(20) not null default '', --建立人員
	`createTime` datetime not null default '0-0-0', --建立時間
	`updater` varchar(20) not null default '', --修改人員
	`updateTime` datetime not null default '0-0-0', --修改時間

    primary key (id)
) type=InnoDB ;


C. 資料庫欄名中文對照及簡繁設定(3個文檔)
resource/com/dasam/e3010001/client/res/lang/cmz_table.ppt, cmz_ui.ppt, cmz_xclass.ppt
#============ cmz_table.ppt ============
#區碼-----------------
cmzZipCode.id = 區碼 || 区码
cmzZipCode.name = 名稱

#============ cmz_ui.ppt ============
#----------- edit.CmzZipCode ------------
edit.CmzZipCode.filter = a.id,1;a.name,1;[@x.memo,tbl],a.memo,1;[@x.swDel,tbl],a.swDel,2
# edit.CmzZipCodeView 
edit.CmzZipCodeView.title = [@XTool.view_button.CmzZipCodeView,cls]
edit.CmzZipCodeView.filter = [@edit.CmzZipCode.filter]

#============ cmz_xclass.ppt ============
XTool.view_button.CmzZipCodeView = 郵遞區號資料視窗 || 邮递区号资料视窗


D. 資料視窗程式
Client: src/com/dasam/e3010001/client/edit/CmzZipCodeView.java
public class CmzZipCodeView extends com.dasam.client.gui.XDlgView {

    public CmzZipCodeView()  throws Exception {
        this.convLangTables = "cmzZipCode";
        this.setTitle(ui("title"));
        this.filterList = uiFilter("filter");
        this.serviceClassId = "edit.CmzZipCodeView";
        this.fieldStyle = "{id=wd:80;ha:c}{name=wd:220}";
        this.fieldList = "id,name";
    }

}

Server: src/com/dasam/e3010001/server/edit/CmzZipCodeView.java
public class CmzZipCodeView extends XServiceListI {

    public HashMap doWorkInit(HashMap map) throws Exception {
        setXUserInformationObject(map, true); //建立user
        setLastUpdateTime(map);
        setPageRecord(map); //頁筆數
        this.tableStateId = "cmzZipCode";
        this.viewTableName = tableStateId;
        if (filterString==null) filterString = XLet.getString(map.get("filter"));
        this.viewSelect = "select a.id, concat(if(swDel=1,'*',''),name) as 'name', swDel from cmzZipCode a ";

        return defaultFunctions(map);
    }

}


E. 單表編輯主程式
Client: src/com/dasam/e3010001/client/edit/CmzZipCode.java
public class CmzZipCode extends XFrameEditI {

    public CmzZipCode() throws Exception {
        this.isVoidWorkMode=true;
        this.isUnvoidWorkMode=true;
        this.convLangTables = "cmzZipCode,x";
        this.filterList = uiFilter("filter");
        this.serviceClassId = "edit.CmzZipCode";
    }

    public void doWorkInit(HashMap map) throws Exception {
        super.doWorkDefault(map,this);
        this.moveRecord("init", XLet.getString(map.get("#link_edit_initValue")));

		//editor layout
        //"主碼"
        XEText eId = new XEText(tbl("id"),10,this,"id");
        xlay.add(eId,0,0);
        eId.setFindRecord(this);
        //資料視窗
        XButton2 btnView = XTool.getViewButton("CmzZipCodeView",eId,this,"id", xwbar.getButton("first"));
        xlay.addComH(eId,btnView,1,0);
        editMap.put(btnView,"view");

        //"名稱"
        XEText eName = new XEText(tbl("name"),20,this,"name");
        xlay.add(eName,0,0);

        //"備註"
        XEText eMemo = new XEText(tbl("memo"),20,this,"memo");
        xlay.add(eMemo,0,0);

        this.addEditStateLabel("v",0,0,0);

        this.viewPack();
        setWorkObjectValue(DATA_RS);
        setWorkObjectEditStatus("view");
    }

}

Server: src/com/dasam/e3010001/server/edit/CmzZipCode.java
public class CmzZipCode extends XServiceEditI {

    public HashMap doWorkInit(HashMap map) throws Exception {
        setXUserInformationObject(map, true); //建立user
        setLastUpdateTime(map);
        this.tableStateId = "cmzZipCode";
        this.editTableName = tableStateId;
        this.setDeleteWorkMode(false); //設定使用作廢方式,
        this.isUnvoidWorkMode=true; //設定可使用回復作廢方式,
		if (filterString==null) filterString = XLet.getString(map.get("filter"));
        this.editSelect="select * from cmzZipCode a ";

        HashMap ret = defaultFunctions(map);
        return ret;
    }

}



其他行業別的問題,
歡迎在這版做討論~
所有客制套件最先整合的是選單,
把各個要客制的功能先列在選單中,
包含要重載的程式, 也是在選單中
做設定. 請看 SDK中的範例專案的
com.dasam.e3010001.client.SystemDataCmz.java


package com.dasam.e3010001.client;

import com.dasam.work.XRowSet;
import com.dasam.work.XLet;
import com.dasam.client.menu.XMenuAdd;
import com.dasam.client.XSystem;


public class SystemDataCmz {


    //--------------------------------------------------------------------------
    //data : 原menu資料,要預防原系統的class id名稱,
    //insPoint : menu內定統一要加入的點,也可以自己設定,內定:"_window"
    public static XRowSet addMenuData(XRowSet data, String insPoint) throws Exception {
        XMenuAdd x = new XMenuAdd();
        XRowSet rs = x.createRsMenu();//開空menu

        //加入menu,名稱前加".",表示不轉語系,
        x.add0(rs,"X",".客制","_XX",null);
            x.add2(rs,1,"A",".產品組合單建立","edit.CmzBomItem",1,"edit_2",2,null);
            x.add2(rs,1,"B",".產品多階展開表","rpt.CmzBomLevelList",1,"report_1",3,null);
            x.addLine(rs,1);
            x.add2(rs,1,"C",".取得主機時間","cmz_get_server_time",1,null,0,null);
            x.addLine(rs,1);
            x.add2(rs,1,"D",".郵遞區號編輯","edit.CmzZipCode",1,"edit_1",2,null);
            x.add2(rs,1,"E",".會員郵寄標籤","rpt.CmzMemberMailLabel",1,"report_3",3,null);
            x.addLine(rs,1);
            x.add1(rs,1,"Z",".會員年費管理","_X_Z",null);
                x.add2(rs,2,"A",".會員年費單編輯","edit.CmzMemberYearFee",1,"edit_1",2,null);
                x.add2(rs,2,"B",".會員年費單列表","rpt.CmzMemberYearFeeList",1,"report_1",3,null);

        //將結構加在'視窗'之前
        data = com.dasam.client.system.XSystemData.insertMenuData(data, rs, insPoint);

        //做原程式extends,
        //Item_2 --> Item == 商品加入組合頁簽
        //Member_2 --> Member == 會員加入郵遞區號
        x.setExtendId(data, new String[]{
            "edit.Item",
            "edit.Member",
        }, "_2");

        //刪除原系統menu
        //x.delete(data, "edit.OutStk");
        return data;
    }



    //--------------------------------------------------------------------------
    //執行授權的序號
    public static boolean isAuthorize() throws Exception {
        return true;
        //return XSystem.isPassSerial("01-001-0104,01-001-0105");
    }

}


所以我們在執行這個客制插件時, 在主選單會出現
這裡所增加的部份在 "視窗" 選單的前面. 這支程式
像客制專案的定義區, 定義增加那些程式功能, 或修
改那些程式.

行20是根節點, 在加在選單的根部.

行23,25,28是產生一條選單的線,做分隔.

行29是選單子節點.

行21是實際要加入的選單功能
x.add2(rs,1(x),"A",".產品組合單建立","edit.CmzBomItem",1,"edit_2",2,null);
"x" 的參數是節點的階層, 要設對, 從1開始
"A" 在傳統選單, 有快捷鍵作用
".產品組合單建立" 選單名稱, 單語系一定要以"."做開頭.
"edit.CmzBomItem" 指按下選單後要執行的程式名稱, 實際是 com.dasam.e3010001.client.edit.CmzBomItem.java
"edit_2" 是icon樣式,也可以自行加入

行39~42是重載執行, 主要用於修改原程式用.

行53~69是設定可以執行套件的權限, 以產品序號為識別.


E3/SDK有一些基本模組程式, 一般都是做
設計的底層, 我們會陸續以實際的程式做
說明.

例如:
單表編輯,
父子表編輯,
查詢視窗,
長時間處理,
報表模組,
...


這裡的程式設計主要以JavaSE為主,
雖然以SE做程式設計, 但可以在網路
上執行, 因為E3已有HTTP的通訊傳
送模組.

E3中的程式設計, 第一步是先安裝SDK
請看 E3/SDK安裝説明
再看原始碼 SystemDataCmz.java
這是整合選單的程式.

整合好後, 再看實作的程式類型, 單表編輯,
雙表編輯, 報表編輯.. 等, 再copy目前已
有相同的模組, 作修改. 以此類推, 以達成
需求的實踐.


 
討論區首頁 » 個人資料 e3Admin » 文章發表人是 e3Admin
前往:   

2011 DASAMX GROUP.    Powered by JForum 2.1.9©    建議使用Firefox瀏覽